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