2 * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. 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
9 package org.opendaylight.netvirt.natservice.internal;
11 import java.math.BigInteger;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.Future;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.controller.liblldp.NetUtils;
21 import org.opendaylight.controller.liblldp.PacketException;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
24 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
25 import org.opendaylight.genius.mdsalutil.ActionInfo;
26 import org.opendaylight.genius.mdsalutil.FlowEntity;
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.MetaDataUtil;
31 import org.opendaylight.genius.mdsalutil.NwConstants;
32 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
33 import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
34 import org.opendaylight.genius.mdsalutil.actions.ActionSetDestinationIp;
35 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
36 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
37 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldVlanVid;
38 import org.opendaylight.genius.mdsalutil.actions.ActionSetSourceIp;
39 import org.opendaylight.genius.mdsalutil.actions.ActionSetTcpDestinationPort;
40 import org.opendaylight.genius.mdsalutil.actions.ActionSetTcpSourcePort;
41 import org.opendaylight.genius.mdsalutil.actions.ActionSetUdpDestinationPort;
42 import org.opendaylight.genius.mdsalutil.actions.ActionSetUdpSourcePort;
43 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
44 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
45 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
46 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
47 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
48 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
49 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
50 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
51 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
52 import org.opendaylight.genius.mdsalutil.matches.MatchTcpDestinationPort;
53 import org.opendaylight.genius.mdsalutil.matches.MatchTcpSourcePort;
54 import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
55 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
56 import org.opendaylight.genius.mdsalutil.packet.Ethernet;
57 import org.opendaylight.genius.mdsalutil.packet.IPv4;
58 import org.opendaylight.genius.mdsalutil.packet.TCP;
59 import org.opendaylight.genius.mdsalutil.packet.UDP;
60 import org.opendaylight.netvirt.elanmanager.api.IElanService;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexOutput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
74 import org.opendaylight.yangtools.yang.common.RpcResult;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
79 public class NaptEventHandler {
80 private static final Logger LOG = LoggerFactory.getLogger(NaptEventHandler.class);
81 private final DataBroker dataBroker;
82 private static IMdsalApiManager mdsalManager;
83 private final PacketProcessingService pktService;
84 private final OdlInterfaceRpcService interfaceManagerRpc;
85 private final NaptManager naptManager;
86 private final IElanService elanManager;
87 private final IdManagerService idManager;
88 private IInterfaceManager interfaceManager;
91 public NaptEventHandler(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
92 final NaptManager naptManager,
93 final PacketProcessingService pktService,
94 final OdlInterfaceRpcService interfaceManagerRpc,
95 final IInterfaceManager interfaceManager,
96 final IElanService elanManager,
97 final IdManagerService idManager) {
98 this.dataBroker = dataBroker;
99 NaptEventHandler.mdsalManager = mdsalManager;
100 this.naptManager = naptManager;
101 this.pktService = pktService;
102 this.interfaceManagerRpc = interfaceManagerRpc;
103 this.interfaceManager = interfaceManager;
104 this.elanManager = elanManager;
105 this.idManager = idManager;
108 // TODO Clean up the exception handling
109 @SuppressWarnings("checkstyle:IllegalCatch")
110 public void handleEvent(NAPTEntryEvent naptEntryEvent) {
112 Flow programming logic of the OUTBOUND NAPT TABLE :
113 1) Get the internal IP address, port number, router ID from the event.
114 2) Use the NAPT service getExternalAddressMapping() to get the External IP and the port.
115 3) Build the flow for replacing the Internal IP and port with the External IP and port.
116 a) Write the matching criteria.
117 b) Match the router ID in the metadata.
118 d) Write the VPN ID to the metadata.
119 e) Write the other data.
120 f) Set the apply actions instruction with the action setfield.
121 4) Write the flow to the OUTBOUND NAPT Table and forward to FIB table for routing the traffic.
123 Flow programming logic of the INBOUND NAPT TABLE :
124 Same as Outbound table logic except that :
125 1) Build the flow for replacing the External IP and port with the Internal IP and port.
126 2) Match the VPN ID in the metadata.
127 3) Write the router ID to the metadata.
128 5) Write the flow to the INBOUND NAPT Table and forward to FIB table for routing the traffic.
131 Long routerId = naptEntryEvent.getRouterId();
132 LOG.info("NAT Service : handleEvent() entry for IP {}, port {}, routerID {}",
133 naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
135 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
136 long bgpVpnId = NatConstants.INVALID_ID;
138 LOG.warn("NAT Service : dpnId is null. Assuming the router ID {} as the BGP VPN ID and proceeding....",
141 LOG.debug("NAT Service : BGP VPN ID {}", bgpVpnId);
142 String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
143 String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
144 if (routerName == null) {
145 LOG.error("NAT Service: Unable to find router for VpnName {}", vpnName);
148 routerId = NatUtil.getVpnId(dataBroker, routerName);
149 LOG.debug("NAT Service : Router ID {}", routerId);
150 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
152 LOG.error("NAT Service : dpnId is null for the router {}", routerId);
156 if (naptEntryEvent.getOperation() == NAPTEntryEvent.Operation.ADD) {
157 LOG.debug("NAT Service : Inside Add operation of NaptEventHandler");
158 // Get the External Gateway MAC Address
159 String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
160 if (extGwMacAddress != null) {
161 LOG.debug("NAT Service : External Gateway MAC address {} found for External Router ID {}",
162 extGwMacAddress, routerId);
164 LOG.error("NAT Service : No External Gateway MAC address found for External Router ID {}",
168 //Get the external network ID from the ExternalRouter model
169 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
170 if (networkId == null) {
171 LOG.error("NAT Service : networkId is null");
175 //Get the VPN ID from the ExternalNetworks model
176 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
177 if (vpnUuid == null) {
178 LOG.error("NAT Service : vpnUuid is null");
181 Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
183 //Get the internal IpAddress, internal port number from the event
184 String internalIpAddress = naptEntryEvent.getIpAddress();
185 int internalPort = naptEntryEvent.getPortNumber();
186 SessionAddress internalAddress = new SessionAddress(internalIpAddress, internalPort);
187 NAPTEntryEvent.Protocol protocol = naptEntryEvent.getProtocol();
189 //Get the external IP address for the corresponding internal IP address
190 SessionAddress externalAddress =
191 naptManager.getExternalAddressMapping(routerId, internalAddress, naptEntryEvent.getProtocol());
192 if (externalAddress == null) {
193 LOG.error("NAT Service : externalAddress is null");
196 // Build and install the NAPT translation flows in the Outbound and Inbound NAPT tables
197 if (!naptEntryEvent.isPktProcessed()) {
198 Long vpnIdFromExternalSubnet = getVpnIdFromExternalSubnet(dataBroker, routerId,
199 externalAddress.getIpAddress());
200 if (vpnIdFromExternalSubnet != NatConstants.INVALID_ID) {
201 vpnId = vpnIdFromExternalSubnet;
204 // Added External Gateway MAC Address
205 buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId,
206 externalAddress, internalAddress, protocol, extGwMacAddress);
207 buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId,
208 internalAddress, externalAddress, protocol, extGwMacAddress);
211 //Send Packetout - tcp or udp packets which got punted to controller.
212 BigInteger metadata = naptEntryEvent.getPacketReceived().getMatch().getMetadata().getMetadata();
213 byte[] inPayload = naptEntryEvent.getPacketReceived().getPayload();
214 Ethernet ethPkt = new Ethernet();
215 if (inPayload != null) {
217 ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
218 } catch (Exception e) {
219 LOG.warn("NAT Service : Failed to decode Packet", e);
225 long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
226 LOG.debug("NAT Service : portTag from incoming packet is {}", portTag);
227 String interfaceName = getInterfaceNameFromTag(portTag);
228 LOG.debug("NAT Service : interfaceName fetched from portTag is {}", interfaceName);
229 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
230 .interfaces.Interface iface = null;
232 iface = interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName);
234 LOG.error("NAT Service : Unable to read interface {} from config DataStore", interfaceName);
237 IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
238 if (ifL2vlan != null && ifL2vlan.getVlanId() != null) {
239 vlanId = ifL2vlan.getVlanId().getValue() == null ? 0 : ifL2vlan.getVlanId().getValue();
241 InterfaceInfo infInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(interfaceName);
242 if (infInfo != null) {
243 LOG.debug("NAT Service : portName fetched from interfaceManager is {}", infInfo.getPortName());
246 byte[] pktOut = buildNaptPacketOut(ethPkt);
248 List<ActionInfo> actionInfos = new ArrayList<>();
249 if (ethPkt.getPayload() instanceof IPv4) {
250 IPv4 ipPkt = (IPv4) ethPkt.getPayload();
251 if ((ipPkt.getPayload() instanceof TCP) || (ipPkt.getPayload() instanceof UDP)) {
252 if (ethPkt.getEtherType() != (short) NwConstants.ETHTYPE_802_1Q) {
254 if (infInfo != null) {
255 LOG.debug("NAT Service : vlanId is {}", vlanId);
258 actionInfos.add(new ActionPushVlan(0));
259 actionInfos.add(new ActionSetFieldVlanVid(1, vlanId));
261 LOG.debug("NAT Service : No vlanId {}, may be untagged", vlanId);
264 LOG.error("NAT Service : error in getting interfaceInfo");
269 LOG.debug("NAT Service : This is VLAN Trunk port case - need not do VLAN tagging again");
273 if (pktOut != null) {
274 String routerName = NatUtil.getRouterName(dataBroker, routerId);
275 long tunId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, routerId,
277 sendNaptPacketOut(pktOut, infInfo, actionInfos, tunId);
279 LOG.warn("NAT Service : Unable to send Packet Out");
283 LOG.debug("NAT Service : Inside delete Operation of NaptEventHandler");
284 removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, naptEntryEvent.getIpAddress(),
285 naptEntryEvent.getPortNumber());
288 LOG.info("NAT Service : handleNaptEvent() exited for IP {}, port {}, routerID : {}",
289 naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
290 } catch (Exception e) {
291 LOG.error("NAT Service :Exception in NaptEventHandler.handleEvent() payload {}", naptEntryEvent, e);
295 public static void buildAndInstallNatFlows(BigInteger dpnId, short tableId, long vpnId, long routerId,
296 long bgpVpnId, SessionAddress actualSourceAddress,
297 SessionAddress translatedSourceAddress,
298 NAPTEntryEvent.Protocol protocol, String extGwMacAddress) {
299 LOG.debug("NAT Service : Build and install NAPT flows in InBound and OutBound tables for "
300 + "dpnId {} and routerId {}", dpnId, routerId);
301 //Build the flow for replacing the actual IP and port with the translated IP and port.
303 if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
304 idleTimeout = NatConstants.DEFAULT_NAPT_IDLE_TIMEOUT;
307 if (bgpVpnId != NatConstants.INVALID_ID) {
308 intranetVpnId = bgpVpnId;
310 intranetVpnId = routerId;
312 LOG.debug("NAT Service : Intranet VPN ID {}", intranetVpnId);
313 LOG.debug("NAT Service : Router ID {}", routerId);
314 String translatedIp = translatedSourceAddress.getIpAddress();
315 int translatedPort = translatedSourceAddress.getPortNumber();
316 String actualIp = actualSourceAddress.getIpAddress();
317 int actualPort = actualSourceAddress.getPortNumber();
318 String switchFlowRef =
319 NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), actualIp, actualPort);
320 FlowEntity snatFlowEntity = MDSALUtil.buildFlowEntity(dpnId, tableId, switchFlowRef,
321 NatConstants.DEFAULT_NAPT_FLOW_PRIORITY, NatConstants.NAPT_FLOW_NAME, idleTimeout, 0,
322 NatUtil.getCookieNaptFlow(routerId),
323 buildAndGetMatchInfo(actualIp, actualPort, tableId, protocol, intranetVpnId),
324 buildAndGetSetActionInstructionInfo(translatedIp, translatedPort, intranetVpnId, vpnId, tableId,
325 protocol, extGwMacAddress));
326 snatFlowEntity.setSendFlowRemFlag(true);
328 LOG.debug("NAT Service : Installing the NAPT flow in the table {} for the switch with the DPN ID {} ",
330 mdsalManager.syncInstallFlow(snatFlowEntity, 1);
331 LOG.trace("NAT Service : Exited buildAndInstallNatflows");
334 private static List<MatchInfo> buildAndGetMatchInfo(String ip, int port, short tableId,
335 NAPTEntryEvent.Protocol protocol, long segmentId) {
336 MatchInfo ipMatchInfo = null;
337 MatchInfo portMatchInfo = null;
338 MatchInfo protocolMatchInfo = null;
339 InetAddress ipAddress = null;
340 String ipAddressAsString = null;
342 ipAddress = InetAddress.getByName(ip);
343 ipAddressAsString = ipAddress.getHostAddress();
345 } catch (UnknownHostException e) {
346 LOG.error("NAT Service : UnknowHostException in buildAndGetMatchInfo. Failed to build NAPT Flow for "
347 + "ip {}", ipAddress);
351 MatchInfo metaDataMatchInfo = null;
352 if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
353 ipMatchInfo = new MatchIpv4Source(ipAddressAsString, "32");
354 if (protocol == NAPTEntryEvent.Protocol.TCP) {
355 protocolMatchInfo = MatchIpProtocol.TCP;
356 portMatchInfo = new MatchTcpSourcePort(port);
357 } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
358 protocolMatchInfo = MatchIpProtocol.UDP;
359 portMatchInfo = new MatchUdpSourcePort(port);
362 new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID);
364 ipMatchInfo = new MatchIpv4Destination(ipAddressAsString, "32");
365 if (protocol == NAPTEntryEvent.Protocol.TCP) {
366 protocolMatchInfo = MatchIpProtocol.TCP;
367 portMatchInfo = new MatchTcpDestinationPort(port);
368 } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
369 protocolMatchInfo = MatchIpProtocol.UDP;
370 portMatchInfo = new MatchUdpDestinationPort(port);
372 //metaDataMatchInfo = new MatchMetadata(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID);
374 ArrayList<MatchInfo> matchInfo = new ArrayList<>();
375 matchInfo.add(MatchEthernetType.IPV4);
376 matchInfo.add(ipMatchInfo);
377 matchInfo.add(protocolMatchInfo);
378 matchInfo.add(portMatchInfo);
379 if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
380 matchInfo.add(metaDataMatchInfo);
385 private static List<InstructionInfo> buildAndGetSetActionInstructionInfo(String ipAddress, int port,
386 long segmentId, long vpnId,
388 NAPTEntryEvent.Protocol protocol,
389 String extGwMacAddress) {
390 ActionInfo ipActionInfo = null;
391 ActionInfo macActionInfo = null;
392 ActionInfo portActionInfo = null;
393 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
394 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
396 case NwConstants.OUTBOUND_NAPT_TABLE:
397 ipActionInfo = new ActionSetSourceIp(ipAddress);
398 // Added External Gateway MAC Address
399 macActionInfo = new ActionSetFieldEthernetSource(new MacAddress(extGwMacAddress));
400 if (protocol == NAPTEntryEvent.Protocol.TCP) {
401 portActionInfo = new ActionSetTcpSourcePort(port);
402 } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
403 portActionInfo = new ActionSetUdpSourcePort(port);
405 // reset the split-horizon bit to allow traffic from tunnel to be sent back to the provider port
406 instructionInfo.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnId),
407 MetaDataUtil.METADATA_MASK_VRFID.or(MetaDataUtil.METADATA_MASK_SH_FLAG)));
410 case NwConstants.INBOUND_NAPT_TABLE:
411 ipActionInfo = new ActionSetDestinationIp(ipAddress);
412 if (protocol == NAPTEntryEvent.Protocol.TCP) {
413 portActionInfo = new ActionSetTcpDestinationPort(port);
414 } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
415 portActionInfo = new ActionSetUdpDestinationPort(port);
417 instructionInfo.add(new InstructionWriteMetadata(
418 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID));
422 LOG.error("NAT Service : Neither OUTBOUND_NAPT_TABLE nor INBOUND_NAPT_TABLE matches with "
423 + "input table id {}", tableId);
427 listActionInfo.add(ipActionInfo);
428 listActionInfo.add(portActionInfo);
429 if (macActionInfo != null) {
430 listActionInfo.add(macActionInfo);
431 LOG.debug("NAT Service : External GW MAC Address {} is found ", macActionInfo);
433 instructionInfo.add(new InstructionApplyActions(listActionInfo));
434 instructionInfo.add(new InstructionGotoTable(NwConstants.NAPT_PFIB_TABLE));
436 return instructionInfo;
439 void removeNatFlows(BigInteger dpnId, short tableId ,long segmentId, String ip, int port) {
440 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
441 LOG.error("NAT Service : DPN ID {} is invalid" , dpnId);
443 LOG.debug("NAT Service : Remove NAPT flows for dpnId {}, segmentId {}, ip {} and port {} ",
444 dpnId, segmentId, ip, port);
446 //Build the flow with the port IP and port as the match info.
447 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(segmentId), ip, port);
448 FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
449 LOG.debug("NAT Service : Remove the flow in the table {} for the switch with the DPN ID {}",
450 NwConstants.INBOUND_NAPT_TABLE, dpnId);
451 mdsalManager.removeFlow(snatFlowEntity);
455 protected byte[] buildNaptPacketOut(Ethernet etherPkt) {
456 LOG.debug("NAT Service : About to build Napt Packet Out");
457 if (etherPkt.getPayload() instanceof IPv4) {
459 IPv4 ipPkt = (IPv4) etherPkt.getPayload();
460 if ((ipPkt.getPayload() instanceof TCP) || (ipPkt.getPayload() instanceof UDP)) {
462 rawPkt = etherPkt.serialize();
464 } catch (PacketException e2) {
465 LOG.error("failed to build NAPT Packet out ", e2);
469 LOG.error("NAT Service : Unable to build NaptPacketOut since its neither TCP nor UDP");
473 LOG.error("NAT Service : Unable to build NaptPacketOut since its not IPv4 packet");
477 private void sendNaptPacketOut(byte[] pktOut, InterfaceInfo infInfo, List<ActionInfo> actionInfos, Long tunId) {
478 LOG.trace("NAT Service: Sending packet out DpId {}, interfaceInfo {}", infInfo.getDpId(), infInfo);
479 // set inPort, and action as OFPP_TABLE so that it starts from table 0 (lowest table as per spec)
480 actionInfos.add(new ActionSetFieldTunnelId(2, BigInteger.valueOf(tunId)));
481 actionInfos.add(new ActionOutput(3, new Uri("0xfffffff9")));
482 NodeConnectorRef inPort = MDSALUtil.getNodeConnRef(infInfo.getDpId(), String.valueOf(infInfo.getPortNo()));
483 LOG.debug("NAT Service : inPort for packetout is being set to {}", String.valueOf(infInfo.getPortNo()));
484 TransmitPacketInput output = MDSALUtil.getPacketOut(actionInfos, pktOut, infInfo.getDpId().longValue(), inPort);
485 LOG.trace("NAT Service: Transmitting packet: {}",output);
486 this.pktService.transmitPacket(output);
489 private String getInterfaceNameFromTag(long portTag) {
490 String interfaceName = null;
491 GetInterfaceFromIfIndexInput input =
492 new GetInterfaceFromIfIndexInputBuilder().setIfIndex((int) portTag).build();
493 Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput =
494 interfaceManagerRpc.getInterfaceFromIfIndex(input);
496 GetInterfaceFromIfIndexOutput output = futureOutput.get().getResult();
497 interfaceName = output.getInterfaceName();
498 } catch (InterruptedException | ExecutionException e) {
499 LOG.error("NAT Service : Error while retrieving the interfaceName from tag using "
500 + "getInterfaceFromIfIndex RPC");
502 LOG.trace("NAT Service : Returning interfaceName {} for tag {} form getInterfaceNameFromTag",
503 interfaceName, portTag);
504 return interfaceName;
507 private long getVpnIdFromExternalSubnet(DataBroker dataBroker, Long routerId, String externalIpAddress) {
508 String routerName = NatUtil.getRouterName(dataBroker, routerId);
509 if (routerName != null) {
510 Routers extRouter = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
511 if (extRouter != null) {
512 return NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIpAddress, extRouter);
516 return NatConstants.INVALID_ID;