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 LOG.info("Ipv6ForwardingService: {} init", getClass().getSimpleName());
93 public boolean addCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx,
94 Routers routers, BigInteger primarySwitchId) {
95 String routerName = routers.getRouterName();
96 LOG.info("handleSnatAllSwitch : invoked for router {} with NAPTSwitch {} for {} flows",
97 routerName, primarySwitchId, "installing");
98 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
100 * Primary switch handled separately since the pseudo port created may
101 * not be present in the switch list on delete.
103 addCentralizedRouter(confTx, routers, primarySwitchId, primarySwitchId);
104 for (BigInteger dpnId : switches) {
105 if (!Objects.equals(primarySwitchId, dpnId)) {
106 addCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
113 public boolean addCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx,
114 Routers routers, BigInteger primarySwitchId, BigInteger dpnId) {
115 Long routerId = NatUtil.getVpnId(dataBroker, routers.getRouterName());
116 BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
118 if (!dpnId.equals(primarySwitchId)) {
119 LOG.info("handleSnat (non-NAPTSwitch) : {} flows on switch {} for router {}",
120 "Installing", dpnId, routers.getRouterName());
121 // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
122 addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
124 // Currently we are only programming flows when ext-net has an IPv6Subnet
125 if (routerHasIpv6ExtSubnet(routers)) {
126 // Program flows on non-NAPTSwitch to send N/S packets to the NAPTSwitch
127 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routers.getRouterName(),
131 LOG.info("handleSnat (NAPTSwitch) : {} flows on switch {} for router {}",
132 "Installing", dpnId, routers.getRouterName());
133 // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
134 addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
136 // Program flows from PSNAT_TABLE(26) to OUTBOUND_NAPT_TABLE(46) (egress direction)
137 addIpv6SnatMissEntryForNaptSwitch(confTx, dpnId, routerId, routerMetadata);
139 // Program flows in INTERNAL_TUNNEL_TABLE(36) for packets coming from non-NAPTSwitch (egress direction)
140 addIpv6TerminatingServiceTblEntry(confTx, dpnId, routerId, routerMetadata);
142 // Program flows from NAPT_PFIB_TABLE(47) to FIB_TABLE(21) (ingress direction)
143 addIpv6NaptPfibInboundFlow(confTx, dpnId, routerId, routerMetadata);
145 // Now installing flows that use SubnetInfo
146 ipv6SubnetFlowProgrammer. addSubnetSpecificFlows(confTx, dpnId, routerId, routers, routerMetadata);
152 public boolean removeCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx,
153 Routers routers, BigInteger primarySwitchId) throws ExecutionException, InterruptedException {
154 String routerName = routers.getRouterName();
155 LOG.info("handleSnatAllSwitch : invoked for router {} with NAPTSwitch {} for {} flows",
156 routerName, primarySwitchId, "removing");
157 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
159 * Primary switch handled separately since the pseudo port created may
160 * not be present in the switch list on delete.
162 removeCentralizedRouter(confTx, routers, primarySwitchId, primarySwitchId);
163 for (BigInteger dpnId : switches) {
164 if (!Objects.equals(primarySwitchId, dpnId)) {
165 removeCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
172 public boolean removeCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx,
173 Routers routers, BigInteger primarySwitchId, BigInteger dpnId)
174 throws ExecutionException, InterruptedException {
175 Long routerId = NatUtil.getVpnId(dataBroker, routers.getRouterName());
176 BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
178 if (!dpnId.equals(primarySwitchId)) {
179 LOG.info("handleSnat (non-NAPTSwitch) : {} flows on switch {} for router {}",
180 "Removing", dpnId, routers.getRouterName());
181 // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
182 addIpv6DefaultFibRoute(confTx, dpnId, routerId, routerMetadata);
184 // Currently we are only programming flows when ext-net has an IPv6Subnet
185 if (routerHasIpv6ExtSubnet(routers)) {
186 // Program flows on non-NAPTSwitch to send N/S packets to the NAPTSwitch
187 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routers.getRouterName(),
191 LOG.info("handleSnat (NAPTSwitch) : {} flows on switch {} for router {}",
192 "Removing", dpnId, routers.getRouterName());
193 // Program default flow from FIB_TABLE(21) to PSNAT_TABLE(26) (egress direction)
194 removeIpv6DefaultFibRoute(confTx, dpnId, routerId);
196 // Program flows from PSNAT_TABLE(26) to OUTBOUND_NAPT_TABLE(46) (egress direction)
197 removeIpv6SnatMissEntryForNaptSwitch(confTx, dpnId, routerId);
199 // Program flows in INTERNAL_TUNNEL_TABLE(36) for packets coming from non-NAPTSwitch (egress direction)
200 removeIpv6TerminatingServiceTblEntry(confTx, dpnId, routerId);
202 // Program flows from NAPT_PFIB_TABLE(47) to FIB_TABLE(21) (ingress direction)
203 removeIpv6NaptPfibInboundFlow(confTx, dpnId, routerId);
205 // Now installing flows that use SubnetInfo
206 ipv6SubnetFlowProgrammer.removeSubnetSpecificFlows(confTx, dpnId, routerId, routers);
212 public boolean handleRouterUpdate(TypedReadWriteTransaction<Configuration> confTx,
213 Routers origRouter, Routers updatedRouter) throws ExecutionException, InterruptedException {
214 LOG.info("handleRouterUpdate : originalRouter {}, updatedRouter {}", origRouter, updatedRouter);
215 String routerName = origRouter.getRouterName();
216 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
217 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
218 BigInteger routerMetadata = MetaDataUtil.getVpnIdMetadata(routerId);
220 // If the external network is updated with an IPv6Subnet, program the necessary flows on non-NAPTSwitch
221 if (!routerHasIpv6ExtSubnet(origRouter) && routerHasIpv6ExtSubnet(updatedRouter)) {
222 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
223 for (BigInteger dpnId : switches) {
224 if (!Objects.equals(primarySwitchId, dpnId)) {
225 LOG.info("handleRouterUpdate (non-NAPTSwitch) : Installing flows on switch {} for router {}",
227 addIpv6PsNatMissEntryNonNaptSwitch(confTx, dpnId, routerId, routerName,
233 ipv6SubnetFlowProgrammer.removeSubnetSpecificFlows(confTx, primarySwitchId, routerId, origRouter);
234 ipv6SubnetFlowProgrammer.addSubnetSpecificFlows(confTx, primarySwitchId, routerId, updatedRouter,
240 public boolean addSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
241 BigInteger primarySwitchId) {
246 public boolean addSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
247 BigInteger primarySwitchId, BigInteger dpnId) {
252 public boolean removeSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
253 BigInteger primarySwitchId) throws ExecutionException, InterruptedException {
258 public boolean removeSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
259 BigInteger primarySwitchId, BigInteger dpnId) throws ExecutionException, InterruptedException {
264 protected void addIpv6DefaultFibRoute(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
265 Long routerId, BigInteger routerMetadata) {
266 LOG.debug("installIpv6DefaultFibRoute : Installing default FIB route to PSNAT_TABLE on {}", dpnId);
267 List<MatchInfo> matches = new ArrayList<>();
268 matches.add(MatchEthernetType.IPV6);
269 matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
271 List<InstructionInfo> instructions = new ArrayList<>();
272 instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
274 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.L3_FIB_TABLE, routerId);
275 flowRef += ".Outbound";
276 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.L3_FIB_TABLE, flowRef,
277 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef,
278 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
281 protected void removeIpv6DefaultFibRoute(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
282 Long routerId) throws ExecutionException, InterruptedException {
283 LOG.debug("installIpv6DefaultFibRoute : Installing default FIB route to PSNAT_TABLE on {}", dpnId);
284 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.L3_FIB_TABLE, routerId);
285 flowRef += ".Outbound";
286 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.L3_FIB_TABLE, flowRef);
289 protected void addIpv6PsNatMissEntryNonNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
290 BigInteger dpnId, Long routerId, String routerName, BigInteger primarySwitchId) {
291 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, installing SNAT miss entry in"
292 + " switch {} for router {}", dpnId, routerName);
293 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
294 List<BucketInfo> listBucketInfo = new ArrayList<>();
296 String ifNamePrimary = NatUtil.getTunnelInterfaceName(dpnId, primarySwitchId, itmManager);
297 if (ifNamePrimary != null) {
298 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, Primary Tunnel interface is {}",
300 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
301 interfaceManager, ifNamePrimary, routerId, true);
303 LOG.warn("installIpv6PsNatMissEntryNonNaptSwitch: could not get tunnelInterface for {} on Switch {}",
304 primarySwitchId, dpnId);
307 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
308 listBucketInfo.add(0, bucketPrimary);
310 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : installSnatMissEntry called for dpnId {} with"
311 + " primaryBucket {} ", dpnId, listBucketInfo.get(0));
313 long groupId = createGroupIdForIpv6Router(getGroupIdKey(routerName + "IPv6"));
314 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll,
316 LOG.debug("installing the PSNAT to NAPTSwitch GroupEntity:{} with GroupId: {}", groupEntity, groupId);
317 mdsalManager.addGroup(confTx, groupEntity);
318 List<MatchInfo> matches = new ArrayList<>();
319 matches.add(MatchEthernetType.IPV6);
320 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
322 List<ActionInfo> actionsInfo = new ArrayList<>();
323 actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(routerId)));
324 actionsInfo.add(new ActionGroup(groupId));
325 List<InstructionInfo> instructions = new ArrayList<>();
326 instructions.add(new InstructionApplyActions(actionsInfo));
328 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
329 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef,
330 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
331 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
334 protected void removeIpv6PsNatMissEntryNonNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
335 BigInteger dpnId, Long routerId, String routerName, BigInteger primarySwitchId)
336 throws ExecutionException, InterruptedException {
337 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, installing SNAT miss entry in"
338 + " switch {} for router {}", dpnId, routerName);
339 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
340 List<BucketInfo> listBucketInfo = new ArrayList<>();
342 String ifNamePrimary = NatUtil.getTunnelInterfaceName(dpnId, primarySwitchId, itmManager);
343 if (ifNamePrimary != null) {
344 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : On Non-Napt Switch, Primary Tunnel interface is {}",
346 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
347 interfaceManager, ifNamePrimary, routerId, true);
349 LOG.warn("installIpv6PsNatMissEntryNonNaptSwitch: could not get tunnelInterface for {} on Switch {}",
350 primarySwitchId, dpnId);
353 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
354 listBucketInfo.add(0, bucketPrimary);
356 LOG.debug("installIpv6PsNatMissEntryNonNaptSwitch : installSnatMissEntry called for dpnId {} with"
357 + " primaryBucket {} ", dpnId, listBucketInfo.get(0));
359 long groupId = createGroupIdForIpv6Router(getGroupIdKey(routerName + "IPv6"));
360 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll,
362 LOG.debug("removing the PSNAT to NAPTSwitch GroupEntity:{} with GroupId: {}", groupEntity, groupId);
363 mdsalManager.removeGroup(confTx, groupEntity);
365 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
366 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef);
370 protected void addIpv6SnatMissEntryForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
371 BigInteger dpnId, Long routerId, BigInteger routerMetadata) {
372 LOG.debug("installIpv6SnatMissEntryForNaptSwitch {} called for routerId {}", dpnId, routerId);
373 List<MatchInfo> matches = new ArrayList<>();
374 matches.add(MatchEthernetType.IPV6);
375 matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
377 List<InstructionInfo> instructions = new ArrayList<>();
378 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
380 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
381 flowRef += ".Outbound";
382 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef,
383 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
384 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
387 protected void removeIpv6SnatMissEntryForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
388 BigInteger dpnId, Long routerId)
389 throws ExecutionException, InterruptedException {
390 LOG.debug("installIpv6SnatMissEntryForNaptSwitch {} called for routerId {}", dpnId, routerId);
391 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
392 flowRef += ".Outbound";
393 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef);
396 protected void addIpv6TerminatingServiceTblEntry(TypedReadWriteTransaction<Configuration> confTx,
397 BigInteger dpnId, Long routerId, BigInteger routerMetadata) {
398 LOG.debug("installIpv6TerminatingServiceTblEntry : creating entry for Terminating Service Table "
399 + "for switch {}, routerId {}", dpnId, routerId);
400 List<MatchInfo> matches = new ArrayList<>();
401 matches.add(MatchEthernetType.IPV6);
402 matches.add(new MatchTunnelId(BigInteger.valueOf(routerId)));
404 List<ActionInfo> actionsInfos = new ArrayList<>();
405 ActionNxLoadMetadata actionLoadMeta = new ActionNxLoadMetadata(routerMetadata, LOAD_START, LOAD_END);
406 actionsInfos.add(actionLoadMeta);
407 actionsInfos.add(new ActionNxResubmit(NwConstants.OUTBOUND_NAPT_TABLE));
408 List<InstructionInfo> instructions = new ArrayList<>();
409 instructions.add(new InstructionApplyActions(actionsInfos));
411 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
412 flowRef += ".Outbound";
413 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
414 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef,
415 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
419 protected void removeIpv6TerminatingServiceTblEntry(TypedReadWriteTransaction<Configuration> confTx,
420 BigInteger dpnId, Long routerId) throws ExecutionException, InterruptedException {
421 LOG.debug("installIpv6TerminatingServiceTblEntry : creating entry for Terminating Service Table "
422 + "for switch {}, routerId {}", dpnId, routerId);
423 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
424 flowRef += ".Outbound";
425 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef);
429 protected void addIpv6NaptPfibInboundFlow(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
430 long routerId, BigInteger routerMetadata) {
431 LOG.debug("installIpv6NaptPfibInboundFlow : called for dpnId {} and routerId {} ", dpnId, routerId);
432 List<MatchInfoBase> matches = new ArrayList<>();
433 matches.add(MatchEthernetType.IPV6);
434 matches.add(new MatchMetadata(routerMetadata, MetaDataUtil.METADATA_MASK_VRFID));
436 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
437 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
438 listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
439 listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
440 instructionInfo.add(new InstructionApplyActions(listActionInfo));
442 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
443 flowRef += ".Inbound";
444 NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef,
445 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY,
446 flowRef, NwConstants.COOKIE_SNAT_TABLE,
447 matches, instructionInfo);
450 protected void removeIpv6NaptPfibInboundFlow(TypedReadWriteTransaction<Configuration> confTx, BigInteger dpnId,
452 throws ExecutionException, InterruptedException {
453 LOG.debug("installIpv6NaptPfibInboundFlow : called for dpnId {} and routerId {} ", dpnId, routerId);
454 String flowRef = NatUtil.getIpv6FlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
455 flowRef += ".Inbound";
456 NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef);
459 protected long createGroupIdForIpv6Router(String groupIdKey) {
460 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
461 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
464 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
465 RpcResult<AllocateIdOutput> rpcResult = result.get();
466 return rpcResult.getResult().getIdValue();
467 } catch (NullPointerException | InterruptedException | ExecutionException e) {
468 LOG.error("createGroupIdForIPv6Router: Exception while creating group with key : {}", groupIdKey, e);
473 protected boolean routerHasIpv6ExtSubnet(Routers routers) {
474 for (ExternalIps externalIp : routers.getExternalIps()) {
475 if (!NWUtil.isIpv4Address(externalIp.getIpAddress())) {
476 LOG.debug("router {}, has an external IPv6 subnet {}",
477 routers.getRouterName(), externalIp.getIpAddress());
481 LOG.debug("router {}, does not have an external IPv6 subnet", routers.getRouterName());