Do not use char[]-based union access
[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 org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
16 import org.opendaylight.genius.infra.Datastore.Configuration;
17 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
18 import org.opendaylight.genius.infra.TypedWriteTransaction;
19 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
20 import org.opendaylight.genius.mdsalutil.ActionInfo;
21 import org.opendaylight.genius.mdsalutil.BucketInfo;
22 import org.opendaylight.genius.mdsalutil.GroupEntity;
23 import org.opendaylight.genius.mdsalutil.InstructionInfo;
24 import org.opendaylight.genius.mdsalutil.MDSALUtil;
25 import org.opendaylight.genius.mdsalutil.MatchInfo;
26 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
27 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
28 import org.opendaylight.genius.mdsalutil.NwConstants;
29 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
30 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
31 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
32 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
33 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
34 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldMeta;
35 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
36 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
37 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
38 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
39 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
40 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
41 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
42 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
43 import org.opendaylight.netvirt.elanmanager.api.IElanService;
44 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
45 import org.opendaylight.netvirt.natservice.ha.NatDataUtil;
46 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddressBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatFlags;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatRangePresent;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService {
62
63     private static final Logger LOG = LoggerFactory.getLogger(VxlanGreConntrackBasedSnatService.class);
64     private final ExternalRoutersListener externalRouterListener;
65     private final IElanService elanManager;
66
67     public VxlanGreConntrackBasedSnatService(DataBroker dataBroker, IMdsalApiManager mdsalManager,
68                                              ItmRpcService itmManager, OdlInterfaceRpcService odlInterfaceRpcService,
69                                              IdManagerService idManager, NAPTSwitchSelector naptSwitchSelector,
70                                              ExternalRoutersListener externalRouterListener, IElanService elanManager,
71                                              IInterfaceManager interfaceManager,
72                                              IVpnFootprintService vpnFootprintService,
73                                              IFibManager fibManager, NatDataUtil natDataUtil,
74                                              DataTreeEventCallbackRegistrar eventCallbacks) {
75         super(dataBroker, mdsalManager, itmManager, idManager, naptSwitchSelector, odlInterfaceRpcService,
76                 interfaceManager, vpnFootprintService, fibManager, natDataUtil, eventCallbacks);
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(confTx, dpnId, routers, routerId, routerName, externalIp);
169     }
170
171     @Override
172     protected void removeSnatSpecificEntriesForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
173         Routers routers, BigInteger dpnId) {
174
175         LOG.info("installSnatSpecificEntriesForNaptSwitch for router {}",
176             routers.getRouterName());
177         String routerName = routers.getRouterName();
178         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
179
180         /* Remove Outbound NAT entries */
181         removeSnatMissEntryForPrimrySwch(confTx, dpnId, routerId);
182         removeTerminatingServiceTblEntryForVxlanGre(confTx, dpnId, routerId);
183         //Long extNetVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
184         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, routers.getNetworkId());
185         if (vpnUuid == null) {
186             LOG.error("installSnatSpecificEntriesForNaptSwitch: Unable to retrieve external vpn_id for "
187                 + "external network {} with routerId {}", routers.getNetworkId(), routerId);
188             return;
189         }
190         Long extNetVpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
191         LOG.info("installSnatSpecificEntriesForNaptSwitch: external network vpn_id {} for router {}",
192             extNetVpnId, routers.getRouterName());
193         List<ExternalIps> externalIps = routers.getExternalIps();
194         removeOutboundTblTrackEntryForVxlanGre(confTx, dpnId, routerId);
195         removeOutboundTblEntryForVxlanGre(confTx, dpnId, routerId, externalIps);
196         removeNaptPfibFlowForVxlanGre(confTx, routers, dpnId, extNetVpnId);
197         removeNaptPfibEntry(confTx, dpnId, routerId);
198
199         //Install Inbound NAT entries
200         removeInboundEntryForVxlanGre(confTx, dpnId, routerId, externalIps);
201         if (externalIps.isEmpty()) {
202             LOG.error("installSnatSpecificEntriesForNaptSwitch: No externalIP present for router {}",
203                 routerName);
204             return;
205         }
206         //The logic now handle only one external IP per router, others if present will be ignored.
207         String externalIp = NatUtil.validateAndAddNetworkMask(externalIps.get(0).getIpAddress());
208         externalRouterListener.clearFibTsAndReverseTraffic(dpnId, routerId, routers.getNetworkId(),
209             Collections.singletonList(externalIp), null, routers.getExtGwMacAddress(), confTx);
210     }
211
212     protected void addOutboundTblTrackEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId,
213         Long routerId, Long extNetVpnId) {
214         LOG.info("createOutboundTblTrackEntryForVxlanGre: Install Outbound tracking table flow on dpId {} for "
215                 + "routerId {}", dpnId, routerId);
216         List<MatchInfoBase> matches = new ArrayList<>();
217         matches.add(MatchEthernetType.IPV4);
218         matches.add(new NxMatchCtState(SNAT_CT_STATE, SNAT_CT_STATE_MASK));
219         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
220
221         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
222         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil.getVpnIdMetadata(extNetVpnId));
223         listActionInfo.add(actionSetFieldMeta);
224         ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
225         listActionInfo.add(new ActionNxResubmit(NwConstants.NAPT_PFIB_TABLE));
226         instructionInfo.add(new InstructionApplyActions(listActionInfo));
227
228         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId) + "trkest";
229         addFlow(confTx, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, NatConstants.SNAT_TRK_FLOW_PRIORITY, flowRef,
230                 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
231
232     }
233
234     protected void removeOutboundTblTrackEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx,
235         BigInteger dpnId, Long routerId) {
236         LOG.info("createOutboundTblTrackEntryForVxlanGre: Install Outbound tracking table flow on dpId {} for "
237             + "routerId {}", dpnId, routerId);
238
239         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId) + "trkest";
240         removeFlow(confTx, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef);
241
242     }
243
244     protected void addOutboundTblEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId,
245         long routerId, Long extNetVpnId, List<ExternalIps> externalIps, int elanId) {
246         LOG.info("createOutboundTblEntryForVxlanGre: Install Outbound table flow on dpId {} for routerId {}", dpnId,
247                 routerId);
248         List<MatchInfoBase> matches = new ArrayList<>();
249         matches.add(MatchEthernetType.IPV4);
250         matches.add(new NxMatchCtState(TRACKED_NEW_CT_STATE, TRACKED_NEW_CT_MASK));
251         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
252         if (externalIps.isEmpty()) {
253             LOG.error("createOutboundTblEntryForVxlanGre: No externalIP present for routerId {}",
254                     routerId);
255             return;
256         }
257         //The logic now handle only one external IP per router, others if present will be ignored.
258         String externalIp = externalIps.get(0).getIpAddress();
259         List<ActionInfo> actionsInfos = new ArrayList<>();
260         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
261                 .getVpnIdMetadata(extNetVpnId));
262         actionsInfos.add(actionSetFieldMeta);
263         List<ActionNxConntrack.NxCtAction> ctActionsListCommit = new ArrayList<>();
264         int rangePresent = NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue();
265         int flags = NxActionNatFlags.NXNATFSRC.getIntValue();
266         ActionNxConntrack.NxCtAction nxCtActionCommit = new ActionNxConntrack.NxNat(0, flags, rangePresent,
267             IpPrefixOrAddressBuilder.getDefaultInstance(externalIp).getIpAddress(), null,0, 0);
268         ctActionsListCommit.add(nxCtActionCommit);
269         int ctCommitFlag = 1;
270         ActionNxConntrack actionNxConntrackSubmit = new ActionNxConntrack(ctCommitFlag, 0, elanId,
271                 NwConstants.NAPT_PFIB_TABLE, ctActionsListCommit);
272         actionsInfos.add(actionNxConntrackSubmit);
273         List<InstructionInfo> instructions = new ArrayList<>();
274         instructions.add(new InstructionApplyActions(actionsInfos));
275         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
276         addFlow(confTx, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,  NatConstants.SNAT_NEW_FLOW_PRIORITY,
277                 flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
278     }
279
280     protected void removeOutboundTblEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
281         long routerId, List<ExternalIps> externalIps) {
282         LOG.info("createOutboundTblEntryForVxlanGre: Install Outbound table flow on dpId {} for routerId {}", dpnId,
283             routerId);
284         if (externalIps.isEmpty()) {
285             LOG.error("createOutboundTblEntryForVxlanGre: No externalIP present for routerId {}",
286                 routerId);
287             return;
288         }
289         //The logic now handle only one external IP per router, others if present will be ignored.
290         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
291         removeFlow(confTx, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef);
292     }
293
294     protected void addNaptPfibFlowForVxlanGre(TypedWriteTransaction<Configuration> confTx, Routers routers,
295         BigInteger dpnId, Long extNetVpnId) {
296         LOG.info("installNaptPfibFlowForVxlanGre: Install Napt preFibFlow on dpId {} with matching extNetVpnId {} "
297                 + "for router {}", dpnId, extNetVpnId, routers.getRouterName());
298         List<MatchInfoBase> matches = new ArrayList<>();
299         matches.add(MatchEthernetType.IPV4);
300         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extNetVpnId),
301                 MetaDataUtil.METADATA_MASK_VRFID));
302         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
303         ArrayList<InstructionInfo> instructions = new ArrayList<>();
304         listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
305         listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
306         instructions.add(new InstructionApplyActions(listActionInfo));
307         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, extNetVpnId);
308         addFlow(confTx, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef, NatConstants.SNAT_TRK_FLOW_PRIORITY,
309                 flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
310     }
311
312     protected void removeNaptPfibFlowForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
313         BigInteger dpnId, Long extNetVpnId) {
314         LOG.info("installNaptPfibFlowForVxlanGre: Install Napt preFibFlow on dpId {} with matching extNetVpnId {} "
315             + "for router {}", dpnId, extNetVpnId, routers.getRouterName());
316         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, extNetVpnId);
317         removeFlow(confTx, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef);
318     }
319
320     protected void addInboundEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId,
321         long routerId, Long extNeVpnId, List<ExternalIps> externalIps, int elanId) {
322         LOG.info("installInboundEntryForVxlanGre:  Install Inbound table entry on dpId {} for routerId {}",
323                 dpnId, routerId);
324         List<MatchInfoBase> matches = new ArrayList<>();
325         matches.add(MatchEthernetType.IPV4);
326         if (externalIps.isEmpty()) {
327             LOG.error("installInboundEntryForVxlanGre : createInboundTblEntry no externalIP present for routerId {}",
328                     routerId);
329             return;
330         }
331         String externalIp = externalIps.get(0).getIpAddress();
332         matches.add(new MatchIpv4Destination(externalIp,"32"));
333         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extNeVpnId), MetaDataUtil.METADATA_MASK_VRFID));
334         List<ActionInfo> actionsInfos = new ArrayList<>();
335         List<ActionNxConntrack.NxCtAction> ctActionsList = new ArrayList<>();
336         ActionNxConntrack.NxCtAction nxCtAction = new ActionNxConntrack.NxNat(0, 0, 0,null, null,0, 0);
337         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
338                 .getVpnIdMetadata(routerId));
339         actionsInfos.add(actionSetFieldMeta);
340         ctActionsList.add(nxCtAction);
341         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(0, 0, elanId, NwConstants
342                 .NAPT_PFIB_TABLE,ctActionsList);
343
344         actionsInfos.add(actionNxConntrack);
345         List<InstructionInfo> instructions = new ArrayList<>();
346         instructions.add(new InstructionApplyActions(actionsInfos));
347         String flowRef = getFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId);
348         addFlow(confTx, dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef, NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef,
349                 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
350     }
351
352     protected void removeInboundEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
353         long routerId, List<ExternalIps> externalIps) {
354         LOG.info("removeInboundEntryForVxlanGre: remove Inbound table entry on dpId {} for routerId {}",
355             dpnId, routerId);
356         if (externalIps.isEmpty()) {
357             LOG.error("removeInboundEntryForVxlanGre : createInboundTblEntry no externalIP present for routerId {}",
358                 routerId);
359             return;
360         }
361
362         String flowRef = getFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId);
363         removeFlow(confTx, dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef);
364     }
365
366     protected void addTerminatingServiceTblEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx,
367         BigInteger dpnId, String routerName, Long routerId, int elanId) {
368         LOG.info("installTerminatingServiceTblEntryForVxlanGre : creating entry for"
369                 + "Terminating Service Table for switch {}, routerId {}", dpnId, routerId);
370         List<MatchInfo> matches = new ArrayList<>();
371         matches.add(MatchEthernetType.IPV4);
372
373         BigInteger tunnelId = BigInteger.valueOf(routerId);
374         if (elanManager.isOpenStackVniSemanticsEnforced()) {
375             tunnelId = NatOverVxlanUtil.getRouterVni(idManager, routerName, routerId);
376         }
377         matches.add(new MatchTunnelId(tunnelId));
378
379         List<ActionInfo> actionsInfos = new ArrayList<>();
380         List<NxCtAction> ctActionsList = new ArrayList<>();
381         NxCtAction nxCtAction = new ActionNxConntrack.NxNat(0, 0, 0,null, null,0, 0);
382         ctActionsList.add(nxCtAction);
383         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(0, 0, elanId, NwConstants
384                 .OUTBOUND_NAPT_TABLE,ctActionsList);
385         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
386                 .getVpnIdMetadata(routerId.longValue()));
387         actionsInfos.add(actionSetFieldMeta);
388         actionsInfos.add(actionNxConntrack);
389         List<InstructionInfo> instructions = new ArrayList<>();
390         instructions.add(new InstructionApplyActions(actionsInfos));
391         String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
392         addFlow(confTx, dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef, NatConstants.DEFAULT_TS_FLOW_PRIORITY,
393             flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
394
395     }
396
397     protected void removeTerminatingServiceTblEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx,
398         BigInteger dpnId, Long routerId) {
399         LOG.info("removeTerminatingServiceTblEntryForVxlanGre : removing entry for"
400             + "Terminating Service Table for switch {}, routerId {}", dpnId, routerId);
401
402         String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
403         removeFlow(confTx, dpnId,  NwConstants.INTERNAL_TUNNEL_TABLE, flowRef);
404
405     }
406
407     @Override
408     protected void addSnatMissEntry(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId, Long routerId,
409         String routerName, BigInteger primarySwitchId) {
410         LOG.debug("installSnatMissEntry : Installing SNAT miss entry in switch {}", dpnId);
411         List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
412         String ifNamePrimary = getTunnelInterfaceName(dpnId, primarySwitchId);
413         List<BucketInfo> listBucketInfo = new ArrayList<>();
414         if (ifNamePrimary != null) {
415             LOG.debug("installSnatMissEntry : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
416             listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
417                     interfaceManager, ifNamePrimary, routerId, true);
418         }
419         BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
420         listBucketInfo.add(0, bucketPrimary);
421         LOG.debug("installSnatMissEntry : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId,
422                 listBucketInfo.get(0));
423         // Install the select group
424         long groupId = createGroupId(getGroupIdKey(routerName));
425         GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll,
426                 listBucketInfo);
427         LOG.debug("installSnatMissEntry : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
428         mdsalManager.addGroup(confTx, groupEntity);
429         // Install miss entry pointing to group
430         LOG.debug("installSnatMissEntry : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}",
431                 dpnId, routerName, groupId);
432         List<MatchInfo> matches = new ArrayList<>();
433         matches.add(new MatchEthernetType(0x0800L));
434         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
435
436         List<ActionInfo> actionsInfo = new ArrayList<>();
437
438         BigInteger tunnelId = BigInteger.valueOf(routerId);
439         if (elanManager.isOpenStackVniSemanticsEnforced()) {
440             tunnelId = NatOverVxlanUtil.getRouterVni(idManager, routerName, routerId);
441         }
442
443         actionsInfo.add(new ActionSetFieldTunnelId(tunnelId));
444         LOG.debug("AbstractSnatService : Setting the tunnel to the list of action infos {}", actionsInfo);
445         actionsInfo.add(new ActionGroup(groupId));
446         List<InstructionInfo> instructions = new ArrayList<>();
447         instructions.add(new InstructionApplyActions(actionsInfo));
448         String flowRef = getFlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
449         addFlow(confTx, dpnId, NwConstants.PSNAT_TABLE, flowRef,  NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
450                 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
451     }
452
453     @Override
454     protected void removeSnatMissEntry(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
455         Long routerId, String routerName) {
456         LOG.debug("installSnatMissEntry : Removing SNAT miss entry in switch {}", dpnId);
457
458         String flowRef = getFlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
459         removeFlow(confTx, dpnId, NwConstants.PSNAT_TABLE, flowRef);
460     }
461
462 }