/*
- * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
package org.opendaylight.netvirt.natservice.internal;
-import org.opendaylight.genius.mdsalutil.*;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.PacketException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
-import org.opendaylight.genius.interfacemanager.globals.VlanInterfaceInfo;
import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
+import org.opendaylight.genius.mdsalutil.ActionInfo;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
+import org.opendaylight.genius.mdsalutil.FlowEntityBuilder;
+import org.opendaylight.genius.mdsalutil.InstructionInfo;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MetaDataUtil;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
+import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetDestinationIp;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldVlanVid;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetSourceIp;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetTcpDestinationPort;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetTcpSourcePort;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetUdpDestinationPort;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetUdpSourcePort;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
+import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
+import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
+import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
+import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
+import org.opendaylight.genius.mdsalutil.matches.MatchTcpDestinationPort;
+import org.opendaylight.genius.mdsalutil.matches.MatchTcpSourcePort;
+import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
+import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
import org.opendaylight.genius.mdsalutil.packet.Ethernet;
-import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
import org.opendaylight.genius.mdsalutil.packet.IPv4;
import org.opendaylight.genius.mdsalutil.packet.TCP;
import org.opendaylight.genius.mdsalutil.packet.UDP;
-import org.opendaylight.controller.liblldp.NetUtils;
-import org.opendaylight.controller.liblldp.PacketException;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
+import org.opendaylight.netvirt.natservice.internal.NaptPacketInHandler.NatPacketProcessingState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+@Singleton
public class NaptEventHandler {
- private NaptManager naptManager;
private static final Logger LOG = LoggerFactory.getLogger(NaptEventHandler.class);
+ private final DataBroker dataBroker;
private static IMdsalApiManager mdsalManager;
- private DataBroker dataBroker;
- private PacketProcessingService pktService;
- private OdlInterfaceRpcService interfaceManagerRpc;
- private IInterfaceManager interfaceManager;
-
- public NaptEventHandler(final DataBroker dataBroker) {
+ private final PacketProcessingService pktService;
+ private final OdlInterfaceRpcService interfaceManagerRpc;
+ private final NaptManager naptManager;
+ private final IElanService elanManager;
+ private final IdManagerService idManager;
+ private final IInterfaceManager interfaceManager;
+ private static SalFlowService salFlowServiceRpc;
+
+ @Inject
+ public NaptEventHandler(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
+ final NaptManager naptManager,
+ final PacketProcessingService pktService,
+ final OdlInterfaceRpcService interfaceManagerRpc,
+ final IInterfaceManager interfaceManager,
+ final IElanService elanManager,
+ final IdManagerService idManager,
+ final SalFlowService salFlowServiceRpc) {
this.dataBroker = dataBroker;
- }
-
- public void setInterfaceManager(IInterfaceManager interfaceManager) {
- this.interfaceManager = interfaceManager;
- }
-
- public void setMdsalManager(IMdsalApiManager mdsalManager) {
- this.mdsalManager = mdsalManager;
- }
-
- public void setNaptManager(NaptManager naptManager) {
+ NaptEventHandler.mdsalManager = mdsalManager;
this.naptManager = naptManager;
- }
-
- public void setPacketProcessingService(PacketProcessingService packetService) {
- this.pktService = packetService;
- }
-
- public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
- LOG.trace("Registered interfaceManager successfully");;
+ this.pktService = pktService;
this.interfaceManagerRpc = interfaceManagerRpc;
+ this.interfaceManager = interfaceManager;
+ this.elanManager = elanManager;
+ this.idManager = idManager;
+ this.salFlowServiceRpc = salFlowServiceRpc;
}
-
- public void handleEvent(NAPTEntryEvent naptEntryEvent){
+ // TODO Clean up the exception handling
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ public void handleEvent(NAPTEntryEvent naptEntryEvent) {
/*
Flow programming logic of the OUTBOUND NAPT TABLE :
1) Get the internal IP address, port number, router ID from the event.
3) Write the router ID to the metadata.
5) Write the flow to the INBOUND NAPT Table and forward to FIB table for routing the traffic.
*/
- Long routerId = naptEntryEvent.getRouterId();
- LOG.info("NAT Service : handleEvent() entry for IP {}, port {}, routerID {}", naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
-
- //Get the DPN ID
- BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
- long bgpVpnId = NatConstants.INVALID_ID;
- if(dpnId == null ){
- LOG.warn("NAT Service : dpnId is null. Assuming the router ID {} as the BGP VPN ID and proceeding....", routerId);
- bgpVpnId = routerId;
- LOG.debug("NAT Service : BGP VPN ID {}", bgpVpnId);
- String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
- String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
- routerId = NatUtil.getVpnId(dataBroker, routerName);
- LOG.debug("NAT Service : Router ID {}", routerId);
- dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
- if(dpnId == null){
- LOG.error("NAT Service : dpnId is null for the router {}", routerId);
- return;
- }
- }
- if(naptEntryEvent.getOperation() == NAPTEntryEvent.Operation.ADD) {
- LOG.debug("NAT Service : Inside Add operation of NaptEventHandler");
-
- //Get the external network ID from the ExternalRouter model
- Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
- if(networkId == null ){
- LOG.error("NAT Service : networkId is null");
- return;
- }
-
- //Get the VPN ID from the ExternalNetworks model
- Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
- if(vpnUuid == null ){
- LOG.error("NAT Service : vpnUuid is null");
- return;
- }
- Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
-
- //Get the internal IpAddress, internal port number from the event
- String internalIpAddress = naptEntryEvent.getIpAddress();
- int internalPort = naptEntryEvent.getPortNumber();
- SessionAddress internalAddress = new SessionAddress(internalIpAddress, internalPort);
- NAPTEntryEvent.Protocol protocol = naptEntryEvent.getProtocol();
-
- //Get the external IP address for the corresponding internal IP address
- SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, naptEntryEvent.getProtocol());
- if(externalAddress == null ){
- if(externalAddress == null){
- LOG.error("NAT Service : externalAddress is null");
+ try {
+ Long routerId = naptEntryEvent.getRouterId();
+ LOG.trace("handleEvent : Time Elapsed before procesing snat ({}:{}) packet is {} ms,"
+ + "routerId: {},isPktProcessed:{}", naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(),
+ (System.currentTimeMillis() - naptEntryEvent.getObjectCreationTime()),
+ routerId, naptEntryEvent.isPktProcessed());
+ //Get the DPN ID
+ BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ long bgpVpnId = NatConstants.INVALID_ID;
+ if (dpnId == null) {
+ LOG.warn("handleEvent : dpnId is null. Assuming the router ID {} as the BGP VPN ID and proceeding....",
+ routerId);
+ bgpVpnId = routerId;
+ LOG.debug("handleEvent : BGP VPN ID {}", bgpVpnId);
+ String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
+ String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
+ if (routerName == null) {
+ LOG.error("handleEvent : Unable to find router for VpnName {}", vpnName);
return;
}
- }
- //Build and install the NAPT translation flows in the Outbound and Inbound NAPT tables
- if(!naptEntryEvent.isPktProcessed()) {
- buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId, internalAddress, externalAddress, protocol);
- buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId, externalAddress, internalAddress, protocol);
- }
-
- //Send Packetout - tcp or udp packets which got punted to controller.
- BigInteger metadata = naptEntryEvent.getPacketReceived().getMatch().getMetadata().getMetadata();
- byte[] inPayload = naptEntryEvent.getPacketReceived().getPayload();
- Ethernet ethPkt = new Ethernet();
- if (inPayload != null) {
- try {
- ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
- } catch (Exception e) {
- LOG.warn("Failed to decode Packet", e);
+ routerId = NatUtil.getVpnId(dataBroker, routerName);
+ LOG.debug("handleEvent : Router ID {}", routerId);
+ dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ if (dpnId == null) {
+ LOG.error("handleEvent : dpnId is null for the router {}", routerId);
return;
}
}
+ if (naptEntryEvent.getOperation() == NAPTEntryEvent.Operation.ADD) {
+ LOG.debug("handleEvent : Inside Add operation of NaptEventHandler");
+ // Build and install the NAPT translation flows in the Outbound and Inbound NAPT tables
+ if (!naptEntryEvent.isPktProcessed()) {
- long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
- LOG.debug("NAT Service : portTag from incoming packet is {}", portTag);
- String interfaceName = getInterfaceNameFromTag(portTag);
- LOG.debug("NAT Service : interfaceName fetched from portTag is {}", interfaceName);
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface = null;
- long vlanId =0;
- iface = interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName);
- if(iface == null) {
- LOG.error("NAT Service : Unable to read interface {} from config DataStore", interfaceName);
- return;
- }
- IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
- if(ifL2vlan != null && ifL2vlan.getVlanId() !=null){
- vlanId = ifL2vlan.getVlanId().getValue() == null ? 0 : ifL2vlan.getVlanId().getValue();
- }
- InterfaceInfo infInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(interfaceName);
- if(infInfo !=null) {
- LOG.debug("NAT Service : portName fetched from interfaceManager is {}", infInfo.getPortName());
- }
-
- byte[] pktOut = buildNaptPacketOut(ethPkt);
-
- List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
- if (ethPkt.getPayload() instanceof IPv4) {
- IPv4 ipPkt = (IPv4) ethPkt.getPayload();
- if ((ipPkt.getPayload() instanceof TCP) || (ipPkt.getPayload() instanceof UDP) ) {
- if (ethPkt.getEtherType() != (short)NwConstants.ETHTYPE_802_1Q) {
- // VLAN Access port
- if(infInfo != null) {
- LOG.debug("NAT Service : vlanId is {}", vlanId);
- if(vlanId != 0) {
- // Push vlan
- actionInfos.add(new ActionInfo(ActionType.push_vlan, new String[] {}, 0));
- actionInfos.add(new ActionInfo(ActionType.set_field_vlan_vid,
- new String[] { Long.toString(vlanId) }, 1));
- } else {
- LOG.debug("NAT Service : No vlanId {}, may be untagged", vlanId);
- }
- } else {
- LOG.error("NAT Service : error in getting interfaceInfo");
- return;
- }
+ // Get the External Gateway MAC Address
+ String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
+ if (extGwMacAddress != null) {
+ LOG.debug("handleEvent : External Gateway MAC address {} found for External Router ID {}",
+ extGwMacAddress, routerId);
} else {
- // VLAN Trunk Port
- LOG.debug("NAT Service : This is VLAN Trunk port case - need not do VLAN tagging again");
+ LOG.error("handleEvent : No External Gateway MAC address found for External Router ID {}",
+ routerId);
+ return;
+ }
+ //Get the external network ID from the ExternalRouter model
+ Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
+ if (networkId == null) {
+ LOG.error("handleEvent : networkId is null");
+ return;
+ }
+
+ //Get the VPN ID from the ExternalNetworks model
+ Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
+ if (vpnUuid == null) {
+ LOG.error("handleEvent : vpnUuid is null");
+ return;
+ }
+ Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
+
+ //Get the internal IpAddress, internal port number from the event
+ String internalIpAddress = naptEntryEvent.getIpAddress();
+ int internalPort = naptEntryEvent.getPortNumber();
+ SessionAddress internalAddress = new SessionAddress(internalIpAddress, internalPort);
+ NAPTEntryEvent.Protocol protocol = naptEntryEvent.getProtocol();
+
+ //Get the external IP address for the corresponding internal IP address
+ SessionAddress externalAddress =
+ naptManager.getExternalAddressMapping(routerId, internalAddress,
+ naptEntryEvent.getProtocol());
+ if (externalAddress == null) {
+ LOG.error("handleEvent : externalAddress is null");
+ return;
+ }
+
+ Long vpnIdFromExternalSubnet = getVpnIdFromExternalSubnet(dataBroker, routerId,
+ externalAddress.getIpAddress());
+ if (vpnIdFromExternalSubnet != NatConstants.INVALID_ID) {
+ vpnId = vpnIdFromExternalSubnet;
}
+
+ // Added External Gateway MAC Address
+ Future<RpcResult<AddFlowOutput>> addFlowResult =
+ buildAndInstallNatFlowsOptionalRpc(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnId, routerId,
+ bgpVpnId, externalAddress, internalAddress, protocol, extGwMacAddress, true);
+ final BigInteger finalDpnId = dpnId;
+ final Long finalVpnId = vpnId;
+ final Long finalRouterId = routerId;
+ final long finalBgpVpnId = bgpVpnId;
+ Futures.addCallback(JdkFutureAdapters.listenInPoolThread(addFlowResult),
+ new FutureCallback<RpcResult<AddFlowOutput>>() {
+
+ @Override
+ public void onSuccess(@Nullable RpcResult<AddFlowOutput> result) {
+ LOG.debug("handleEvent : Configured inbound rule for {} to {}",
+ internalAddress, externalAddress);
+ Future<RpcResult<AddFlowOutput>> addFlowResult =
+ buildAndInstallNatFlowsOptionalRpc(finalDpnId,
+ NwConstants.OUTBOUND_NAPT_TABLE, finalVpnId, finalRouterId,
+ finalBgpVpnId, internalAddress, externalAddress, protocol,
+ extGwMacAddress, true);
+ Futures.addCallback(JdkFutureAdapters.listenInPoolThread(addFlowResult),
+ new FutureCallback<RpcResult<AddFlowOutput>>() {
+
+ @Override
+ public void onSuccess(@Nullable RpcResult<AddFlowOutput> result) {
+ LOG.debug("handleEvent : Configured outbound rule, sending packet out"
+ + "from {} to {}", internalAddress, externalAddress);
+ prepareAndSendPacketOut(naptEntryEvent, finalRouterId);
+ }
+
+ @Override
+ public void onFailure(@Nonnull Throwable throwable) {
+ LOG.error("handleEvent : Error configuring outbound "
+ + "SNAT flows using RPC for SNAT connection from {} to {}",
+ internalAddress, externalAddress);
+ }
+ });
+ }
+
+ @Override
+ public void onFailure(@Nonnull Throwable throwable) {
+ LOG.error("handleEvent : Error configuring inbound SNAT flows "
+ + "using RPC for SNAT connection from {} to {}",
+ internalAddress, externalAddress);
+ }
+ });
+ String key = naptEntryEvent.getRouterId() + NatConstants.COLON_SEPARATOR
+ + naptEntryEvent.getIpAddress() + NatConstants.COLON_SEPARATOR
+ + naptEntryEvent.getPortNumber();
+ NatPacketProcessingState state = NaptPacketInHandler.INCOMING_PACKET_MAP.get(key);
+ state.setFlowInstalledTime(System.currentTimeMillis());
+ } else {
+ prepareAndSendPacketOut(naptEntryEvent, routerId);
}
- }
- if(pktOut != null) {
- sendNaptPacketOut(pktOut, infInfo, actionInfos, routerId);
+ LOG.trace("handleEvent : Time elapsed after Processsing snat ({}:{}) packet: {}ms,isPktProcessed:{} ",
+ naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(),
+ (System.currentTimeMillis() - naptEntryEvent.getObjectCreationTime()),
+ naptEntryEvent.isPktProcessed());
} else {
- LOG.warn("NAT Service : Unable to send Packet Out");
+ LOG.debug("handleEvent : Inside delete Operation of NaptEventHandler");
+ removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, naptEntryEvent.getIpAddress(),
+ naptEntryEvent.getPortNumber());
+ LOG.info("handleEvent : exited for removeEvent for IP {}, port {}, routerID : {}",
+ naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
+ }
+ } catch (Exception e) {
+ LOG.error("handleEvent :Exception in NaptEventHandler.handleEvent() payload {}", naptEntryEvent, e);
+ }
+ }
+
+ private void prepareAndSendPacketOut(NAPTEntryEvent naptEntryEvent, Long routerId) {
+ //Send Packetout - tcp or udp packets which got punted to controller.
+ BigInteger metadata = naptEntryEvent.getPacketReceived().getMatch().getMetadata().getMetadata();
+ byte[] inPayload = naptEntryEvent.getPacketReceived().getPayload();
+ Ethernet ethPkt = new Ethernet();
+ if (inPayload != null) {
+ try {
+ ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
+ } catch (PacketException e) {
+ LOG.error("prepareAndSendPacketOut : Failed to decode Packet", e);
+ return;
}
+ }
+
+ long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
+ LOG.debug("prepareAndSendPacketOut : portTag from incoming packet is {}", portTag);
+ String interfaceName = getInterfaceNameFromTag(portTag);
+ LOG.debug("prepareAndSendPacketOut : interfaceName fetched from portTag is {}", interfaceName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
+ .interfaces.Interface iface = null;
+ int vlanId = 0;
+ iface = interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName);
+ if (iface == null) {
+ LOG.error("prepareAndSendPacketOut : Unable to read interface {} from config DataStore", interfaceName);
+ return;
+ }
+ List<ActionInfo> actionInfos = new ArrayList<>();
+ IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
+ if (ifL2vlan != null && ifL2vlan.getVlanId() != null) {
+ vlanId = ifL2vlan.getVlanId().getValue() == null ? 0 : ifL2vlan.getVlanId().getValue();
+ }
+ InterfaceInfo infInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(interfaceName);
+ if (infInfo == null) {
+ LOG.error("prepareAndSendPacketOut : error in getting interfaceInfo from Operation DS");
+ return;
+ }
- }else{
- LOG.debug("NAT Service : Inside delete Operation of NaptEventHandler");
- removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber());
+ byte[] pktOut = buildNaptPacketOut(ethPkt);
+ if (ethPkt.getEtherType() != (short) NwConstants.ETHTYPE_802_1Q) {
+ // VLAN Access port
+ LOG.debug("prepareAndSendPacketOut : vlanId is {}", vlanId);
+ if (vlanId != 0) {
+ // Push vlan
+ actionInfos.add(new ActionPushVlan(0));
+ actionInfos.add(new ActionSetFieldVlanVid(1, vlanId));
+ } else {
+ LOG.debug("prepareAndSendPacketOut : No vlanId {}, may be untagged", vlanId);
+ }
+ } else {
+ // VLAN Trunk Port
+ LOG.debug("prepareAndSendPacketOut : This is VLAN Trunk port case - need not do VLAN tagging again");
}
+ if (pktOut != null) {
+ String routerName = NatUtil.getRouterName(dataBroker, routerId);
+ long tunId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, routerId,
+ routerName);
+ sendNaptPacketOut(pktOut, infInfo, actionInfos, tunId);
+ } else {
+ LOG.warn("prepareAndSendPacketOut : Unable to send Packet Out");
+ }
+ }
- LOG.info("NAT Service : handleNaptEvent() exited for IP, port, routerID : {}", naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
+ public static void buildAndInstallNatFlows(BigInteger dpnId, short tableId, long vpnId, long routerId,
+ long bgpVpnId, SessionAddress actualSourceAddress,
+ SessionAddress translatedSourceAddress,
+ NAPTEntryEvent.Protocol protocol, String extGwMacAddress) {
+ buildAndInstallNatFlowsOptionalRpc(dpnId, tableId, vpnId, routerId, bgpVpnId, actualSourceAddress,
+ translatedSourceAddress, protocol, extGwMacAddress, false);
}
- public static void buildAndInstallNatFlows(BigInteger dpnId, short tableId, long vpnId, long routerId, long bgpVpnId, SessionAddress actualSourceAddress,
- SessionAddress translatedSourceAddress, NAPTEntryEvent.Protocol protocol){
- LOG.debug("NAT Service : Build and install NAPT flows in InBound and OutBound tables for dpnId {} and routerId {}", dpnId, routerId);
+ public static Future<RpcResult<AddFlowOutput>> buildAndInstallNatFlowsOptionalRpc(
+ BigInteger dpnId, short tableId, long vpnId, long routerId, long bgpVpnId,
+ SessionAddress actualSourceAddress, SessionAddress translatedSourceAddress,
+ NAPTEntryEvent.Protocol protocol, String extGwMacAddress,
+ boolean sendRpc) {
+ LOG.debug("buildAndInstallNatFlowsOptionalRpc : Build and install table={} flow on dpnId {} and routerId {}",
+ tableId, dpnId, routerId);
//Build the flow for replacing the actual IP and port with the translated IP and port.
- String actualIp = actualSourceAddress.getIpAddress();
- int actualPort = actualSourceAddress.getPortNumber();
- String translatedIp = translatedSourceAddress.getIpAddress();
- String translatedPort = String.valueOf(translatedSourceAddress.getPortNumber());
- int idleTimeout=0;
- if(tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
+ int idleTimeout = 0;
+ if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
idleTimeout = NatConstants.DEFAULT_NAPT_IDLE_TIMEOUT;
}
- long metaDataValue = routerId;
- String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(metaDataValue), actualIp, actualPort);
-
long intranetVpnId;
- if(bgpVpnId != NatConstants.INVALID_ID){
+ if (bgpVpnId != NatConstants.INVALID_ID) {
intranetVpnId = bgpVpnId;
- }else{
+ } else {
intranetVpnId = routerId;
}
- LOG.debug("NAT Service : Intranet VPN ID {}", intranetVpnId);
- LOG.debug("NAT Service : Router ID {}", routerId);
- FlowEntity snatFlowEntity = MDSALUtil.buildFlowEntity(dpnId, tableId, switchFlowRef, NatConstants.DEFAULT_NAPT_FLOW_PRIORITY, NatConstants.NAPT_FLOW_NAME,
- idleTimeout, 0, NatUtil.getCookieNaptFlow(metaDataValue), buildAndGetMatchInfo(actualIp, actualPort, tableId, protocol, intranetVpnId, vpnId),
- buildAndGetSetActionInstructionInfo(translatedIp, translatedPort, intranetVpnId, vpnId, tableId, protocol));
+ LOG.debug("buildAndInstallNatFlowsOptionalRpc : Intranet VPN ID {} Router ID {}", intranetVpnId, routerId);
+ String translatedIp = translatedSourceAddress.getIpAddress();
+ int translatedPort = translatedSourceAddress.getPortNumber();
+ String actualIp = actualSourceAddress.getIpAddress();
+ int actualPort = actualSourceAddress.getPortNumber();
+ String switchFlowRef =
+ NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), actualIp, actualPort);
+
+ FlowEntity snatFlowEntity = new FlowEntityBuilder()
+ .setDpnId(dpnId)
+ .setTableId(tableId)
+ .setFlowId(switchFlowRef)
+ .setPriority(NatConstants.DEFAULT_NAPT_FLOW_PRIORITY)
+ .setFlowName(NatConstants.NAPT_FLOW_NAME)
+ .setIdleTimeOut(idleTimeout)
+ .setHardTimeOut(0)
+ .setCookie(NatUtil.getCookieNaptFlow(routerId))
+ .setMatchInfoList(buildAndGetMatchInfo(actualIp, actualPort, tableId, protocol, intranetVpnId))
+ .setInstructionInfoList(buildAndGetSetActionInstructionInfo(translatedIp, translatedPort,
+ intranetVpnId, vpnId, tableId, protocol, extGwMacAddress))
+ .setSendFlowRemFlag(true)
+ .build();
+
+ // Install flows using RPC to prevent race with future packet-out that depends on this flow
+ Future<RpcResult<AddFlowOutput>> addFlowResult = null;
+ if (sendRpc) {
+ Flow flow = snatFlowEntity.getFlowBuilder().build();
+ NodeRef nodeRef = getNodeRef(dpnId);
+ FlowRef flowRef = getFlowRef(dpnId, flow);
+ AddFlowInput addFlowInput = new AddFlowInputBuilder(flow).setFlowRef(flowRef).setNode(nodeRef).build();
+ long startTime = System.currentTimeMillis();
+ addFlowResult = salFlowServiceRpc.addFlow(addFlowInput);
+ LOG.debug("buildAndInstallNatFlowsOptionalRpc : Time elapsed for salFlowServiceRpc table {}: {}ms ",
+ tableId, (System.currentTimeMillis() - startTime));
+ // Keep flow installation through MDSAL as well to be able to handle switch failures
+ startTime = System.currentTimeMillis();
+ mdsalManager.installFlow(snatFlowEntity);
+ LOG.trace("buildAndInstallNatFlowsOptionalRpc : Time Elapsed while installing table-{} "
+ + "flow on DPN:{} for snat packet({},{}): {}ms", tableId, dpnId,
+ actualSourceAddress.getIpAddress(),actualSourceAddress.getPortNumber(),
+ (System.currentTimeMillis() - startTime));
+ } else {
+ long startTime = System.currentTimeMillis();
+ mdsalManager.syncInstallFlow(snatFlowEntity, 1);
+ LOG.trace("buildAndInstallNatFlowsOptionalRpc : Time Elapsed while installing table-{} "
+ + "flow on DPN:{} for snat packet({},{}): {}ms", tableId, dpnId,
+ actualSourceAddress.getIpAddress(),actualSourceAddress.getPortNumber(),
+ (System.currentTimeMillis() - startTime));
+ }
+ LOG.trace("buildAndInstallNatFlowsOptionalRpc : Exited");
- snatFlowEntity.setSendFlowRemFlag(true);
+ return addFlowResult;
+ }
+
+ private static Node buildInventoryDpnNode(BigInteger dpnId) {
+ NodeId nodeId = new NodeId("openflow:" + dpnId);
+ Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
+ return nodeDpn;
+ }
- LOG.debug("NAT Service : Installing the NAPT flow in the table {} for the switch with the DPN ID {} ", tableId, dpnId);
- mdsalManager.syncInstallFlow(snatFlowEntity, 1);
- LOG.trace("NAT Service : Exited buildAndInstallNatflows");
+ private static NodeRef getNodeRef(BigInteger dpnId) {
+ NodeId nodeId = new NodeId("openflow:" + dpnId);
+ return new NodeRef(InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(nodeId)).toInstance());
}
- private static List<MatchInfo> buildAndGetMatchInfo(String ip, int port, short tableId, NAPTEntryEvent.Protocol protocol, long segmentId, long vpnId){
+ public static FlowRef getFlowRef(BigInteger dpId, Flow flow) {
+ FlowKey flowKey = new FlowKey(new FlowId(flow.getId()));
+ Node nodeDpn = buildInventoryDpnNode(dpId);
+ InstanceIdentifier<Flow> flowInstanceId =
+ InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flow.getTableId()))
+ .child(Flow.class, flowKey)
+ .build();
+ return new FlowRef(flowInstanceId);
+ }
+
+ private static List<MatchInfo> buildAndGetMatchInfo(String ip, int port, short tableId,
+ NAPTEntryEvent.Protocol protocol, long segmentId) {
MatchInfo ipMatchInfo = null;
MatchInfo portMatchInfo = null;
MatchInfo protocolMatchInfo = null;
ipAddressAsString = ipAddress.getHostAddress();
} catch (UnknownHostException e) {
- LOG.error("NAT Service : UnknowHostException in buildAndGetMatchInfo. Failed to build NAPT Flow for ip {}", ipAddress);
+ LOG.error("buildAndGetMatchInfo : UnknowHostException in buildAndGetMatchInfo."
+ + "Failed to build NAPT Flow for ip {}", ipAddress, e);
return null;
}
MatchInfo metaDataMatchInfo = null;
- if(tableId == NwConstants.OUTBOUND_NAPT_TABLE){
- ipMatchInfo = new MatchInfo(MatchFieldType.ipv4_source, new String[] {ipAddressAsString, "32" });
- if(protocol == NAPTEntryEvent.Protocol.TCP) {
- protocolMatchInfo = new MatchInfo(MatchFieldType.ip_proto, new long[] {IPProtocols.TCP.intValue()});
- portMatchInfo = new MatchInfo(MatchFieldType.tcp_src, new long[]{port});
- } else if(protocol == NAPTEntryEvent.Protocol.UDP) {
- protocolMatchInfo = new MatchInfo(MatchFieldType.ip_proto, new long[] {IPProtocols.UDP.intValue()});
- portMatchInfo = new MatchInfo(MatchFieldType.udp_src, new long[]{port});
+ if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
+ ipMatchInfo = new MatchIpv4Source(ipAddressAsString, "32");
+ if (protocol == NAPTEntryEvent.Protocol.TCP) {
+ protocolMatchInfo = MatchIpProtocol.TCP;
+ portMatchInfo = new MatchTcpSourcePort(port);
+ } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
+ protocolMatchInfo = MatchIpProtocol.UDP;
+ portMatchInfo = new MatchUdpSourcePort(port);
}
- metaDataMatchInfo = new MatchInfo(MatchFieldType.metadata,
- new BigInteger[] { MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID });
- }else{
- ipMatchInfo = new MatchInfo(MatchFieldType.ipv4_destination, new String[] {ipAddressAsString, "32" });
- if(protocol == NAPTEntryEvent.Protocol.TCP) {
- protocolMatchInfo = new MatchInfo(MatchFieldType.ip_proto, new long[] {IPProtocols.TCP.intValue()});
- portMatchInfo = new MatchInfo(MatchFieldType.tcp_dst, new long[]{port});
- } else if(protocol == NAPTEntryEvent.Protocol.UDP) {
- protocolMatchInfo = new MatchInfo(MatchFieldType.ip_proto, new long[] {IPProtocols.UDP.intValue()});
- portMatchInfo = new MatchInfo(MatchFieldType.udp_dst, new long[]{port});
+ metaDataMatchInfo =
+ new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID);
+ } else {
+ ipMatchInfo = new MatchIpv4Destination(ipAddressAsString, "32");
+ if (protocol == NAPTEntryEvent.Protocol.TCP) {
+ protocolMatchInfo = MatchIpProtocol.TCP;
+ portMatchInfo = new MatchTcpDestinationPort(port);
+ } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
+ protocolMatchInfo = MatchIpProtocol.UDP;
+ portMatchInfo = new MatchUdpDestinationPort(port);
}
- //metaDataMatchInfo = new MatchInfo(MatchFieldType.metadata, new BigInteger[]{BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID});
+ //metaDataMatchInfo = new MatchMetadata(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID);
}
ArrayList<MatchInfo> matchInfo = new ArrayList<>();
- matchInfo.add(new MatchInfo(MatchFieldType.eth_type, new long[] { 0x0800L }));
+ matchInfo.add(MatchEthernetType.IPV4);
matchInfo.add(ipMatchInfo);
matchInfo.add(protocolMatchInfo);
matchInfo.add(portMatchInfo);
- if(tableId == NwConstants.OUTBOUND_NAPT_TABLE){
+ if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
matchInfo.add(metaDataMatchInfo);
}
return matchInfo;
}
- private static List<InstructionInfo> buildAndGetSetActionInstructionInfo(String ipAddress, String port, long segmentId, long vpnId, short tableId, NAPTEntryEvent.Protocol protocol) {
+ private static List<InstructionInfo> buildAndGetSetActionInstructionInfo(String ipAddress, int port,
+ long segmentId, long vpnId,
+ short tableId,
+ NAPTEntryEvent.Protocol protocol,
+ String extGwMacAddress) {
ActionInfo ipActionInfo = null;
+ ActionInfo macActionInfo = null;
ActionInfo portActionInfo = null;
ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
-
- if(tableId == NwConstants.OUTBOUND_NAPT_TABLE){
- ipActionInfo = new ActionInfo(ActionType.set_source_ip, new String[] {ipAddress});
- if(protocol == NAPTEntryEvent.Protocol.TCP) {
- portActionInfo = new ActionInfo( ActionType.set_tcp_source_port, new String[] {port});
- } else if(protocol == NAPTEntryEvent.Protocol.UDP) {
- portActionInfo = new ActionInfo( ActionType.set_udp_source_port, new String[] {port});
- }
- instructionInfo.add(new InstructionInfo(InstructionType.write_metadata,
- new BigInteger[] { MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
- }else{
- ipActionInfo = new ActionInfo(ActionType.set_destination_ip, new String[] {ipAddress});
- if(protocol == NAPTEntryEvent.Protocol.TCP) {
- portActionInfo = new ActionInfo( ActionType.set_tcp_destination_port, new String[] {port});
- } else if(protocol == NAPTEntryEvent.Protocol.UDP) {
- portActionInfo = new ActionInfo( ActionType.set_udp_destination_port, new String[] {port});
- }
- instructionInfo.add(new InstructionInfo(InstructionType.write_metadata,
- new BigInteger[] { MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
+ switch (tableId) {
+ case NwConstants.OUTBOUND_NAPT_TABLE:
+ ipActionInfo = new ActionSetSourceIp(ipAddress);
+ // Added External Gateway MAC Address
+ macActionInfo = new ActionSetFieldEthernetSource(new MacAddress(extGwMacAddress));
+ if (protocol == NAPTEntryEvent.Protocol.TCP) {
+ portActionInfo = new ActionSetTcpSourcePort(port);
+ } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
+ portActionInfo = new ActionSetUdpSourcePort(port);
+ }
+ // reset the split-horizon bit to allow traffic from tunnel to be sent back to the provider port
+ instructionInfo.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnId),
+ MetaDataUtil.METADATA_MASK_VRFID.or(MetaDataUtil.METADATA_MASK_SH_FLAG)));
+ break;
+
+ case NwConstants.INBOUND_NAPT_TABLE:
+ ipActionInfo = new ActionSetDestinationIp(ipAddress);
+ if (protocol == NAPTEntryEvent.Protocol.TCP) {
+ portActionInfo = new ActionSetTcpDestinationPort(port);
+ } else if (protocol == NAPTEntryEvent.Protocol.UDP) {
+ portActionInfo = new ActionSetUdpDestinationPort(port);
+ }
+ instructionInfo.add(new InstructionWriteMetadata(
+ MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID));
+ break;
+
+ default:
+ LOG.error("buildAndGetSetActionInstructionInfo : Neither OUTBOUND_NAPT_TABLE nor "
+ + "INBOUND_NAPT_TABLE matches with input table id {}", tableId);
+ return null;
}
listActionInfo.add(ipActionInfo);
listActionInfo.add(portActionInfo);
-
- instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
- instructionInfo.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.NAPT_PFIB_TABLE
- }));
+ if (macActionInfo != null) {
+ listActionInfo.add(macActionInfo);
+ LOG.debug("buildAndGetSetActionInstructionInfo : External GW MAC Address {} is found ", macActionInfo);
+ }
+ instructionInfo.add(new InstructionApplyActions(listActionInfo));
+ instructionInfo.add(new InstructionGotoTable(NwConstants.NAPT_PFIB_TABLE));
return instructionInfo;
}
- void removeNatFlows(BigInteger dpnId, short tableId ,long segmentId, String ip, int port){
- if(dpnId == null || dpnId.equals(BigInteger.ZERO)){
- LOG.error("NAT Service : DPN ID {} is invalid" , dpnId);
+ void removeNatFlows(BigInteger dpnId, short tableId ,long segmentId, String ip, int port) {
+ if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
+ LOG.error("removeNatFlows : DPN ID {} is invalid" , dpnId);
+ return;
}
- LOG.debug("NAT Service : Remove NAPT flows for dpnId {}, segmentId {}, ip {} and port {} ", dpnId, segmentId, ip, port);
+ LOG.debug("removeNatFlows : Remove NAPT flows for dpnId {}, segmentId {}, ip {} and port {} ",
+ dpnId, segmentId, ip, port);
//Build the flow with the port IP and port as the match info.
String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(segmentId), ip, port);
FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
- LOG.debug("NAT Service : Remove the flow in the table {} for the switch with the DPN ID {}", NwConstants.INBOUND_NAPT_TABLE, dpnId);
+ LOG.debug("removeNatFlows : Remove the flow in the table {} for the switch with the DPN ID {}",
+ NwConstants.INBOUND_NAPT_TABLE, dpnId);
+ long startTime = System.currentTimeMillis();
mdsalManager.removeFlow(snatFlowEntity);
-
+ LOG.trace("removeNatFlows : Time Elapsed for removing table-{} flow from switch with DPN ID:{} "
+ + "for SNAT ({}:{}) session:{}ms", tableId, dpnId, ip, port, (System.currentTimeMillis() - startTime));
}
protected byte[] buildNaptPacketOut(Ethernet etherPkt) {
-
- LOG.debug("NAT Service : About to build Napt Packet Out");
+ LOG.debug("removeNatFlows : About to build Napt Packet Out");
if (etherPkt.getPayload() instanceof IPv4) {
byte[] rawPkt;
IPv4 ipPkt = (IPv4) etherPkt.getPayload();
- if ((ipPkt.getPayload() instanceof TCP) || (ipPkt.getPayload() instanceof UDP) ) {
+ if (ipPkt.getPayload() instanceof TCP || ipPkt.getPayload() instanceof UDP) {
try {
rawPkt = etherPkt.serialize();
return rawPkt;
} catch (PacketException e2) {
- // TODO Auto-generated catch block
- e2.printStackTrace();
+ LOG.error("failed to build NAPT Packet out ", e2);
return null;
}
- } else {
- LOG.error("NAT Service : Unable to build NaptPacketOut since its neither TCP nor UDP");
- return null;
- }
+ } else {
+ LOG.error("removeNatFlows : Unable to build NaptPacketOut since its neither TCP nor UDP");
+ return null;
+ }
}
- LOG.error("NAT Service : Unable to build NaptPacketOut since its not IPv4 packet");
+ LOG.error("removeNatFlows : Unable to build NaptPacketOut since its not IPv4 packet");
return null;
-
}
- private void sendNaptPacketOut(byte[] pktOut, InterfaceInfo infInfo, List<ActionInfo> actionInfos, Long routerId) {
- LOG.trace("NAT Service: Sending packet out DpId {}, interfaceInfo {}", infInfo.getDpId(), infInfo);
- // set in_port, and action as OFPP_TABLE so that it starts from table 0 (lowest table as per spec)
- actionInfos.add(new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
- BigInteger.valueOf(routerId)}, 2));
- actionInfos.add(new ActionInfo(ActionType.output, new String[] { "0xfffffff9" }, 3));
- NodeConnectorRef in_port = MDSALUtil.getNodeConnRef(infInfo.getDpId(), String.valueOf(infInfo.getPortNo()));
- LOG.debug("NAT Service : in_port for packetout is being set to {}", String.valueOf(infInfo.getPortNo()));
- TransmitPacketInput output = MDSALUtil.getPacketOut(actionInfos, pktOut, infInfo.getDpId().longValue(), in_port);
- LOG.trace("NAT Service: Transmitting packet: {}",output);
+ private void sendNaptPacketOut(byte[] pktOut, InterfaceInfo infInfo, List<ActionInfo> actionInfos, Long tunId) {
+ LOG.trace("sendNaptPacketOut: Sending packet out DpId {}, interfaceInfo {}", infInfo.getDpId(), infInfo);
+ // set inPort, and action as OFPP_TABLE so that it starts from table 0 (lowest table as per spec)
+ actionInfos.add(new ActionSetFieldTunnelId(2, BigInteger.valueOf(tunId)));
+ actionInfos.add(new ActionOutput(3, new Uri("0xfffffff9")));
+ NodeConnectorRef inPort = MDSALUtil.getNodeConnRef(infInfo.getDpId(), String.valueOf(infInfo.getPortNo()));
+ LOG.debug("sendNaptPacketOut : inPort for packetout is being set to {}", String.valueOf(infInfo.getPortNo()));
+ TransmitPacketInput output = MDSALUtil.getPacketOut(actionInfos, pktOut, infInfo.getDpId().longValue(), inPort);
+ LOG.debug("sendNaptPacketOut : Transmitting packet: {}, inPort {}", output, inPort);
this.pktService.transmitPacket(output);
}
private String getInterfaceNameFromTag(long portTag) {
String interfaceName = null;
- GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder().setIfIndex(new Integer((int)portTag)).build();
- Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput = interfaceManagerRpc.getInterfaceFromIfIndex(input);
+ GetInterfaceFromIfIndexInput input =
+ new GetInterfaceFromIfIndexInputBuilder().setIfIndex((int) portTag).build();
+ Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput =
+ interfaceManagerRpc.getInterfaceFromIfIndex(input);
try {
GetInterfaceFromIfIndexOutput output = futureOutput.get().getResult();
interfaceName = output.getInterfaceName();
} catch (InterruptedException | ExecutionException e) {
- LOG.error("NAT Service : Error while retrieving the interfaceName from tag using getInterfaceFromIfIndex RPC");
+ LOG.error("getInterfaceNameFromTag : Error while retrieving the interfaceName from tag using "
+ + "getInterfaceFromIfIndex RPC");
}
- LOG.trace("NAT Service : Returning interfaceName {} for tag {} form getInterfaceNameFromTag", interfaceName, portTag);
+ LOG.trace("getInterfaceNameFromTag : Returning interfaceName {} for tag {} form getInterfaceNameFromTag",
+ interfaceName, portTag);
return interfaceName;
}
+ private long getVpnIdFromExternalSubnet(DataBroker dataBroker, Long routerId, String externalIpAddress) {
+ String routerName = NatUtil.getRouterName(dataBroker, routerId);
+ if (routerName != null) {
+ Routers extRouter = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
+ if (extRouter != null) {
+ return NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIpAddress, extRouter);
+ }
+ }
+
+ return NatConstants.INVALID_ID;
+ }
}