2 * Copyright (c) 2018 Red Hat, Inc. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.natservice.internal;
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;
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;
59 public class Ipv6ForwardingService implements SnatServiceListener {
60 private static final Logger LOG = LoggerFactory.getLogger(Ipv6ForwardingService.class);
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;
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;
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);
96 * Primary switch handled separately since the pseudo port created may
97 * not be present in the switch list on delete.
99 addCentralizedRouter(confTx, routers, primarySwitchId, primarySwitchId);
100 for (BigInteger dpnId : switches) {
101 if (!Objects.equals(primarySwitchId, dpnId)) {
102 addCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
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);
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);
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(),
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);
132 // Program flows from PSNAT_TABLE(26) to OUTBOUND_NAPT_TABLE(46) (egress direction)
133 addIpv6SnatMissEntryForNaptSwitch(confTx, dpnId, routerId, routerMetadata);
135 // Program flows in INTERNAL_TUNNEL_TABLE(36) for packets coming from non-NAPTSwitch (egress direction)
136 addIpv6TerminatingServiceTblEntry(confTx, dpnId, routerId, routerMetadata);
138 // Program flows from NAPT_PFIB_TABLE(47) to FIB_TABLE(21) (ingress direction)
139 addIpv6NaptPfibInboundFlow(confTx, dpnId, routerId, routerMetadata);
141 // Now installing flows that use SubnetInfo
142 ipv6SubnetFlowProgrammer. addSubnetSpecificFlows(confTx, dpnId, routerId, routers, routerMetadata);
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);
155 * Primary switch handled separately since the pseudo port created may
156 * not be present in the switch list on delete.
158 removeCentralizedRouter(confTx, routers, primarySwitchId, primarySwitchId);
159 for (BigInteger dpnId : switches) {
160 if (!Objects.equals(primarySwitchId, dpnId)) {
161 removeCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
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);
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);
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(),
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);
192 // Program flows from PSNAT_TABLE(26) to OUTBOUND_NAPT_TABLE(46) (egress direction)
193 removeIpv6SnatMissEntryForNaptSwitch(confTx, dpnId, routerId);
195 // Program flows in INTERNAL_TUNNEL_TABLE(36) for packets coming from non-NAPTSwitch (egress direction)
196 removeIpv6TerminatingServiceTblEntry(confTx, dpnId, routerId);
198 // Program flows from NAPT_PFIB_TABLE(47) to FIB_TABLE(21) (ingress direction)
199 removeIpv6NaptPfibInboundFlow(confTx, dpnId, routerId);
201 // Now installing flows that use SubnetInfo
202 ipv6SubnetFlowProgrammer.removeSubnetSpecificFlows(confTx, dpnId, routerId, routers);
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);
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 {}",
223 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routerName,
229 ipv6SubnetFlowProgrammer.removeSubnetSpecificFlows(confTx, primarySwitchId, routerId, origRouter);
230 ipv6SubnetFlowProgrammer.addSubnetSpecificFlows(confTx, primarySwitchId, routerId, updatedRouter,
236 public boolean addSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
237 BigInteger primarySwitchId) {
242 public boolean addSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
243 BigInteger primarySwitchId, BigInteger dpnId) {
248 public boolean removeSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
249 BigInteger primarySwitchId) throws ExecutionException, InterruptedException {
254 public boolean removeSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
255 BigInteger primarySwitchId, BigInteger dpnId) throws ExecutionException, InterruptedException {
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));
267 List<InstructionInfo> instructions = new ArrayList<>();
268 instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
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);
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);
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<>();
292 String ifNamePrimary = NatUtil.getTunnelInterfaceName(dpnId, primarySwitchId, itmManager);
293 if (ifNamePrimary != null) {
294 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, Primary Tunnel interface is {}",
296 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
297 interfaceManager, ifNamePrimary, routerId, true);
299 LOG.warn("installIpv6PsNatMissEntryNonNaptSwitch: could not get tunnelInterface for {} on Switch {}",
300 primarySwitchId, dpnId);
303 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
304 listBucketInfo.add(0, bucketPrimary);
306 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : installSnatMissEntry called for dpnId {} with"
307 + " primaryBucket {} ", dpnId, listBucketInfo.get(0));
309 long groupId = createGroupIdForIpv6Router(getGroupIdKey(routerName + "IPv6"));
310 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll,
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));
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));
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);
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));
337 List<InstructionInfo> instructions = new ArrayList<>();
338 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
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);
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);
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)));
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));
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);
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);
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));
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));
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);
410 protected void removeIpv6NaptPfibInboundFlow(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
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);
419 protected long createGroupIdForIpv6Router(String groupIdKey) {
420 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
421 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
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);
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());
441 LOG.debug("router {}, does not have an external IPv6 subnet", routers.getRouterName());