Remove GENIUS UTIL references in NatService/Qos Modules
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / VxlanGreConntrackBasedSnatService.java
1 /*
2  * Copyright © 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.natservice.internal;
9
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.concurrent.ExecutionException;
15 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
16 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
17 import org.opendaylight.genius.mdsalutil.ActionInfo;
18 import org.opendaylight.genius.mdsalutil.BucketInfo;
19 import org.opendaylight.genius.mdsalutil.GroupEntity;
20 import org.opendaylight.genius.mdsalutil.InstructionInfo;
21 import org.opendaylight.genius.mdsalutil.MDSALUtil;
22 import org.opendaylight.genius.mdsalutil.MatchInfo;
23 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
24 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
25 import org.opendaylight.genius.mdsalutil.NwConstants;
26 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
27 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
28 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
29 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
30 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
31 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldMeta;
32 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
33 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
34 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
35 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
36 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
37 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
38 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
39 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
40 import org.opendaylight.mdsal.binding.api.DataBroker;
41 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
42 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
43 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
44 import org.opendaylight.netvirt.elanmanager.api.IElanService;
45 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
46 import org.opendaylight.netvirt.natservice.ha.NatDataUtil;
47 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIpsKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddressBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatFlags;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatRangePresent;
60 import org.opendaylight.yangtools.yang.common.Uint32;
61 import org.opendaylight.yangtools.yang.common.Uint64;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService {
66
67     private static final Logger LOG = LoggerFactory.getLogger(VxlanGreConntrackBasedSnatService.class);
68     private final ExternalRoutersListener externalRouterListener;
69     private final IElanService elanManager;
70     private final NatOverVxlanUtil natOverVxlanUtil;
71
72     public VxlanGreConntrackBasedSnatService(DataBroker dataBroker, IMdsalApiManager mdsalManager,
73                                              ItmRpcService itmManager, OdlInterfaceRpcService odlInterfaceRpcService,
74                                              IdManagerService idManager, NAPTSwitchSelector naptSwitchSelector,
75                                              ExternalRoutersListener externalRouterListener, IElanService elanManager,
76                                              IInterfaceManager interfaceManager,
77                                              IVpnFootprintService vpnFootprintService,
78                                              IFibManager fibManager, NatDataUtil natDataUtil,
79                                              DataTreeEventCallbackRegistrar eventCallbacks,
80                                              NatOverVxlanUtil natOverVxlanUtil) {
81         super(dataBroker, mdsalManager, itmManager, idManager, naptSwitchSelector, odlInterfaceRpcService,
82                 interfaceManager, vpnFootprintService, fibManager, natDataUtil, eventCallbacks);
83         this.externalRouterListener = externalRouterListener;
84         this.elanManager = elanManager;
85         this.natOverVxlanUtil = natOverVxlanUtil;
86     }
87
88     @Override
89     public boolean addSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
90         Uint64 primarySwitchId) {
91         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(confTx, routers.getNetworkId());
92         LOG.debug("VxlanGreConntrackBasedSnatService: handleSnatAllSwitch ProviderTypes {}", extNwProviderType);
93         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
94             LOG.debug("handleSnatAllSwitch : Skip FLAT/VLAN provider networks.");
95             return true;
96         }
97         return super.addSnatAllSwitch(confTx, routers, primarySwitchId);
98     }
99
100     @Override
101     public boolean removeSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
102             Uint64 primarySwitchId) throws ExecutionException, InterruptedException {
103         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(confTx, routers.getNetworkId());
104         LOG.debug("VxlanGreConntrackBasedSnatService: handleSnatAllSwitch ProviderTypes {}", extNwProviderType);
105         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
106             LOG.debug("handleSnatAllSwitch : Skip FLAT/VLAN provider networks.");
107             return true;
108         }
109         return super.removeSnatAllSwitch(confTx, routers, primarySwitchId);
110     }
111
112     public boolean addCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
113             Uint64 primarySwitchId) {
114         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
115         LOG.debug("VxlanGreConntrackBasedSnatService: handleCentralizedRouterAllSwitch ProviderTypes {}",
116                 extNwProviderType);
117         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
118             LOG.debug("handleCentralizedRouterAllSwitch : Skip FLAT/VLAN provider networks.");
119             return true;
120         }
121         return super.addCentralizedRouterAllSwitch(confTx, routers, primarySwitchId);
122     }
123
124     public boolean removeCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
125             Uint64 primarySwitchId)  throws ExecutionException, InterruptedException {
126         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
127         LOG.debug("VxlanGreConntrackBasedSnatService: handleCentralizedRouterAllSwitch ProviderTypes {}",
128                 extNwProviderType);
129         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
130             LOG.debug("handleCentralizedRouterAllSwitch : Skip FLAT/VLAN provider networks.");
131             return true;
132         }
133         return super.removeCentralizedRouterAllSwitch(confTx, routers, primarySwitchId);
134     }
135
136     public boolean addCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
137             Uint64 primarySwitchId, Uint64 dpnId) {
138         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
139         LOG.debug("VxlanGreConntrackBasedSnatService: handleCentralizedRouter ProviderTypes {}", extNwProviderType);
140         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
141             LOG.debug("handleCentralizedRouter : Skip FLAT/VLAN provider networks.");
142             return true;
143         }
144         return super.addCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
145     }
146
147     public boolean removeCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
148             Uint64 primarySwitchId, Uint64 dpnId)  throws ExecutionException, InterruptedException {
149         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
150         LOG.debug("VxlanGreConntrackBasedSnatService: handleCentralizedRouter ProviderTypes {}", extNwProviderType);
151         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
152             LOG.debug("handleCentralizedRouter : Skip FLAT/VLAN provider networks.");
153             return true;
154         }
155         return super.removeCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
156     }
157
158     @Override
159     public boolean addSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
160         Uint64 primarySwitchId, Uint64 dpnId) {
161         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(confTx, routers.getNetworkId());
162         LOG.debug("VxlanGreConntrackBasedSnatService: handleSnat ProviderTypes {}", extNwProviderType);
163         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
164             LOG.debug("handleSnat : Skip FLAT/VLAN provider networks.");
165             return true;
166         }
167         return super.addSnat(confTx, routers, primarySwitchId, dpnId);
168     }
169
170     @Override
171     public boolean removeSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
172             Uint64 primarySwitchId, Uint64 dpnId) throws ExecutionException, InterruptedException {
173         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(confTx, routers.getNetworkId());
174         LOG.debug("VxlanGreConntrackBasedSnatService: handleSnat ProviderTypes {}", extNwProviderType);
175         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
176             LOG.debug("handleSnat : Skip FLAT/VLAN provider networks.");
177             return true;
178         }
179         return super.removeSnat(confTx, routers, primarySwitchId, dpnId);
180     }
181
182     @Override
183     protected void addSnatSpecificEntriesForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
184         Uint64 dpnId) {
185
186         LOG.info("installSnatSpecificEntriesForNaptSwitch for router {}",
187             routers.getRouterName());
188         String routerName = routers.getRouterName();
189         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
190         int elanId = NatUtil.getElanInstanceByName(routers.getNetworkId().getValue(), dataBroker)
191             .getElanTag().intValue();
192         /* Install Outbound NAT entries */
193
194         addSnatMissEntryForPrimrySwch(confTx, dpnId, routerId, elanId);
195         addTerminatingServiceTblEntryForVxlanGre(confTx, dpnId, routerName, routerId, elanId);
196         //Long extNetVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
197         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, routers.getNetworkId());
198         if (vpnUuid == null) {
199             LOG.error("installSnatSpecificEntriesForNaptSwitch: Unable to retrieve external vpn_id for "
200                 + "external network {} with routerId {}", routers.getNetworkId(), routerId);
201             return;
202         }
203         Uint32 extNetVpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
204         LOG.info("installSnatSpecificEntriesForNaptSwitch: external network vpn_id {} for router {}",
205             extNetVpnId, routers.getRouterName());
206         Map<ExternalIpsKey, ExternalIps> keyExternalIpsMap = routers.nonnullExternalIps();
207         addOutboundTblTrackEntryForVxlanGre(confTx, dpnId, routerId, extNetVpnId);
208         addOutboundTblEntryForVxlanGre(confTx, dpnId, routerId, extNetVpnId,
209                 new ArrayList<ExternalIps>(keyExternalIpsMap.values()), elanId);
210         addNaptPfibFlowForVxlanGre(confTx, routers, dpnId, extNetVpnId);
211         addNaptPfibEntry(confTx, dpnId, routerId);
212
213         //Install Inbound NAT entries
214         addInboundEntryForVxlanGre(confTx, dpnId, routerId, extNetVpnId,
215                 new ArrayList<ExternalIps>(keyExternalIpsMap.values()), elanId);
216         if (keyExternalIpsMap.isEmpty()) {
217             LOG.error("installSnatSpecificEntriesForNaptSwitch: No externalIP present for router {}",
218                 routerName);
219             return;
220         }
221         //The logic now handle only one external IP per router, others if present will be ignored.
222         String externalIp = NatUtil.validateAndAddNetworkMask(
223                 new ArrayList<ExternalIps>(keyExternalIpsMap.values()).get(0).getIpAddress());
224         externalRouterListener.handleSnatReverseTraffic(confTx, dpnId, routers, routerId, routerName, externalIp);
225     }
226
227     @Override
228     protected void removeSnatSpecificEntriesForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
229             Routers routers, Uint64 dpnId) throws ExecutionException, InterruptedException {
230
231         LOG.info("installSnatSpecificEntriesForNaptSwitch for router {}",
232             routers.getRouterName());
233         String routerName = routers.getRouterName();
234         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
235
236         /* Remove Outbound NAT entries */
237         removeSnatMissEntryForPrimrySwch(confTx, dpnId, routerId);
238         removeTerminatingServiceTblEntryForVxlanGre(confTx, dpnId, routerId);
239         //Long extNetVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
240         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, routers.getNetworkId());
241         if (vpnUuid == null) {
242             LOG.error("installSnatSpecificEntriesForNaptSwitch: Unable to retrieve external vpn_id for "
243                 + "external network {} with routerId {}", routers.getNetworkId(), routerId);
244             return;
245         }
246         Uint32 extNetVpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
247         LOG.info("installSnatSpecificEntriesForNaptSwitch: external network vpn_id {} for router {}",
248             extNetVpnId, routers.getRouterName());
249         Map<ExternalIpsKey, ExternalIps> keyExternalIpsMap = routers.nonnullExternalIps();
250         removeOutboundTblTrackEntryForVxlanGre(confTx, dpnId, routerId);
251         removeOutboundTblEntryForVxlanGre(confTx, dpnId, routerId,
252                 new ArrayList<ExternalIps>(keyExternalIpsMap.values()));
253         removeNaptPfibFlowForVxlanGre(confTx, routers, dpnId, extNetVpnId);
254         removeNaptPfibEntry(confTx, dpnId, routerId);
255
256         //Install Inbound NAT entries
257         removeInboundEntryForVxlanGre(confTx, dpnId, routerId, new ArrayList<ExternalIps>(keyExternalIpsMap.values()));
258         if (keyExternalIpsMap.isEmpty()) {
259             LOG.error("installSnatSpecificEntriesForNaptSwitch: No externalIP present for router {}",
260                 routerName);
261             return;
262         }
263         //The logic now handle only one external IP per router, others if present will be ignored.
264         String externalIp = NatUtil.validateAndAddNetworkMask(
265                 new ArrayList<ExternalIps>(keyExternalIpsMap.values()).get(0).getIpAddress());
266         externalRouterListener.clearFibTsAndReverseTraffic(dpnId, routerId, routers.getNetworkId(),
267             Collections.singletonList(externalIp), null, routers.getExtGwMacAddress(), confTx);
268     }
269
270     protected void addOutboundTblTrackEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, Uint64 dpnId,
271                                                        Uint32 routerId, Uint32 extNetVpnId) {
272         LOG.info("createOutboundTblTrackEntryForVxlanGre: Install Outbound tracking table flow on dpId {} for "
273                 + "routerId {}", dpnId, routerId);
274         List<MatchInfoBase> matches = new ArrayList<>();
275         matches.add(MatchEthernetType.IPV4);
276         matches.add(new NxMatchCtState(SNAT_CT_STATE, SNAT_CT_STATE_MASK));
277         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
278                 MetaDataUtil.METADATA_MASK_VRFID));
279
280         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
281         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(
282                 MetaDataUtil.getVpnIdMetadata(extNetVpnId.longValue()));
283         listActionInfo.add(actionSetFieldMeta);
284         ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
285         listActionInfo.add(new ActionNxResubmit(NwConstants.NAPT_PFIB_TABLE));
286         instructionInfo.add(new InstructionApplyActions(listActionInfo));
287
288         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId) + "trkest";
289         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
290                 NatConstants.SNAT_TRK_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
291
292     }
293
294     protected void removeOutboundTblTrackEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx,
295             Uint64 dpnId, Uint32 routerId) throws ExecutionException, InterruptedException {
296         LOG.info("createOutboundTblTrackEntryForVxlanGre: Install Outbound tracking table flow on dpId {} for "
297             + "routerId {}", dpnId, routerId);
298
299         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId) + "trkest";
300         NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef);
301
302     }
303
304     protected void addOutboundTblEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, Uint64 dpnId,
305                                                   Uint32 routerId, Uint32 extNetVpnId, List<ExternalIps> externalIps,
306                                                   int elanId) {
307         LOG.info("createOutboundTblEntryForVxlanGre: Install Outbound table flow on dpId {} for routerId {}", dpnId,
308                 routerId);
309         List<MatchInfoBase> matches = new ArrayList<>();
310         matches.add(MatchEthernetType.IPV4);
311         matches.add(new NxMatchCtState(TRACKED_NEW_CT_STATE, TRACKED_NEW_CT_MASK));
312         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
313                 MetaDataUtil.METADATA_MASK_VRFID));
314         if (externalIps.isEmpty()) {
315             LOG.error("createOutboundTblEntryForVxlanGre: No externalIP present for routerId {}",
316                     routerId);
317             return;
318         }
319         //The logic now handle only one external IP per router, others if present will be ignored.
320         String externalIp = externalIps.get(0).getIpAddress();
321         List<ActionInfo> actionsInfos = new ArrayList<>();
322         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
323                 .getVpnIdMetadata(extNetVpnId.longValue()));
324         actionsInfos.add(actionSetFieldMeta);
325         List<ActionNxConntrack.NxCtAction> ctActionsListCommit = new ArrayList<>();
326         int rangePresent = NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue();
327         int flags = NxActionNatFlags.NXNATFSRC.getIntValue();
328         ActionNxConntrack.NxCtAction nxCtActionCommit = new ActionNxConntrack.NxNat(0, flags, rangePresent,
329             IpPrefixOrAddressBuilder.getDefaultInstance(externalIp).getIpAddress(), null,0, 0);
330         ctActionsListCommit.add(nxCtActionCommit);
331         int ctCommitFlag = 1;
332         ActionNxConntrack actionNxConntrackSubmit = new ActionNxConntrack(ctCommitFlag, 0, elanId,
333                 NwConstants.NAPT_PFIB_TABLE, ctActionsListCommit);
334         actionsInfos.add(actionNxConntrackSubmit);
335         List<InstructionInfo> instructions = new ArrayList<>();
336         instructions.add(new InstructionApplyActions(actionsInfos));
337         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
338         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
339                 NatConstants.SNAT_NEW_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
340     }
341
342     protected void removeOutboundTblEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, Uint64 dpnId,
343                                                      Uint32 routerId, List<ExternalIps> externalIps)
344             throws ExecutionException, InterruptedException {
345         LOG.info("createOutboundTblEntryForVxlanGre: Install Outbound table flow on dpId {} for routerId {}", dpnId,
346             routerId);
347         if (externalIps.isEmpty()) {
348             LOG.error("createOutboundTblEntryForVxlanGre: No externalIP present for routerId {}",
349                 routerId);
350             return;
351         }
352         //The logic now handle only one external IP per router, others if present will be ignored.
353         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
354         NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef);
355     }
356
357     protected void addNaptPfibFlowForVxlanGre(TypedWriteTransaction<Configuration> confTx, Routers routers,
358         Uint64 dpnId, Uint32 extNetVpnId) {
359         LOG.info("installNaptPfibFlowForVxlanGre: Install Napt preFibFlow on dpId {} with matching extNetVpnId {} "
360                 + "for router {}", dpnId, extNetVpnId, routers.getRouterName());
361         List<MatchInfoBase> matches = new ArrayList<>();
362         matches.add(MatchEthernetType.IPV4);
363         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extNetVpnId.longValue()),
364                 MetaDataUtil.METADATA_MASK_VRFID));
365         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
366         ArrayList<InstructionInfo> instructions = new ArrayList<>();
367         listActionInfo.add(new ActionNxLoadInPort(Uint64.ZERO));
368         listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
369         instructions.add(new InstructionApplyActions(listActionInfo));
370         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, extNetVpnId);
371         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef,
372                 NatConstants.SNAT_TRK_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
373     }
374
375     protected void removeNaptPfibFlowForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
376             Uint64 dpnId, Uint32 extNetVpnId) throws ExecutionException, InterruptedException {
377         LOG.info("installNaptPfibFlowForVxlanGre: Install Napt preFibFlow on dpId {} with matching extNetVpnId {} "
378             + "for router {}", dpnId, extNetVpnId, routers.getRouterName());
379         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, extNetVpnId);
380         NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef);
381     }
382
383     protected void addInboundEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, Uint64 dpnId,
384                                               Uint32 routerId, Uint32 extNeVpnId, List<ExternalIps> externalIps,
385                                               int elanId) {
386         LOG.info("installInboundEntryForVxlanGre:  Install Inbound table entry on dpId {} for routerId {}",
387                 dpnId, routerId);
388         List<MatchInfoBase> matches = new ArrayList<>();
389         matches.add(MatchEthernetType.IPV4);
390         if (externalIps.isEmpty()) {
391             LOG.error("installInboundEntryForVxlanGre : createInboundTblEntry no externalIP present for routerId {}",
392                     routerId);
393             return;
394         }
395         String externalIp = externalIps.get(0).getIpAddress();
396         matches.add(new MatchIpv4Destination(externalIp,"32"));
397         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extNeVpnId.longValue()),
398                 MetaDataUtil.METADATA_MASK_VRFID));
399         List<ActionInfo> actionsInfos = new ArrayList<>();
400         List<ActionNxConntrack.NxCtAction> ctActionsList = new ArrayList<>();
401         ActionNxConntrack.NxCtAction nxCtAction = new ActionNxConntrack.NxNat(0, 0, 0,null, null,0, 0);
402         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
403                 .getVpnIdMetadata(routerId.longValue()));
404         actionsInfos.add(actionSetFieldMeta);
405         ctActionsList.add(nxCtAction);
406         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(0, 0, elanId, NwConstants
407                 .NAPT_PFIB_TABLE,ctActionsList);
408
409         actionsInfos.add(actionNxConntrack);
410         List<InstructionInfo> instructions = new ArrayList<>();
411         instructions.add(new InstructionApplyActions(actionsInfos));
412         String flowRef = getFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId);
413         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef,
414                 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
415     }
416
417     protected void removeInboundEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, Uint64 dpnId,
418                                                  Uint32 routerId, List<ExternalIps> externalIps)
419             throws ExecutionException, InterruptedException {
420         LOG.info("removeInboundEntryForVxlanGre: remove Inbound table entry on dpId {} for routerId {}",
421             dpnId, routerId);
422         if (externalIps.isEmpty()) {
423             LOG.error("removeInboundEntryForVxlanGre : createInboundTblEntry no externalIP present for routerId {}",
424                 routerId);
425             return;
426         }
427
428         String flowRef = getFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId);
429         NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef);
430     }
431
432     protected void addTerminatingServiceTblEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx,
433         Uint64 dpnId, String routerName, Uint32 routerId, int elanId) {
434         LOG.info("installTerminatingServiceTblEntryForVxlanGre : creating entry for"
435                 + "Terminating Service Table for switch {}, routerId {}", dpnId, routerId);
436         List<MatchInfo> matches = new ArrayList<>();
437         matches.add(MatchEthernetType.IPV4);
438
439         Uint64 tunnelId = Uint64.valueOf(routerId);
440         if (elanManager.isOpenStackVniSemanticsEnforced()) {
441             tunnelId = natOverVxlanUtil.getRouterVni(routerName, routerId);
442         }
443         matches.add(new MatchTunnelId(tunnelId));
444
445         List<ActionInfo> actionsInfos = new ArrayList<>();
446         List<NxCtAction> ctActionsList = new ArrayList<>();
447         NxCtAction nxCtAction = new ActionNxConntrack.NxNat(0, 0, 0,null, null,0, 0);
448         ctActionsList.add(nxCtAction);
449         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(0, 0, elanId, NwConstants
450                 .OUTBOUND_NAPT_TABLE,ctActionsList);
451         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
452                 .getVpnIdMetadata(routerId.longValue()));
453         actionsInfos.add(actionSetFieldMeta);
454         actionsInfos.add(actionNxConntrack);
455         List<InstructionInfo> instructions = new ArrayList<>();
456         instructions.add(new InstructionApplyActions(actionsInfos));
457         String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
458         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
459                 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
460
461     }
462
463     protected void removeTerminatingServiceTblEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx,
464             Uint64 dpnId, Uint32 routerId) throws ExecutionException, InterruptedException {
465         LOG.info("removeTerminatingServiceTblEntryForVxlanGre : removing entry for"
466             + "Terminating Service Table for switch {}, routerId {}", dpnId, routerId);
467
468         String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
469         NatUtil.removeFlow(confTx, mdsalManager, dpnId,  NwConstants.INTERNAL_TUNNEL_TABLE, flowRef);
470
471     }
472
473     @Override
474     protected void addSnatMissEntry(TypedReadWriteTransaction<Configuration> confTx, Uint64 dpnId, Uint32 routerId,
475         String routerName, Uint64 primarySwitchId) {
476         LOG.debug("addSnatMissEntry : Installing SNAT miss entry in switch {}", dpnId);
477         List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
478         String ifNamePrimary = NatUtil.getTunnelInterfaceName(dpnId, primarySwitchId, itmManager);
479         List<BucketInfo> listBucketInfo = new ArrayList<>();
480         if (ifNamePrimary != null) {
481             LOG.debug("addSnatMissEntry : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
482             listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
483                     interfaceManager, ifNamePrimary, routerId, true);
484         }
485         BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
486         listBucketInfo.add(0, bucketPrimary);
487         LOG.debug("addSnatMissEntry : addSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId,
488                 listBucketInfo.get(0));
489         // Install the select group
490         Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME, getGroupIdKey(routerName));
491         if (groupId != NatConstants.INVALID_ID) {
492             GroupEntity groupEntity = MDSALUtil
493                 .buildGroupEntity(dpnId, groupId.longValue(), routerName, GroupTypes.GroupAll,
494                     listBucketInfo);
495             LOG.debug("addSnatMissEntry : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
496             mdsalManager.addGroup(confTx, groupEntity);
497             // Install miss entry pointing to group
498             LOG.debug(
499                 "addSnatMissEntry : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}",
500                 dpnId, routerName, groupId);
501             List<MatchInfo> matches = new ArrayList<>();
502             matches.add(new MatchEthernetType(0x0800L));
503             matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
504                 MetaDataUtil.METADATA_MASK_VRFID));
505
506             List<ActionInfo> actionsInfo = new ArrayList<>();
507
508             Uint64 tunnelId = Uint64.valueOf(routerId);
509             if (elanManager.isOpenStackVniSemanticsEnforced()) {
510                 tunnelId = natOverVxlanUtil.getRouterVni(routerName, routerId);
511             }
512
513             actionsInfo.add(new ActionSetFieldTunnelId(tunnelId));
514             LOG.debug("addSnatMissEntry : Setting the tunnel to the list of action infos {}",
515                 actionsInfo);
516             actionsInfo.add(new ActionGroup(groupId.longValue()));
517             List<InstructionInfo> instructions = new ArrayList<>();
518             instructions.add(new InstructionApplyActions(actionsInfo));
519             String flowRef = getFlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
520             NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef,
521                 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE,
522                 matches,
523                 instructions);
524         } else {
525             LOG.error("installSnatMissEntry: Unable to get groupId for router:{}", routerName);
526         }
527     }
528
529     @Override
530     protected void removeSnatMissEntry(TypedReadWriteTransaction<Configuration> confTx, Uint64 dpnId,
531                                        Uint32 routerId, String routerName)
532             throws ExecutionException, InterruptedException {
533         LOG.debug("installSnatMissEntry : Removing SNAT miss entry in switch {}", dpnId);
534
535         String flowRef = getFlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
536         NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef);
537     }
538
539 }