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