natservice dead code removal
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / Ipv6ForwardingService.java
1 /*
2  * Copyright (c) 2018 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 static org.opendaylight.netvirt.natservice.internal.AbstractSnatService.LOAD_END;
11 import static org.opendaylight.netvirt.natservice.internal.AbstractSnatService.LOAD_START;
12 import static org.opendaylight.netvirt.natservice.internal.NatUtil.getGroupIdKey;
13
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.Objects;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Future;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.genius.infra.Datastore.Configuration;
22 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
23 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
24 import org.opendaylight.genius.mdsalutil.ActionInfo;
25 import org.opendaylight.genius.mdsalutil.BucketInfo;
26 import org.opendaylight.genius.mdsalutil.GroupEntity;
27 import org.opendaylight.genius.mdsalutil.InstructionInfo;
28 import org.opendaylight.genius.mdsalutil.MDSALUtil;
29 import org.opendaylight.genius.mdsalutil.MatchInfo;
30 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
31 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
32 import org.opendaylight.genius.mdsalutil.NWUtil;
33 import org.opendaylight.genius.mdsalutil.NwConstants;
34 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
35 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
36 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadMetadata;
37 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
38 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
39 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
40 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
41 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
42 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
43 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
44 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
45 import org.opendaylight.netvirt.natservice.api.SnatServiceListener;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
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.ext.routers.Routers;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
55 import org.opendaylight.yangtools.yang.common.RpcResult;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 public class Ipv6ForwardingService implements SnatServiceListener {
60     private static final Logger LOG = LoggerFactory.getLogger(Ipv6ForwardingService.class);
61
62     protected final DataBroker dataBroker;
63     protected final IMdsalApiManager mdsalManager;
64     protected final IdManagerService idManager;
65     protected final NAPTSwitchSelector naptSwitchSelector;
66     protected final ItmRpcService itmManager;
67     protected final OdlInterfaceRpcService odlInterfaceRpcService;
68     protected final IInterfaceManager interfaceManager;
69     protected final Ipv6SubnetFlowProgrammer ipv6SubnetFlowProgrammer;
70
71     public Ipv6ForwardingService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
72                                   final ItmRpcService itmManager,
73                                   final OdlInterfaceRpcService odlInterfaceRpcService,
74                                   final IdManagerService idManager,
75                                   final NAPTSwitchSelector naptSwitchSelector,
76                                   final IInterfaceManager interfaceManager,
77                                   final Ipv6SubnetFlowProgrammer ipv6SubnetFlowProgrammer) {
78         this.dataBroker = dataBroker;
79         this.mdsalManager = mdsalManager;
80         this.itmManager = itmManager;
81         this.odlInterfaceRpcService = odlInterfaceRpcService;
82         this.idManager = idManager;
83         this.naptSwitchSelector = naptSwitchSelector;
84         this.interfaceManager = interfaceManager;
85         this.ipv6SubnetFlowProgrammer = ipv6SubnetFlowProgrammer;
86     }
87
88     @Override
89     public boolean addCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx,
90             Routers routers, BigInteger primarySwitchId) {
91         String routerName = routers.getRouterName();
92         LOG.info("handleSnatAllSwitch : invoked for router {} with NAPTSwitch {} for {} flows",
93                 routerName, primarySwitchId, "installing");
94         List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
95         /*
96          * Primary switch handled separately since the pseudo port created may
97          * not be present in the switch list on delete.
98          */
99         addCentralizedRouter(confTx, routers, primarySwitchId, primarySwitchId);
100         for (BigInteger dpnId : switches) {
101             if (!Objects.equals(primarySwitchId, dpnId)) {
102                 addCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
103             }
104         }
105         return true;
106     }
107
108     @Override
109     public boolean addCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx,
110             Routers routers, BigInteger primarySwitchId, BigInteger dpnId) {
111         Long routerId = NatUtil.getVpnId(dataBroker, routers.getRouterName());
112         BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
113
114         if (!dpnId.equals(primarySwitchId)) {
115             LOG.info("handleSnat (non-NAPTSwitch) : {} flows on switch {} for router {}",
116                     "Installing", dpnId, routers.getRouterName());
117             // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
118             addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
119
120             // Currently we are only programming flows when ext-net has an IPv6Subnet
121             if (routerHasIpv6ExtSubnet(routers)) {
122                 // Program flows on non-NAPTSwitch to send N/S packets to the NAPTSwitch
123                 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routers.getRouterName(),
124                         primarySwitchId);
125             }
126         } else {
127             LOG.info("handleSnat (NAPTSwitch) : {} flows on switch {} for router {}",
128                     "Installing", dpnId, routers.getRouterName());
129             // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
130             addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
131
132             // Program flows from PSNAT_TABLE(26) to OUTBOUND_NAPT_TABLE(46) (egress direction)
133             addIpv6SnatMissEntryForNaptSwitch(confTx, dpnId, routerId, routerMetadata);
134
135             // Program flows in INTERNAL_TUNNEL_TABLE(36) for packets coming from non-NAPTSwitch (egress direction)
136             addIpv6TerminatingServiceTblEntry(confTx, dpnId, routerId, routerMetadata);
137
138             // Program flows from NAPT_PFIB_TABLE(47) to FIB_TABLE(21) (ingress direction)
139             addIpv6NaptPfibInboundFlow(confTx, dpnId, routerId, routerMetadata);
140
141             // Now installing flows that use SubnetInfo
142             ipv6SubnetFlowProgrammer. addSubnetSpecificFlows(confTx, dpnId, routerId, routers, routerMetadata);
143         }
144         return true;
145     }
146
147     @Override
148     public boolean removeCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx,
149             Routers routers, BigInteger primarySwitchId) throws ExecutionException, InterruptedException {
150         String routerName = routers.getRouterName();
151         LOG.info("handleSnatAllSwitch : invoked for router {} with NAPTSwitch {} for {} flows",
152                 routerName, primarySwitchId, "removing");
153         List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
154         /*
155          * Primary switch handled separately since the pseudo port created may
156          * not be present in the switch list on delete.
157          */
158         removeCentralizedRouter(confTx, routers, primarySwitchId, primarySwitchId);
159         for (BigInteger dpnId : switches) {
160             if (!Objects.equals(primarySwitchId, dpnId)) {
161                 removeCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
162             }
163         }
164         return true;
165     }
166
167     @Override
168     public boolean removeCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx,
169             Routers routers, BigInteger primarySwitchId, BigInteger dpnId)
170                     throws ExecutionException, InterruptedException {
171         Long routerId = NatUtil.getVpnId(dataBroker, routers.getRouterName());
172         BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
173
174         if (!dpnId.equals(primarySwitchId)) {
175             LOG.info("handleSnat (non-NAPTSwitch) : {} flows on switch {} for router {}",
176                     "Removing", dpnId, routers.getRouterName());
177             // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
178             addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
179
180             // Currently we are only programming flows when ext-net has an IPv6Subnet
181             if (routerHasIpv6ExtSubnet(routers)) {
182                 // Program flows on non-NAPTSwitch to send N/S packets to the NAPTSwitch
183                 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routers.getRouterName(),
184                         primarySwitchId);
185             }
186         } else {
187             LOG.info("handleSnat (NAPTSwitch) : {} flows on switch {} for router {}",
188                     "Removing", dpnId, routers.getRouterName());
189             // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
190             removeIpv6DefaultFibRoute(confTx, dpnId, routerId);
191
192             // Program flows from PSNAT_TABLE(26) to OUTBOUND_NAPT_TABLE(46) (egress direction)
193             removeIpv6SnatMissEntryForNaptSwitch(confTx, dpnId, routerId);
194
195             // Program flows in INTERNAL_TUNNEL_TABLE(36) for packets coming from non-NAPTSwitch (egress direction)
196             removeIpv6TerminatingServiceTblEntry(confTx, dpnId, routerId);
197
198             // Program flows from NAPT_PFIB_TABLE(47) to FIB_TABLE(21) (ingress direction)
199             removeIpv6NaptPfibInboundFlow(confTx, dpnId, routerId);
200
201             // Now installing flows that use SubnetInfo
202             ipv6SubnetFlowProgrammer.removeSubnetSpecificFlows(confTx, dpnId, routerId, routers);
203         }
204         return true;
205     }
206
207     @Override
208     public boolean handleRouterUpdate(TypedReadWriteTransaction<Configuration> confTx,
209             Routers origRouter, Routers updatedRouter) throws ExecutionException, InterruptedException {
210         LOG.info("handleRouterUpdate : originalRouter {}, updatedRouter {}", origRouter, updatedRouter);
211         String routerName = origRouter.getRouterName();
212         BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
213         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
214         BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
215
216         // If the external network is updated with an IPv6Subnet, program the necessary flows on non-NAPTSwitch
217         if (!routerHasIpv6ExtSubnet(origRouter) && routerHasIpv6ExtSubnet(updatedRouter)) {
218             List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
219             for (BigInteger dpnId : switches) {
220                 if (!Objects.equals(primarySwitchId, dpnId)) {
221                     LOG.info("handleRouterUpdate (non-NAPTSwitch) : Installing flows on switch {} for router {}",
222                             dpnId, routerName);
223                     addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routerName,
224                             primarySwitchId);
225                 }
226             }
227         }
228
229         ipv6SubnetFlowProgrammer.removeSubnetSpecificFlows(confTx, primarySwitchId, routerId, origRouter);
230         ipv6SubnetFlowProgrammer.addSubnetSpecificFlows(confTx, primarySwitchId, routerId, updatedRouter,
231                 routerMetadata);
232         return true;
233     }
234
235     @Override
236     public boolean addSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
237             BigInteger primarySwitchId) {
238         return true;
239     }
240
241     @Override
242     public boolean addSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
243             BigInteger primarySwitchId, BigInteger dpnId) {
244         return true;
245     }
246
247     @Override
248     public boolean removeSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
249             BigInteger primarySwitchId)  throws ExecutionException, InterruptedException {
250         return true;
251     }
252
253     @Override
254     public boolean removeSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
255             BigInteger primarySwitchId, BigInteger dpnId) throws ExecutionException, InterruptedException {
256         return true;
257     }
258
259
260     protected void addIpv6DefaultFibRoute(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
261             Long routerId, BigInteger routerMetadata) {
262         LOG.debug("installIpv6DefaultFibRoute : Installing default FIB route to PSNAT_TABLE on {}", dpnId);
263         List<MatchInfo> matches = new ArrayList<>();
264         matches.add(MatchEthernetType.IPV6);
265         matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
266
267         List<InstructionInfo> instructions = new ArrayList<>();
268         instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
269
270         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.L3_FIB_TABLE, routerId);
271         flowRef += ".Outbound";
272         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.L3_FIB_TABLE, flowRef,
273                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef,
274                 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
275     }
276
277     protected void removeIpv6DefaultFibRoute(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
278             Long routerId) throws ExecutionException, InterruptedException {
279         LOG.debug("installIpv6DefaultFibRoute : Installing default FIB route to PSNAT_TABLE on {}", dpnId);
280         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.L3_FIB_TABLE, routerId);
281         flowRef += ".Outbound";
282         NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.L3_FIB_TABLE, flowRef);
283     }
284
285     protected void addIpv6PsNatMissEntryNonNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
286             BigInteger dpnId, Long routerId, String routerName, BigInteger primarySwitchId) {
287         LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, installing SNAT miss entry in"
288                 + " switch {} for router {}", dpnId, routerName);
289         List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
290         List<BucketInfo> listBucketInfo = new ArrayList<>();
291
292         String ifNamePrimary = NatUtil.getTunnelInterfaceName(dpnId, primarySwitchId, itmManager);
293         if (ifNamePrimary != null) {
294             LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, Primary Tunnel interface is {}",
295                     ifNamePrimary);
296             listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
297                     interfaceManager, ifNamePrimary, routerId, true);
298         } else {
299             LOG.warn("installIpv6PsNatMissEntryNonNaptSwitch: could not get tunnelInterface for {} on Switch {}",
300                     primarySwitchId, dpnId);
301         }
302
303         BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
304         listBucketInfo.add(0, bucketPrimary);
305
306         LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : installSnatMissEntry called for dpnId {} with"
307                 + " primaryBucket {} ", dpnId, listBucketInfo.get(0));
308
309         long groupId = createGroupIdForIpv6Router(getGroupIdKey(routerName + "IPv6"));
310         GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll,
311                 listBucketInfo);
312         LOG.debug("installing the PSNAT to NAPTSwitch GroupEntity:{} with GroupId: {}", groupEntity, groupId);
313         mdsalManager.addGroup(confTx, groupEntity);
314         List<MatchInfo> matches = new ArrayList<>();
315         matches.add(MatchEthernetType.IPV6);
316         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
317
318         List<ActionInfo> actionsInfo = new ArrayList<>();
319         actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(routerId)));
320         actionsInfo.add(new ActionGroup(groupId));
321         List<InstructionInfo> instructions = new ArrayList<>();
322         instructions.add(new InstructionApplyActions(actionsInfo));
323
324         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
325         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef,
326                 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
327                 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
328     }
329
330     protected void addIpv6SnatMissEntryForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
331             BigInteger dpnId, Long routerId, BigInteger routerMetadata) {
332         LOG.debug("installIpv6SnatMissEntryForNaptSwitch {} called for routerId {}", dpnId, routerId);
333         List<MatchInfo> matches = new ArrayList<>();
334         matches.add(MatchEthernetType.IPV6);
335         matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
336
337         List<InstructionInfo> instructions = new ArrayList<>();
338         instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
339
340         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
341         flowRef += ".Outbound";
342         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef,
343                 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
344                 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
345     }
346
347     protected void removeIpv6SnatMissEntryForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
348             BigInteger dpnId, Long routerId)
349                     throws ExecutionException, InterruptedException {
350         LOG.debug("installIpv6SnatMissEntryForNaptSwitch {} called for routerId {}", dpnId, routerId);
351         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
352         flowRef += ".Outbound";
353         NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef);
354     }
355
356     protected void addIpv6TerminatingServiceTblEntry(TypedReadWriteTransaction<Configuration> confTx,
357             BigInteger dpnId, Long  routerId, BigInteger routerMetadata) {
358         LOG.debug("installIpv6TerminatingServiceTblEntry : creating entry for Terminating Service Table "
359                 + "for switch {}, routerId {}", dpnId, routerId);
360         List<MatchInfo> matches = new ArrayList<>();
361         matches.add(MatchEthernetType.IPV6);
362         matches.add(new MatchTunnelId(BigInteger.valueOf(routerId)));
363
364         List<ActionInfo> actionsInfos = new ArrayList<>();
365         ActionNxLoadMetadata actionLoadMeta = new ActionNxLoadMetadata(routerMetadata, LOAD_START, LOAD_END);
366         actionsInfos.add(actionLoadMeta);
367         actionsInfos.add(new ActionNxResubmit(NwConstants.OUTBOUND_NAPT_TABLE));
368         List<InstructionInfo> instructions = new ArrayList<>();
369         instructions.add(new InstructionApplyActions(actionsInfos));
370
371         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
372         flowRef += ".Outbound";
373         NatUtil.addFlow(confTx, mdsalManager, dpnId,  NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
374                 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef,
375                 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
376
377     }
378
379     protected void removeIpv6TerminatingServiceTblEntry(TypedReadWriteTransaction<Configuration> confTx,
380             BigInteger dpnId, Long  routerId) throws ExecutionException, InterruptedException {
381         LOG.debug("installIpv6TerminatingServiceTblEntry : creating entry for Terminating Service Table "
382                 + "for switch {}, routerId {}", dpnId, routerId);
383         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
384         flowRef += ".Outbound";
385         NatUtil.removeFlow(confTx, mdsalManager, dpnId,  NwConstants.INTERNAL_TUNNEL_TABLE, flowRef);
386
387     }
388
389     protected void addIpv6NaptPfibInboundFlow(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
390             long routerId, BigInteger routerMetadata) {
391         LOG.debug("installIpv6NaptPfibInboundFlow : called for dpnId {} and routerId {} ", dpnId, routerId);
392         List<MatchInfoBase> matches = new ArrayList<>();
393         matches.add(MatchEthernetType.IPV6);
394         matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
395
396         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
397         ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
398         listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
399         listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
400         instructionInfo.add(new InstructionApplyActions(listActionInfo));
401
402         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
403         flowRef += ".Inbound";
404         NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef,
405                 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY,
406                 flowRef, NwConstants.COOKIE_SNAT_TABLE,
407                 matches, instructionInfo);
408     }
409
410     protected void removeIpv6NaptPfibInboundFlow(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
411             long routerId)
412                     throws ExecutionException, InterruptedException {
413         LOG.debug("installIpv6NaptPfibInboundFlow : called for dpnId {} and routerId {} ", dpnId, routerId);
414         String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
415         flowRef += ".Inbound";
416         NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef);
417     }
418
419     protected long createGroupIdForIpv6Router(String groupIdKey) {
420         AllocateIdInput getIdInput = new AllocateIdInputBuilder()
421                 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
422                 .build();
423         try {
424             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
425             RpcResult<AllocateIdOutput> rpcResult = result.get();
426             return rpcResult.getResult().getIdValue();
427         } catch (NullPointerException | InterruptedException | ExecutionException e) {
428             LOG.error("createGroupIdForIPv6Router: Exception while creating group with key : {}", groupIdKey, e);
429         }
430         return 0;
431     }
432
433     protected boolean routerHasIpv6ExtSubnet(Routers routers) {
434         for (ExternalIps externalIp : routers.getExternalIps()) {
435             if (!NWUtil.isIpv4Address(externalIp.getIpAddress())) {
436                 LOG.debug("router {}, has an external IPv6 subnet {}",
437                         routers.getRouterName(), externalIp.getIpAddress());
438                 return true;
439             }
440         }
441         LOG.debug("router {}, does not have an external IPv6 subnet", routers.getRouterName());
442         return false;
443     }
444 }