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