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.concurrent.ExecutionException;
18 import java.util.concurrent.Future;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.genius.infra.Datastore.Configuration;
21 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
22 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
23 import org.opendaylight.genius.mdsalutil.ActionInfo;
24 import org.opendaylight.genius.mdsalutil.BucketInfo;
25 import org.opendaylight.genius.mdsalutil.GroupEntity;
26 import org.opendaylight.genius.mdsalutil.InstructionInfo;
27 import org.opendaylight.genius.mdsalutil.MDSALUtil;
28 import org.opendaylight.genius.mdsalutil.MatchInfo;
29 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
30 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
31 import org.opendaylight.genius.mdsalutil.NWUtil;
32 import org.opendaylight.genius.mdsalutil.NwConstants;
33 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
34 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
35 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadMetadata;
36 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
37 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
38 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
39 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
40 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
41 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
42 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
43 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
44 import org.opendaylight.netvirt.natservice.api.SnatServiceListener;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
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.ext.routers.Routers;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
54 import org.opendaylight.yangtools.yang.common.RpcResult;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
58 public class Ipv6ForwardingService implements SnatServiceListener {
59 private static final Logger LOG = LoggerFactory.getLogger(Ipv6ForwardingService.class);
61 protected final DataBroker dataBroker;
62 protected final IMdsalApiManager mdsalManager;
63 protected final IdManagerService idManager;
64 protected final NAPTSwitchSelector naptSwitchSelector;
65 protected final ItmRpcService itmManager;
66 protected final OdlInterfaceRpcService odlInterfaceRpcService;
67 protected final IInterfaceManager interfaceManager;
68 protected final Ipv6SubnetFlowProgrammer ipv6SubnetFlowProgrammer;
70 public Ipv6ForwardingService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
71 final ItmRpcService itmManager,
72 final OdlInterfaceRpcService odlInterfaceRpcService,
73 final IdManagerService idManager,
74 final NAPTSwitchSelector naptSwitchSelector,
75 final IInterfaceManager interfaceManager,
76 final Ipv6SubnetFlowProgrammer ipv6SubnetFlowProgrammer) {
77 this.dataBroker = dataBroker;
78 this.mdsalManager = mdsalManager;
79 this.itmManager = itmManager;
80 this.odlInterfaceRpcService = odlInterfaceRpcService;
81 this.idManager = idManager;
82 this.naptSwitchSelector = naptSwitchSelector;
83 this.interfaceManager = interfaceManager;
84 this.ipv6SubnetFlowProgrammer = ipv6SubnetFlowProgrammer;
88 LOG.info("Ipv6ForwardingService: {} init", getClass().getSimpleName());
92 public boolean addCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx,
93 Routers routers, BigInteger primarySwitchId) {
94 String routerName = routers.getRouterName();
95 LOG.info("handleSnatAllSwitch : invoked for router {} with NAPTSwitch {} for {} flows",
96 routerName, primarySwitchId, "installing");
97 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
99 * Primary switch handled separately since the pseudo port created may
100 * not be present in the switch list on delete.
102 addCentralizedRouter(confTx, routers, primarySwitchId, primarySwitchId);
103 for (BigInteger dpnId : switches) {
104 if (primarySwitchId != dpnId) {
105 addCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
112 public boolean addCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx,
113 Routers routers, BigInteger primarySwitchId, BigInteger dpnId) {
114 Long routerId = NatUtil.getVpnId(dataBroker, routers.getRouterName());
115 BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
117 if (!dpnId.equals(primarySwitchId)) {
118 LOG.info("handleSnat (non-NAPTSwitch) : {} flows on switch {} for router {}",
119 "Installing", dpnId, routers.getRouterName());
120 // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
121 addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
123 // Currently we are only programming flows when ext-net has an IPv6Subnet
124 if (routerHasIpv6ExtSubnet(routers)) {
125 // Program flows on non-NAPTSwitch to send N/S packets to the NAPTSwitch
126 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routers.getRouterName(),
130 LOG.info("handleSnat (NAPTSwitch) : {} flows on switch {} for router {}",
131 "Installing", dpnId, routers.getRouterName());
132 // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
133 addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
135 // Program flows from PSNAT_TABLE(26) to OUTBOUND_NAPT_TABLE(46) (egress direction)
136 addIpv6SnatMissEntryForNaptSwitch(confTx, dpnId, routerId, routerMetadata);
138 // Program flows in INTERNAL_TUNNEL_TABLE(36) for packets coming from non-NAPTSwitch (egress direction)
139 addIpv6TerminatingServiceTblEntry(confTx, dpnId, routerId, routerMetadata);
141 // Program flows from NAPT_PFIB_TABLE(47) to FIB_TABLE(21) (ingress direction)
142 addIpv6NaptPfibInboundFlow(confTx, dpnId, routerId, routerMetadata);
144 // Now installing flows that use SubnetInfo
145 ipv6SubnetFlowProgrammer. addSubnetSpecificFlows(confTx, dpnId, routerId, routers, routerMetadata);
151 public boolean removeCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx,
152 Routers routers, BigInteger primarySwitchId) throws ExecutionException, InterruptedException {
153 String routerName = routers.getRouterName();
154 LOG.info("handleSnatAllSwitch : invoked for router {} with NAPTSwitch {} for {} flows",
155 routerName, primarySwitchId, "removing");
156 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
158 * Primary switch handled separately since the pseudo port created may
159 * not be present in the switch list on delete.
161 removeCentralizedRouter(confTx, routers, primarySwitchId, primarySwitchId);
162 for (BigInteger dpnId : switches) {
163 if (primarySwitchId != dpnId) {
164 removeCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
171 public boolean removeCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx,
172 Routers routers, BigInteger primarySwitchId, BigInteger dpnId)
173 throws ExecutionException, InterruptedException {
174 Long routerId = NatUtil.getVpnId(dataBroker, routers.getRouterName());
175 BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
177 if (!dpnId.equals(primarySwitchId)) {
178 LOG.info("handleSnat (non-NAPTSwitch) : {} flows on switch {} for router {}",
179 "Removing", dpnId, routers.getRouterName());
180 // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
181 addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
183 // Currently we are only programming flows when ext-net has an IPv6Subnet
184 if (routerHasIpv6ExtSubnet(routers)) {
185 // Program flows on non-NAPTSwitch to send N/S packets to the NAPTSwitch
186 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routers.getRouterName(),
190 LOG.info("handleSnat (NAPTSwitch) : {} flows on switch {} for router {}",
191 "Removing", dpnId, routers.getRouterName());
192 // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
193 removeIpv6DefaultFibRoute(confTx, dpnId, routerId);
195 // Program flows from PSNAT_TABLE(26) to OUTBOUND_NAPT_TABLE(46) (egress direction)
196 removeIpv6SnatMissEntryForNaptSwitch(confTx, dpnId, routerId);
198 // Program flows in INTERNAL_TUNNEL_TABLE(36) for packets coming from non-NAPTSwitch (egress direction)
199 removeIpv6TerminatingServiceTblEntry(confTx, dpnId, routerId);
201 // Program flows from NAPT_PFIB_TABLE(47) to FIB_TABLE(21) (ingress direction)
202 removeIpv6NaptPfibInboundFlow(confTx, dpnId, routerId);
204 // Now installing flows that use SubnetInfo
205 ipv6SubnetFlowProgrammer.removeSubnetSpecificFlows(confTx, dpnId, routerId, routers);
211 public boolean handleRouterUpdate(TypedReadWriteTransaction<Configuration> confTx,
212 Routers origRouter, Routers updatedRouter) throws ExecutionException, InterruptedException {
213 LOG.info("handleRouterUpdate : originalRouter {}, updatedRouter {}", origRouter, updatedRouter);
214 String routerName = origRouter.getRouterName();
215 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
216 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
217 BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
219 // If the external network is updated with an IPv6Subnet, program the necessary flows on non-NAPTSwitch
220 if (!routerHasIpv6ExtSubnet(origRouter) && routerHasIpv6ExtSubnet(updatedRouter)) {
221 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
222 for (BigInteger dpnId : switches) {
223 if (primarySwitchId != dpnId) {
224 LOG.info("handleRouterUpdate (non-NAPTSwitch) : Installing flows on switch {} for router {}",
226 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routerName,
232 ipv6SubnetFlowProgrammer.removeSubnetSpecificFlows(confTx, primarySwitchId, routerId, origRouter);
233 ipv6SubnetFlowProgrammer.addSubnetSpecificFlows(confTx, primarySwitchId, routerId, updatedRouter,
239 public boolean addSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
240 BigInteger primarySwitchId) {
245 public boolean addSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
246 BigInteger primarySwitchId, BigInteger dpnId) {
251 public boolean removeSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
252 BigInteger primarySwitchId) throws ExecutionException, InterruptedException {
257 public boolean removeSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
258 BigInteger primarySwitchId, BigInteger dpnId) throws ExecutionException, InterruptedException {
263 protected void addIpv6DefaultFibRoute(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
264 Long routerId, BigInteger routerMetadata) {
265 LOG.debug("installIpv6DefaultFibRoute : Installing default FIB route to PSNAT_TABLE on {}", dpnId);
266 List<MatchInfo> matches = new ArrayList<>();
267 matches.add(MatchEthernetType.IPV6);
268 matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
270 List<InstructionInfo> instructions = new ArrayList<>();
271 instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
273 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.L3_FIB_TABLE, routerId);
274 flowRef += ".Outbound";
275 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.L3_FIB_TABLE, flowRef,
276 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef,
277 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
280 protected void removeIpv6DefaultFibRoute(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
281 Long routerId) throws ExecutionException, InterruptedException {
282 LOG.debug("installIpv6DefaultFibRoute : Installing default FIB route to PSNAT_TABLE on {}", dpnId);
283 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.L3_FIB_TABLE, routerId);
284 flowRef += ".Outbound";
285 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.L3_FIB_TABLE, flowRef);
288 protected void addIpv6PsNatMissEntryNonNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
289 BigInteger dpnId, Long routerId, String routerName, BigInteger primarySwitchId) {
290 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, installing SNAT miss entry in"
291 + " switch {} for router {}", dpnId, routerName);
292 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
293 List<BucketInfo> listBucketInfo = new ArrayList<>();
295 String ifNamePrimary = NatUtil.getTunnelInterfaceName(dpnId, primarySwitchId, itmManager);
296 if (ifNamePrimary != null) {
297 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, Primary Tunnel interface is {}",
299 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
300 interfaceManager, ifNamePrimary, routerId, true);
302 LOG.warn("installIpv6PsNatMissEntryNonNaptSwitch: could not get tunnelInterface for {} on Switch {}",
303 primarySwitchId, dpnId);
306 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
307 listBucketInfo.add(0, bucketPrimary);
309 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : installSnatMissEntry called for dpnId {} with"
310 + " primaryBucket {} ", dpnId, listBucketInfo.get(0));
312 long groupId = createGroupIdForIpv6Router(getGroupIdKey(routerName + "IPv6"));
313 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll,
315 LOG.debug("installing the PSNAT to NAPTSwitch GroupEntity:{} with GroupId: {}", groupEntity, groupId);
316 mdsalManager.addGroup(confTx, groupEntity);
317 List<MatchInfo> matches = new ArrayList<>();
318 matches.add(MatchEthernetType.IPV6);
319 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
321 List<ActionInfo> actionsInfo = new ArrayList<>();
322 actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(routerId)));
323 actionsInfo.add(new ActionGroup(groupId));
324 List<InstructionInfo> instructions = new ArrayList<>();
325 instructions.add(new InstructionApplyActions(actionsInfo));
327 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
328 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef,
329 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
330 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
333 protected void removeIpv6PsNatMissEntryNonNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
334 BigInteger dpnId, Long routerId, String routerName, BigInteger primarySwitchId)
335 throws ExecutionException, InterruptedException {
336 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, installing SNAT miss entry in"
337 + " switch {} for router {}", dpnId, routerName);
338 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
339 List<BucketInfo> listBucketInfo = new ArrayList<>();
341 String ifNamePrimary = NatUtil.getTunnelInterfaceName(dpnId, primarySwitchId, itmManager);
342 if (ifNamePrimary != null) {
343 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, Primary Tunnel interface is {}",
345 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
346 interfaceManager, ifNamePrimary, routerId, true);
348 LOG.warn("installIpv6PsNatMissEntryNonNaptSwitch: could not get tunnelInterface for {} on Switch {}",
349 primarySwitchId, dpnId);
352 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
353 listBucketInfo.add(0, bucketPrimary);
355 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : installSnatMissEntry called for dpnId {} with"
356 + " primaryBucket {} ", dpnId, listBucketInfo.get(0));
358 long groupId = createGroupIdForIpv6Router(getGroupIdKey(routerName + "IPv6"));
359 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll,
361 LOG.debug("removing the PSNAT to NAPTSwitch GroupEntity:{} with GroupId: {}", groupEntity, groupId);
362 mdsalManager.removeGroup(confTx, groupEntity);
364 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
365 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef);
369 protected void addIpv6SnatMissEntryForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
370 BigInteger dpnId, Long routerId, BigInteger routerMetadata) {
371 LOG.debug("installIpv6SnatMissEntryForNaptSwitch {} called for routerId {}", dpnId, routerId);
372 List<MatchInfo> matches = new ArrayList<>();
373 matches.add(MatchEthernetType.IPV6);
374 matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
376 List<InstructionInfo> instructions = new ArrayList<>();
377 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
379 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
380 flowRef += ".Outbound";
381 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef,
382 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
383 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
386 protected void removeIpv6SnatMissEntryForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
387 BigInteger dpnId, Long routerId)
388 throws ExecutionException, InterruptedException {
389 LOG.debug("installIpv6SnatMissEntryForNaptSwitch {} called for routerId {}", dpnId, routerId);
390 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
391 flowRef += ".Outbound";
392 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef);
395 protected void addIpv6TerminatingServiceTblEntry(TypedReadWriteTransaction<Configuration> confTx,
396 BigInteger dpnId, Long routerId, BigInteger routerMetadata) {
397 LOG.debug("installIpv6TerminatingServiceTblEntry : creating entry for Terminating Service Table "
398 + "for switch {}, routerId {}", dpnId, routerId);
399 List<MatchInfo> matches = new ArrayList<>();
400 matches.add(MatchEthernetType.IPV6);
401 matches.add(new MatchTunnelId(BigInteger.valueOf(routerId)));
403 List<ActionInfo> actionsInfos = new ArrayList<>();
404 ActionNxLoadMetadata actionLoadMeta = new ActionNxLoadMetadata(routerMetadata, LOAD_START, LOAD_END);
405 actionsInfos.add(actionLoadMeta);
406 actionsInfos.add(new ActionNxResubmit(NwConstants.OUTBOUND_NAPT_TABLE));
407 List<InstructionInfo> instructions = new ArrayList<>();
408 instructions.add(new InstructionApplyActions(actionsInfos));
410 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
411 flowRef += ".Outbound";
412 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
413 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef,
414 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
418 protected void removeIpv6TerminatingServiceTblEntry(TypedReadWriteTransaction<Configuration> confTx,
419 BigInteger dpnId, Long routerId) throws ExecutionException, InterruptedException {
420 LOG.debug("installIpv6TerminatingServiceTblEntry : creating entry for Terminating Service Table "
421 + "for switch {}, routerId {}", dpnId, routerId);
422 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
423 flowRef += ".Outbound";
424 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef);
428 protected void addIpv6NaptPfibInboundFlow(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
429 long routerId, BigInteger routerMetadata) {
430 LOG.debug("installIpv6NaptPfibInboundFlow : called for dpnId {} and routerId {} ", dpnId, routerId);
431 List<MatchInfoBase> matches = new ArrayList<>();
432 matches.add(MatchEthernetType.IPV6);
433 matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
435 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
436 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
437 listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
438 listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
439 instructionInfo.add(new InstructionApplyActions(listActionInfo));
441 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
442 flowRef += ".Inbound";
443 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef,
444 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY,
445 flowRef, NwConstants.COOKIE_SNAT_TABLE,
446 matches, instructionInfo);
449 protected void removeIpv6NaptPfibInboundFlow(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
451 throws ExecutionException, InterruptedException {
452 LOG.debug("installIpv6NaptPfibInboundFlow : called for dpnId {} and routerId {} ", dpnId, routerId);
453 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
454 flowRef += ".Inbound";
455 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef);
458 protected long createGroupIdForIpv6Router(String groupIdKey) {
459 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
460 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
463 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
464 RpcResult<AllocateIdOutput> rpcResult = result.get();
465 return rpcResult.getResult().getIdValue();
466 } catch (NullPointerException | InterruptedException | ExecutionException e) {
467 LOG.error("createGroupIdForIPv6Router: Exception while creating group with key : {}", groupIdKey, e);
472 protected boolean routerHasIpv6ExtSubnet(Routers routers) {
473 for (ExternalIps externalIp : routers.getExternalIps()) {
474 if (!NWUtil.isIpv4Address(externalIp.getIpAddress())) {
475 LOG.debug("router {}, has an external IPv6 subnet {}",
476 routers.getRouterName(), externalIp.getIpAddress());
480 LOG.debug("router {}, does not have an external IPv6 subnet", routers.getRouterName());