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.FlowEntityBuilder;
28 import org.opendaylight.genius.mdsalutil.InstructionInfo;
29 import org.opendaylight.genius.mdsalutil.MDSALUtil;
30 import org.opendaylight.genius.mdsalutil.MatchInfo;
31 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
32 import org.opendaylight.genius.mdsalutil.NwConstants;
33 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
34 import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
35 import org.opendaylight.genius.mdsalutil.actions.ActionSetDestinationIp;
36 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
37 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
38 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldVlanVid;
39 import org.opendaylight.genius.mdsalutil.actions.ActionSetSourceIp;
40 import org.opendaylight.genius.mdsalutil.actions.ActionSetTcpDestinationPort;
41 import org.opendaylight.genius.mdsalutil.actions.ActionSetTcpSourcePort;
42 import org.opendaylight.genius.mdsalutil.actions.ActionSetUdpDestinationPort;
43 import org.opendaylight.genius.mdsalutil.actions.ActionSetUdpSourcePort;
44 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
45 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
46 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
47 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
48 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
49 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
50 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
51 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
52 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
53 import org.opendaylight.genius.mdsalutil.matches.MatchTcpDestinationPort;
54 import org.opendaylight.genius.mdsalutil.matches.MatchTcpSourcePort;
55 import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
56 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
57 import org.opendaylight.genius.mdsalutil.packet.Ethernet;
58 import org.opendaylight.genius.mdsalutil.packet.IPv4;
59 import org.opendaylight.genius.mdsalutil.packet.TCP;
60 import org.opendaylight.genius.mdsalutil.packet.UDP;
61 import org.opendaylight.netvirt.elanmanager.api.IElanService;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexOutput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
75 import org.opendaylight.yangtools.yang.common.RpcResult;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
80 public class NaptEventHandler {
81 private static final Logger LOG = LoggerFactory.getLogger(NaptEventHandler.class);
82 private final DataBroker dataBroker;
83 private static IMdsalApiManager mdsalManager;
84 private final PacketProcessingService pktService;
85 private final OdlInterfaceRpcService interfaceManagerRpc;
86 private final NaptManager naptManager;
87 private final IElanService elanManager;
88 private final IdManagerService idManager;
89 private final IInterfaceManager interfaceManager;
92 public NaptEventHandler(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
93 final NaptManager naptManager,
94 final PacketProcessingService pktService,
95 final OdlInterfaceRpcService interfaceManagerRpc,
96 final IInterfaceManager interfaceManager,
97 final IElanService elanManager,
98 final IdManagerService idManager) {
99 this.dataBroker = dataBroker;
100 NaptEventHandler.mdsalManager = mdsalManager;
101 this.naptManager = naptManager;
102 this.pktService = pktService;
103 this.interfaceManagerRpc = interfaceManagerRpc;
104 this.interfaceManager = interfaceManager;
105 this.elanManager = elanManager;
106 this.idManager = idManager;
109 // TODO Clean up the exception handling
110 @SuppressWarnings("checkstyle:IllegalCatch")
111 public void handleEvent(NAPTEntryEvent naptEntryEvent) {
113 Flow programming logic of the OUTBOUND NAPT TABLE :
114 1) Get the internal IP address, port number, router ID from the event.
115 2) Use the NAPT service getExternalAddressMapping() to get the External IP and the port.
116 3) Build the flow for replacing the Internal IP and port with the External IP and port.
117 a) Write the matching criteria.
118 b) Match the router ID in the metadata.
119 d) Write the VPN ID to the metadata.
120 e) Write the other data.
121 f) Set the apply actions instruction with the action setfield.
122 4) Write the flow to the OUTBOUND NAPT Table and forward to FIB table for routing the traffic.
124 Flow programming logic of the INBOUND NAPT TABLE :
125 Same as Outbound table logic except that :
126 1) Build the flow for replacing the External IP and port with the Internal IP and port.
127 2) Match the VPN ID in the metadata.
128 3) Write the router ID to the metadata.
129 5) Write the flow to the INBOUND NAPT Table and forward to FIB table for routing the traffic.
132 Long routerId = naptEntryEvent.getRouterId();
133 LOG.info("NAT Service : handleEvent() entry for IP {}, port {}, routerID {}",
134 naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
136 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
137 long bgpVpnId = NatConstants.INVALID_ID;
139 LOG.warn("NAT Service : dpnId is null. Assuming the router ID {} as the BGP VPN ID and proceeding....",
142 LOG.debug("NAT Service : BGP VPN ID {}", bgpVpnId);
143 String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
144 String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
145 if (routerName == null) {
146 LOG.error("NAT Service: Unable to find router for VpnName {}", vpnName);
149 routerId = NatUtil.getVpnId(dataBroker, routerName);
150 LOG.debug("NAT Service : Router ID {}", routerId);
151 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
153 LOG.error("NAT Service : dpnId is null for the router {}", routerId);
157 if (naptEntryEvent.getOperation() == NAPTEntryEvent.Operation.ADD) {
158 LOG.debug("NAT Service : Inside Add operation of NaptEventHandler");
159 // Get the External Gateway MAC Address
160 String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
161 if (extGwMacAddress != null) {
162 LOG.debug("NAT Service : External Gateway MAC address {} found for External Router ID {}",
163 extGwMacAddress, routerId);
165 LOG.error("NAT Service : No External Gateway MAC address found for External Router ID {}",
169 //Get the external network ID from the ExternalRouter model
170 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
171 if (networkId == null) {
172 LOG.error("NAT Service : networkId is null");
176 //Get the VPN ID from the ExternalNetworks model
177 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
178 if (vpnUuid == null) {
179 LOG.error("NAT Service : vpnUuid is null");
182 Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
184 //Get the internal IpAddress, internal port number from the event
185 String internalIpAddress = naptEntryEvent.getIpAddress();
186 int internalPort = naptEntryEvent.getPortNumber();
187 SessionAddress internalAddress = new SessionAddress(internalIpAddress, internalPort);
188 NAPTEntryEvent.Protocol protocol = naptEntryEvent.getProtocol();
190 //Get the external IP address for the corresponding internal IP address
191 SessionAddress externalAddress =
192 naptManager.getExternalAddressMapping(routerId, internalAddress, naptEntryEvent.getProtocol());
193 if (externalAddress == null) {
194 LOG.error("NAT Service : externalAddress is null");
197 // Build and install the NAPT translation flows in the Outbound and Inbound NAPT tables
198 if (!naptEntryEvent.isPktProcessed()) {
199 Long vpnIdFromExternalSubnet = getVpnIdFromExternalSubnet(dataBroker, routerId,
200 externalAddress.getIpAddress());
201 if (vpnIdFromExternalSubnet != NatConstants.INVALID_ID) {
202 vpnId = vpnIdFromExternalSubnet;
205 // Added External Gateway MAC Address
206 buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId,
207 externalAddress, internalAddress, protocol, extGwMacAddress);
208 buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId,
209 internalAddress, externalAddress, protocol, extGwMacAddress);
212 //Send Packetout - tcp or udp packets which got punted to controller.
213 BigInteger metadata = naptEntryEvent.getPacketReceived().getMatch().getMetadata().getMetadata();
214 byte[] inPayload = naptEntryEvent.getPacketReceived().getPayload();
215 Ethernet ethPkt = new Ethernet();
216 if (inPayload != null) {
218 ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
219 } catch (Exception e) {
220 LOG.warn("NAT Service : Failed to decode Packet", e);
226 long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
227 LOG.debug("NAT Service : portTag from incoming packet is {}", portTag);
228 String interfaceName = getInterfaceNameFromTag(portTag);
229 LOG.debug("NAT Service : interfaceName fetched from portTag is {}", interfaceName);
230 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
231 .interfaces.Interface iface = null;
233 iface = interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName);
235 LOG.error("NAT Service : Unable to read interface {} from config DataStore", interfaceName);
238 IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
239 if (ifL2vlan != null && ifL2vlan.getVlanId() != null) {
240 vlanId = ifL2vlan.getVlanId().getValue() == null ? 0 : ifL2vlan.getVlanId().getValue();
242 InterfaceInfo infInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(interfaceName);
243 if (infInfo != null) {
244 LOG.debug("NAT Service : portName fetched from interfaceManager is {}", infInfo.getPortName());
247 byte[] pktOut = buildNaptPacketOut(ethPkt);
249 List<ActionInfo> actionInfos = new ArrayList<>();
250 if (ethPkt.getPayload() instanceof IPv4) {
251 IPv4 ipPkt = (IPv4) ethPkt.getPayload();
252 if (ipPkt.getPayload() instanceof TCP || ipPkt.getPayload() instanceof UDP) {
253 if (ethPkt.getEtherType() != (short) NwConstants.ETHTYPE_802_1Q) {
255 if (infInfo != null) {
256 LOG.debug("NAT Service : vlanId is {}", vlanId);
259 actionInfos.add(new ActionPushVlan(0));
260 actionInfos.add(new ActionSetFieldVlanVid(1, vlanId));
262 LOG.debug("NAT Service : No vlanId {}, may be untagged", vlanId);
265 LOG.error("NAT Service : error in getting interfaceInfo");
270 LOG.debug("NAT Service : This is VLAN Trunk port case - need not do VLAN tagging again");
274 if (pktOut != null) {
275 String routerName = NatUtil.getRouterName(dataBroker, routerId);
276 long tunId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, routerId,
278 sendNaptPacketOut(pktOut, infInfo, actionInfos, tunId);
280 LOG.warn("NAT Service : Unable to send Packet Out");
284 LOG.debug("NAT Service : Inside delete Operation of NaptEventHandler");
285 removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, naptEntryEvent.getIpAddress(),
286 naptEntryEvent.getPortNumber());
289 LOG.info("NAT Service : handleNaptEvent() exited for IP {}, port {}, routerID : {}",
290 naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
291 } catch (Exception e) {
292 LOG.error("NAT Service :Exception in NaptEventHandler.handleEvent() payload {}", naptEntryEvent, e);
296 public static void buildAndInstallNatFlows(BigInteger dpnId, short tableId, long vpnId, long routerId,
297 long bgpVpnId, SessionAddress actualSourceAddress,
298 SessionAddress translatedSourceAddress,
299 NAPTEntryEvent.Protocol protocol, String extGwMacAddress) {
300 LOG.debug("NAT Service : Build and install NAPT flows in InBound and OutBound tables for "
301 + "dpnId {} and routerId {}", dpnId, routerId);
302 //Build the flow for replacing the actual IP and port with the translated IP and port.
304 if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
305 idleTimeout = NatConstants.DEFAULT_NAPT_IDLE_TIMEOUT;
308 if (bgpVpnId != NatConstants.INVALID_ID) {
309 intranetVpnId = bgpVpnId;
311 intranetVpnId = routerId;
313 LOG.debug("NAT Service : Intranet VPN ID {}", intranetVpnId);
314 LOG.debug("NAT Service : Router ID {}", routerId);
315 String translatedIp = translatedSourceAddress.getIpAddress();
316 int translatedPort = translatedSourceAddress.getPortNumber();
317 String actualIp = actualSourceAddress.getIpAddress();
318 int actualPort = actualSourceAddress.getPortNumber();
319 String switchFlowRef =
320 NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), actualIp, actualPort);
322 FlowEntity snatFlowEntity = new FlowEntityBuilder()
325 .setFlowId(switchFlowRef)
326 .setPriority(NatConstants.DEFAULT_NAPT_FLOW_PRIORITY)
327 .setFlowName(NatConstants.NAPT_FLOW_NAME)
328 .setIdleTimeOut(idleTimeout)
330 .setCookie(NatUtil.getCookieNaptFlow(routerId))
331 .setMatchInfoList(buildAndGetMatchInfo(actualIp, actualPort, tableId, protocol, intranetVpnId))
332 .setInstructionInfoList(buildAndGetSetActionInstructionInfo(translatedIp, translatedPort,
333 intranetVpnId, vpnId, tableId, protocol, extGwMacAddress))
334 .setSendFlowRemFlag(true)
337 LOG.debug("NAT Service : Installing the NAPT flow in the table {} for the switch with the DPN ID {} ",
339 mdsalManager.syncInstallFlow(snatFlowEntity, 1);
340 LOG.trace("NAT Service : Exited buildAndInstallNatflows");
343 private static List<MatchInfo> buildAndGetMatchInfo(String ip, int port, short tableId,
344 NAPTEntryEvent.Protocol protocol, long segmentId) {
345 MatchInfo ipMatchInfo = null;
346 MatchInfo portMatchInfo = null;
347 MatchInfo protocolMatchInfo = null;
348 InetAddress ipAddress = null;
349 String ipAddressAsString = null;
351 ipAddress = InetAddress.getByName(ip);
352 ipAddressAsString = ipAddress.getHostAddress();
354 } catch (UnknownHostException e) {
355 LOG.error("NAT Service : UnknowHostException in buildAndGetMatchInfo. Failed to build NAPT Flow for "
356 + "ip {}", ipAddress);
360 MatchInfo metaDataMatchInfo = null;
361 if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
362 ipMatchInfo = new MatchIpv4Source(ipAddressAsString, "32");
363 if (protocol == NAPTEntryEvent.Protocol.TCP) {
364 protocolMatchInfo = MatchIpProtocol.TCP;
365 portMatchInfo = new MatchTcpSourcePort(port);
366 } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
367 protocolMatchInfo = MatchIpProtocol.UDP;
368 portMatchInfo = new MatchUdpSourcePort(port);
371 new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID);
373 ipMatchInfo = new MatchIpv4Destination(ipAddressAsString, "32");
374 if (protocol == NAPTEntryEvent.Protocol.TCP) {
375 protocolMatchInfo = MatchIpProtocol.TCP;
376 portMatchInfo = new MatchTcpDestinationPort(port);
377 } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
378 protocolMatchInfo = MatchIpProtocol.UDP;
379 portMatchInfo = new MatchUdpDestinationPort(port);
381 //metaDataMatchInfo = new MatchMetadata(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID);
383 ArrayList<MatchInfo> matchInfo = new ArrayList<>();
384 matchInfo.add(MatchEthernetType.IPV4);
385 matchInfo.add(ipMatchInfo);
386 matchInfo.add(protocolMatchInfo);
387 matchInfo.add(portMatchInfo);
388 if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
389 matchInfo.add(metaDataMatchInfo);
394 private static List<InstructionInfo> buildAndGetSetActionInstructionInfo(String ipAddress, int port,
395 long segmentId, long vpnId,
397 NAPTEntryEvent.Protocol protocol,
398 String extGwMacAddress) {
399 ActionInfo ipActionInfo = null;
400 ActionInfo macActionInfo = null;
401 ActionInfo portActionInfo = null;
402 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
403 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
405 case NwConstants.OUTBOUND_NAPT_TABLE:
406 ipActionInfo = new ActionSetSourceIp(ipAddress);
407 // Added External Gateway MAC Address
408 macActionInfo = new ActionSetFieldEthernetSource(new MacAddress(extGwMacAddress));
409 if (protocol == NAPTEntryEvent.Protocol.TCP) {
410 portActionInfo = new ActionSetTcpSourcePort(port);
411 } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
412 portActionInfo = new ActionSetUdpSourcePort(port);
414 // reset the split-horizon bit to allow traffic from tunnel to be sent back to the provider port
415 instructionInfo.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnId),
416 MetaDataUtil.METADATA_MASK_VRFID.or(MetaDataUtil.METADATA_MASK_SH_FLAG)));
419 case NwConstants.INBOUND_NAPT_TABLE:
420 ipActionInfo = new ActionSetDestinationIp(ipAddress);
421 if (protocol == NAPTEntryEvent.Protocol.TCP) {
422 portActionInfo = new ActionSetTcpDestinationPort(port);
423 } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
424 portActionInfo = new ActionSetUdpDestinationPort(port);
426 instructionInfo.add(new InstructionWriteMetadata(
427 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID));
431 LOG.error("NAT Service : Neither OUTBOUND_NAPT_TABLE nor INBOUND_NAPT_TABLE matches with "
432 + "input table id {}", tableId);
436 listActionInfo.add(ipActionInfo);
437 listActionInfo.add(portActionInfo);
438 if (macActionInfo != null) {
439 listActionInfo.add(macActionInfo);
440 LOG.debug("NAT Service : External GW MAC Address {} is found ", macActionInfo);
442 instructionInfo.add(new InstructionApplyActions(listActionInfo));
443 instructionInfo.add(new InstructionGotoTable(NwConstants.NAPT_PFIB_TABLE));
445 return instructionInfo;
448 void removeNatFlows(BigInteger dpnId, short tableId ,long segmentId, String ip, int port) {
449 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
450 LOG.error("NAT Service : DPN ID {} is invalid" , dpnId);
452 LOG.debug("NAT Service : Remove NAPT flows for dpnId {}, segmentId {}, ip {} and port {} ",
453 dpnId, segmentId, ip, port);
455 //Build the flow with the port IP and port as the match info.
456 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(segmentId), ip, port);
457 FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
458 LOG.debug("NAT Service : Remove the flow in the table {} for the switch with the DPN ID {}",
459 NwConstants.INBOUND_NAPT_TABLE, dpnId);
460 mdsalManager.removeFlow(snatFlowEntity);
464 protected byte[] buildNaptPacketOut(Ethernet etherPkt) {
465 LOG.debug("NAT Service : About to build Napt Packet Out");
466 if (etherPkt.getPayload() instanceof IPv4) {
468 IPv4 ipPkt = (IPv4) etherPkt.getPayload();
469 if (ipPkt.getPayload() instanceof TCP || ipPkt.getPayload() instanceof UDP) {
471 rawPkt = etherPkt.serialize();
473 } catch (PacketException e2) {
474 LOG.error("failed to build NAPT Packet out ", e2);
478 LOG.error("NAT Service : Unable to build NaptPacketOut since its neither TCP nor UDP");
482 LOG.error("NAT Service : Unable to build NaptPacketOut since its not IPv4 packet");
486 private void sendNaptPacketOut(byte[] pktOut, InterfaceInfo infInfo, List<ActionInfo> actionInfos, Long tunId) {
487 LOG.trace("NAT Service: Sending packet out DpId {}, interfaceInfo {}", infInfo.getDpId(), infInfo);
488 // set inPort, and action as OFPP_TABLE so that it starts from table 0 (lowest table as per spec)
489 actionInfos.add(new ActionSetFieldTunnelId(2, BigInteger.valueOf(tunId)));
490 actionInfos.add(new ActionOutput(3, new Uri("0xfffffff9")));
491 NodeConnectorRef inPort = MDSALUtil.getNodeConnRef(infInfo.getDpId(), String.valueOf(infInfo.getPortNo()));
492 LOG.debug("NAT Service : inPort for packetout is being set to {}", String.valueOf(infInfo.getPortNo()));
493 TransmitPacketInput output = MDSALUtil.getPacketOut(actionInfos, pktOut, infInfo.getDpId().longValue(), inPort);
494 LOG.trace("NAT Service: Transmitting packet: {}",output);
495 this.pktService.transmitPacket(output);
498 private String getInterfaceNameFromTag(long portTag) {
499 String interfaceName = null;
500 GetInterfaceFromIfIndexInput input =
501 new GetInterfaceFromIfIndexInputBuilder().setIfIndex((int) portTag).build();
502 Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput =
503 interfaceManagerRpc.getInterfaceFromIfIndex(input);
505 GetInterfaceFromIfIndexOutput output = futureOutput.get().getResult();
506 interfaceName = output.getInterfaceName();
507 } catch (InterruptedException | ExecutionException e) {
508 LOG.error("NAT Service : Error while retrieving the interfaceName from tag using "
509 + "getInterfaceFromIfIndex RPC");
511 LOG.trace("NAT Service : Returning interfaceName {} for tag {} form getInterfaceNameFromTag",
512 interfaceName, portTag);
513 return interfaceName;
516 private long getVpnIdFromExternalSubnet(DataBroker dataBroker, Long routerId, String externalIpAddress) {
517 String routerName = NatUtil.getRouterName(dataBroker, routerId);
518 if (routerName != null) {
519 Routers extRouter = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
520 if (extRouter != null) {
521 return NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIpAddress, extRouter);
525 return NatConstants.INVALID_ID;