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