Remote group flow fails in conntrack SNAT
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / ConntrackBasedSnatService.java
1 /*
2  * Copyright (c) 2017 Red Hat, Inc. 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 com.google.common.base.Optional;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.List;
14 import org.apache.commons.lang3.tuple.ImmutablePair;
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.InstructionInfo;
23 import org.opendaylight.genius.mdsalutil.MatchInfo;
24 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
25 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
26 import org.opendaylight.genius.mdsalutil.NWUtil;
27 import org.opendaylight.genius.mdsalutil.NwConstants;
28 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
29 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
30 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
31 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadMetadata;
32 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
33 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
34 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
35 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
36 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
37 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
38 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
39 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
40 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
41 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
42 import org.opendaylight.netvirt.natservice.ha.NatDataUtil;
43 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatFlags;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatRangePresent;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 public abstract class ConntrackBasedSnatService extends AbstractSnatService {
59     private static final Logger LOG = LoggerFactory.getLogger(ConntrackBasedSnatService.class);
60
61     protected static final int TRACKED_NEW_CT_STATE = 0x21;
62     protected static final int TRACKED_NEW_CT_MASK = 0x21;
63     protected static final int SNAT_CT_STATE = 0x40;
64     protected static final int SNAT_CT_STATE_MASK = 0x40;
65     protected static final int DNAT_CT_STATE = 0x80;
66     protected static final int DNAT_CT_STATE_MASK = 0x80;
67
68     public ConntrackBasedSnatService(DataBroker dataBroker, IMdsalApiManager mdsalManager, ItmRpcService itmManager,
69                                      IdManagerService idManager, NAPTSwitchSelector naptSwitchSelector,
70                                      OdlInterfaceRpcService odlInterfaceRpcService,
71                                      IInterfaceManager interfaceManager, IVpnFootprintService vpnFootprintService,
72                                      IFibManager fibManager, NatDataUtil natDataUtil,
73                                      DataTreeEventCallbackRegistrar eventCallbacks) {
74         super(dataBroker, mdsalManager, itmManager, odlInterfaceRpcService, idManager, naptSwitchSelector,
75                 interfaceManager, vpnFootprintService, fibManager, natDataUtil, eventCallbacks);
76     }
77
78     @Override
79     protected void addSnatSpecificEntriesForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
80         Routers routers, BigInteger dpnId) {
81         LOG.info("installSnatSpecificEntriesForNaptSwitch: called for router {}",
82             routers.getRouterName());
83         String routerName = routers.getRouterName();
84         Long routerId = NatUtil.getVpnId(confTx, routerName);
85         int elanId = NatUtil.getElanInstanceByName(confTx, routers.getNetworkId().getValue())
86             .getElanTag().intValue();
87         if (routerId == NatConstants.INVALID_ID) {
88             LOG.error("InvalidRouterId: unable to installSnatSpecificEntriesForNaptSwitch on dpn {}", dpnId);
89             return;
90         }
91         /* Install Outbound NAT entries */
92
93         addSnatMissEntryForPrimrySwch(confTx, dpnId, routerId, elanId);
94         addTerminatingServiceTblEntry(confTx, dpnId, routerId, elanId);
95
96         String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterName(confTx, routerName);
97         addOutboundTblTrackEntry(confTx, dpnId, routerId, extGwMacAddress);
98         for (ExternalIps externalIp : routers.getExternalIps()) {
99             if (!NWUtil.isIpv4Address(externalIp.getIpAddress())) {
100                 // In this class we handle only IPv4 use-cases.
101                 continue;
102             }
103             //The logic now handle only one external IP per router, others if present will be ignored.
104             long extSubnetId = NatUtil.getExternalSubnetVpnId(confTx, externalIp.getSubnetId());
105             addOutboundTblEntry(confTx, dpnId, routerId, externalIp.getIpAddress(), elanId, extGwMacAddress);
106             addNaptPfibFlow(confTx, routers, dpnId, routerId, extSubnetId);
107
108             //Install Inbound NAT entries
109             addInboundEntry(confTx, dpnId, routerId, externalIp.getIpAddress(), elanId, extSubnetId);
110             addNaptPfibEntry(confTx, dpnId, routerId);
111
112             String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp.getIpAddress());
113             Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(confTx, externalIp.getSubnetId());
114             if (externalSubnet.isPresent()) {
115                 String externalVpn =  externalIp.getSubnetId().getValue();
116                 String vpnRd = NatUtil.getVpnRd(confTx, externalVpn);
117                 vpnFootprintService.updateVpnToDpnMapping(dpnId, externalVpn, vpnRd, null /* interfaceName*/,
118                     new ImmutablePair<>(IpAddresses.IpAddressSource.ExternalFixedIP, fibExternalIp),
119                     true);
120             }
121             break;
122         }
123     }
124
125     @Override
126     protected void removeSnatSpecificEntriesForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
127         Routers routers, BigInteger dpnId) {
128         LOG.info("installSnatSpecificEntriesForNaptSwitch: called for router {}",
129             routers.getRouterName());
130         String routerName = routers.getRouterName();
131         Long routerId = NatUtil.getVpnId(confTx, routerName);
132         if (routerId == NatConstants.INVALID_ID) {
133             LOG.error("InvalidRouterId: unable to installSnatSpecificEntriesForNaptSwitch on dpn {}", dpnId);
134             return;
135         }
136         /* Remove Outbound NAT entries */
137
138         removeSnatMissEntryForPrimrySwch(confTx, dpnId, routerId);
139         removeTerminatingServiceTblEntry(confTx, dpnId, routerId);
140
141         removeOutboundTblTrackEntry(confTx, dpnId, routerId);
142         for (ExternalIps externalIp : routers.getExternalIps()) {
143             if (!NWUtil.isIpv4Address(externalIp.getIpAddress())) {
144                 // In this class we handle only IPv4 use-cases.
145                 continue;
146             }
147             //The logic now handle only one external IP per router, others if present will be ignored.
148             removeOutboundTblEntry(confTx, dpnId, routerId);
149             removeNaptPfibFlow(confTx, routers, dpnId, routerId);
150
151             //Install Inbound NAT entries
152             removeInboundEntry(confTx, dpnId, routerId);
153             removeNaptPfibEntry(confTx, dpnId, routerId);
154
155             String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp.getIpAddress());
156             Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(confTx, externalIp.getSubnetId());
157             if (externalSubnet.isPresent()) {
158                 String externalVpn =  externalIp.getSubnetId().getValue();
159                 String vpnRd = NatUtil.getVpnRd(confTx, externalVpn);
160                 vpnFootprintService.updateVpnToDpnMapping(dpnId, externalVpn, vpnRd, null /* interfaceName*/,
161                     new ImmutablePair<>(IpAddresses.IpAddressSource.ExternalFixedIP, fibExternalIp),
162                     false);
163             }
164             break;
165         }
166     }
167
168     @Override
169     protected void addSnatSpecificEntriesForNonNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
170         Routers routers, BigInteger dpnId) {
171         // Nothing to to do here
172     }
173
174     @Override
175     protected void removeSnatSpecificEntriesForNonNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
176         Routers routers, BigInteger dpnId) {
177         // Nothing to to do here
178     }
179
180     protected void addSnatMissEntryForPrimrySwch(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId,
181         Long routerId, int elanId) {
182         LOG.info("installSnatSpecificEntriesForNaptSwitch : called for the primary NAPT switch dpnId {}", dpnId);
183         List<MatchInfo> matches = new ArrayList<>();
184         matches.add(MatchEthernetType.IPV4);
185         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
186         List<InstructionInfo> instructions = new ArrayList<>();
187         List<ActionInfo> actionsInfos = new ArrayList<>();
188         List<NxCtAction> ctActionsList = new ArrayList<>();
189         NxCtAction nxCtAction = new ActionNxConntrack.NxNat(0, 0, 0,null, null,0, 0);
190         ctActionsList.add(nxCtAction);
191         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(0, 0, elanId,
192                 NwConstants.OUTBOUND_NAPT_TABLE,ctActionsList);
193
194         actionsInfos.add(actionNxConntrack);
195         instructions.add(new InstructionApplyActions(actionsInfos));
196
197         String flowRef = getFlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
198         addFlow(confTx, dpnId, NwConstants.PSNAT_TABLE, flowRef, NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
199                 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
200     }
201
202     protected void removeSnatMissEntryForPrimrySwch(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
203         Long routerId) {
204         LOG.info("installSnatSpecificEntriesForNaptSwitch : called for the primary NAPT switch dpnId {}", dpnId);
205
206         String flowRef = getFlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
207         removeFlow(confTx, dpnId, NwConstants.PSNAT_TABLE, flowRef);
208     }
209
210     protected void addTerminatingServiceTblEntry(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId,
211         Long routerId, int elanId) {
212         LOG.info("installTerminatingServiceTblEntry : creating entry for Terminating Service Table "
213                 + "for switch {}, routerId {}", dpnId, routerId);
214         List<MatchInfo> matches = new ArrayList<>();
215         matches.add(MatchEthernetType.IPV4);
216         matches.add(new MatchTunnelId(BigInteger.valueOf(routerId)));
217
218         List<ActionInfo> actionsInfos = new ArrayList<>();
219         List<NxCtAction> ctActionsList = new ArrayList<>();
220         NxCtAction nxCtAction = new ActionNxConntrack.NxNat(0, 0, 0,null, null,0, 0);
221         ctActionsList.add(nxCtAction);
222         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(0, 0, elanId, NwConstants
223                 .OUTBOUND_NAPT_TABLE,ctActionsList);
224         ActionNxLoadMetadata actionLoadMeta = new ActionNxLoadMetadata(MetaDataUtil
225                 .getVpnIdMetadata(routerId), LOAD_START, LOAD_END);
226         actionsInfos.add(actionLoadMeta);
227         actionsInfos.add(actionNxConntrack);
228         List<InstructionInfo> instructions = new ArrayList<>();
229         instructions.add(new InstructionApplyActions(actionsInfos));
230         String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
231         addFlow(confTx, dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef, NatConstants.DEFAULT_TS_FLOW_PRIORITY,
232             flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
233     }
234
235     protected void removeTerminatingServiceTblEntry(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
236         Long routerId) {
237         LOG.info("installTerminatingServiceTblEntry : creating entry for Terminating Service Table "
238             + "for switch {}, routerId {}", dpnId, routerId);
239
240         String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
241         removeFlow(confTx, dpnId,  NwConstants.INTERNAL_TUNNEL_TABLE, flowRef);
242     }
243
244     protected void addOutboundTblTrackEntry(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId,
245         Long routerId, String extGwMacAddress) {
246         LOG.info("createOutboundTblTrackEntry : called for switch {}, routerId {}", dpnId, routerId);
247         List<MatchInfoBase> matches = new ArrayList<>();
248         matches.add(MatchEthernetType.IPV4);
249         matches.add(new NxMatchCtState(SNAT_CT_STATE, SNAT_CT_STATE_MASK));
250         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
251         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
252         listActionInfo.add(new ActionSetFieldEthernetSource(new MacAddress(extGwMacAddress)));
253         ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
254         listActionInfo.add(new ActionNxResubmit(NwConstants.NAPT_PFIB_TABLE));
255         instructionInfo.add(new InstructionApplyActions(listActionInfo));
256
257         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId) + "trkest";
258         addFlow(confTx, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, NatConstants.SNAT_TRK_FLOW_PRIORITY, flowRef,
259                 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
260     }
261
262     protected void removeOutboundTblTrackEntry(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
263         Long routerId) {
264         LOG.info("createOutboundTblTrackEntry : called for switch {}, routerId {}", dpnId, routerId);
265
266         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId) + "trkest";
267         removeFlow(confTx, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef);
268     }
269
270     protected void addOutboundTblEntry(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId, long routerId,
271         String externalIp, int elanId, String extGwMacAddress) {
272         LOG.info("createOutboundTblEntry : dpId {} and routerId {}", dpnId, routerId);
273         List<MatchInfoBase> matches = new ArrayList<>();
274         matches.add(MatchEthernetType.IPV4);
275         matches.add(new NxMatchCtState(TRACKED_NEW_CT_STATE, TRACKED_NEW_CT_MASK));
276         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
277         List<ActionInfo> actionsInfos = new ArrayList<>();
278         actionsInfos.add(new ActionSetFieldEthernetSource(new MacAddress(extGwMacAddress)));
279         List<NxCtAction> ctActionsListCommit = new ArrayList<>();
280         int rangePresent = NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue();
281         int flags = NxActionNatFlags.NXNATFSRC.getIntValue();
282         NxCtAction nxCtActionCommit = new ActionNxConntrack.NxNat(0, flags, rangePresent,
283             new IpPrefixOrAddress(externalIp.toCharArray()).getIpAddress(),
284             null,0, 0);
285         ctActionsListCommit.add(nxCtActionCommit);
286         int ctCommitFlag = 1;
287         ActionNxConntrack actionNxConntrackSubmit = new ActionNxConntrack(ctCommitFlag, 0, elanId,
288             NwConstants.NAPT_PFIB_TABLE, ctActionsListCommit);
289         actionsInfos.add(actionNxConntrackSubmit);
290         List<InstructionInfo> instructions = new ArrayList<>();
291         instructions.add(new InstructionApplyActions(actionsInfos));
292         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
293         addFlow(confTx, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,  NatConstants.SNAT_NEW_FLOW_PRIORITY,
294             flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
295     }
296
297     protected void removeOutboundTblEntry(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
298         long routerId) {
299         LOG.info("createOutboundTblEntry : dpId {} and routerId {}", dpnId, routerId);
300         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
301         removeFlow(confTx, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef);
302     }
303
304     protected void addNaptPfibFlow(TypedReadWriteTransaction<Configuration> confTx, Routers routers, BigInteger dpnId,
305         long routerId, long extSubnetId) {
306         Long extNetId = NatUtil.getVpnId(confTx, routers.getNetworkId().getValue());
307         LOG.info("installNaptPfibFlow : dpId {}, extNetId {}", dpnId, extNetId);
308         List<MatchInfoBase> matches = new ArrayList<>();
309         matches.add(MatchEthernetType.IPV4);
310         matches.add(new NxMatchCtState(SNAT_CT_STATE, SNAT_CT_STATE_MASK));
311         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
312         List<ActionInfo> listActionInfo = new ArrayList<>();
313         if (extSubnetId == NatConstants.INVALID_ID) {
314             LOG.error("installNaptPfibFlow : external subnet id is invalid.");
315             return;
316         }
317         ActionNxLoadMetadata actionLoadMeta = new ActionNxLoadMetadata(MetaDataUtil
318             .getVpnIdMetadata(extSubnetId), LOAD_START, LOAD_END);
319         listActionInfo.add(actionLoadMeta);
320         ArrayList<InstructionInfo> instructions = new ArrayList<>();
321         listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
322         listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
323         instructions.add(new InstructionApplyActions(listActionInfo));
324         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
325         flowRef = flowRef + "OUTBOUND";
326         addFlow(confTx, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef, NatConstants.SNAT_TRK_FLOW_PRIORITY,
327             flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
328     }
329
330     protected void removeNaptPfibFlow(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
331         BigInteger dpnId, long routerId) {
332         Long extNetId = NatUtil.getVpnId(confTx, routers.getNetworkId().getValue());
333         LOG.info("installNaptPfibFlow : dpId {}, extNetId {}", dpnId, extNetId);
334         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId) + "OUTBOUND";
335         removeFlow(confTx, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef);
336     }
337
338     protected void addInboundEntry(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId, long routerId,
339         String externalIp, int elanId, long extSubnetId) {
340         LOG.info("installInboundEntry : dpId {} and routerId {}", dpnId, routerId);
341         List<MatchInfoBase> matches = new ArrayList<>();
342         matches.add(MatchEthernetType.IPV4);
343         matches.add(new MatchIpv4Destination(externalIp,"32"));
344         if (extSubnetId == NatConstants.INVALID_ID) {
345             LOG.error("installInboundEntry : external subnet id is invalid.");
346             return;
347         }
348         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extSubnetId),
349             MetaDataUtil.METADATA_MASK_VRFID));
350         List<ActionInfo> actionsInfos = new ArrayList<>();
351         List<NxCtAction> ctActionsList = new ArrayList<>();
352         NxCtAction nxCtAction = new ActionNxConntrack.NxNat(0, 0, 0,null, null,0, 0);
353         ActionNxLoadMetadata actionLoadMeta = new ActionNxLoadMetadata(MetaDataUtil
354             .getVpnIdMetadata(routerId), LOAD_START, LOAD_END);
355         actionsInfos.add(actionLoadMeta);
356         ctActionsList.add(nxCtAction);
357         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(0, 0, elanId, NwConstants
358             .NAPT_PFIB_TABLE,ctActionsList);
359
360         actionsInfos.add(actionNxConntrack);
361         List<InstructionInfo> instructions = new ArrayList<>();
362         instructions.add(new InstructionApplyActions(actionsInfos));
363         String flowRef = getFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId);
364         flowRef = flowRef + "OUTBOUND";
365         addFlow(confTx, dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef, NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef,
366             NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
367     }
368
369     protected void removeInboundEntry(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
370         long routerId) {
371         LOG.info("installInboundEntry : dpId {} and routerId {}", dpnId, routerId);
372
373         String flowRef = getFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId) + "OUTBOUND";
374         removeFlow(confTx, dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef);
375     }
376
377     protected void addNaptPfibEntry(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId, long routerId) {
378         LOG.info("installNaptPfibEntry : called for dpnId {} and routerId {} ", dpnId, routerId);
379         List<MatchInfoBase> matches = new ArrayList<>();
380         matches.add(MatchEthernetType.IPV4);
381         matches.add(new NxMatchCtState(DNAT_CT_STATE, DNAT_CT_STATE_MASK));
382         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
383
384         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
385         ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
386         listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
387         listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
388         instructionInfo.add(new InstructionApplyActions(listActionInfo));
389
390         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId) + "INBOUND";
391         addFlow(confTx, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef, NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
392             NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
393     }
394
395     protected void removeNaptPfibEntry(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
396         long routerId) {
397         LOG.info("installNaptPfibEntry : called for dpnId {} and routerId {} ", dpnId, routerId);
398         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId) + "INBOUND";
399         removeFlow(confTx, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef);
400     }
401 }