/*
- * Copyright © 2016, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2016, 2018 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.vpnmanager;
-import com.google.common.base.Optional;
import com.google.common.primitives.Ints;
-import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
import org.opendaylight.genius.mdsalutil.MetaDataUtil;
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.genius.mdsalutil.packet.Ethernet;
import org.opendaylight.genius.mdsalutil.packet.IPv4;
+import org.opendaylight.infrautils.metrics.Counter;
+import org.opendaylight.infrautils.metrics.Labeled;
+import org.opendaylight.infrautils.metrics.MetricDescriptor;
+import org.opendaylight.infrautils.metrics.MetricProvider;
import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.netvirt.vpnmanager.api.ICentralizedSwitchProvider;
import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
-import org.opendaylight.netvirt.vpnmanager.utilities.VpnManagerCounters;
+import org.opendaylight.netvirt.vpnmanager.iplearn.ipv4.ArpUtils;
+import org.opendaylight.netvirt.vpnmanager.utilities.CounterUtility;
+import org.opendaylight.openflowplugin.libraries.liblldp.BitBufferHelper;
+import org.opendaylight.openflowplugin.libraries.liblldp.BufferException;
import org.opendaylight.openflowplugin.libraries.liblldp.HexEncode;
-import org.opendaylight.openflowplugin.libraries.liblldp.NetUtils;
import org.opendaylight.openflowplugin.libraries.liblldp.Packet;
import org.opendaylight.openflowplugin.libraries.liblldp.PacketException;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+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.genius.interfacemanager.rev160406.IfTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.Ipv6NdUtilService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final OdlInterfaceRpcService odlInterfaceRpcService;
private final ICentralizedSwitchProvider centralizedSwitchProvider;
private final IInterfaceManager interfaceManager;
- private final VpnManagerCounters vpnManagerCounters;
+ private final Ipv6NdUtilService ipv6NdUtilService;
+ private final Labeled<Labeled<Counter>> packetInCounter;
+ private final VpnUtil vpnUtil;
@Inject
public SubnetRoutePacketInHandler(final DataBroker dataBroker, final PacketProcessingService packetService,
final OdlInterfaceRpcService odlInterfaceRpcService,
- final ICentralizedSwitchProvider centralizedSwitchProvider,
- final IInterfaceManager interfaceManager, VpnManagerCounters vpnManagerCounters) {
+ final ICentralizedSwitchProvider centralizedSwitchProvider, final IInterfaceManager interfaceManager,
+ final Ipv6NdUtilService ipv6NdUtilService, MetricProvider metricProvider, VpnUtil vpnUtil) {
this.dataBroker = dataBroker;
this.packetService = packetService;
this.odlInterfaceRpcService = odlInterfaceRpcService;
this.centralizedSwitchProvider = centralizedSwitchProvider;
this.interfaceManager = interfaceManager;
- this.vpnManagerCounters = vpnManagerCounters;
+ this.ipv6NdUtilService = ipv6NdUtilService;
+ packetInCounter = metricProvider.newCounter(MetricDescriptor.builder().anchor(this)
+ .project(CounterUtility.getProject()).module(CounterUtility.getModule())
+ .id(CounterUtility.getSubnetRouteId()).build(), "action","sourceIp.destinationIp");
+ this.vpnUtil = vpnUtil;
}
@Override
public void onPacketReceived(PacketReceived notification) {
- short tableId = notification.getTableId().getValue();
+ short tableId = notification.getTableId().getValue().toJava();
LOG.trace("{} onPacketReceived: Packet punted from table {}", LOGGING_PREFIX, tableId);
+ if (!vpnUtil.isArpLearningEnabled()) {
+ LOG.trace("Not handling packet as ARP Based Learning is disabled");
+ return;
+ }
byte[] data = notification.getPayload();
if (notification.getMatch() == null || notification.getMatch().getMetadata() == null) {
LOG.error("{} onPacketReceived: Received from table {} where the match or metadata are null",
LOGGING_PREFIX, tableId);
return;
}
- BigInteger metadata = notification.getMatch().getMetadata().getMetadata();
+ Uint64 metadata = notification.getMatch().getMetadata().getMetadata();
Ethernet res = new Ethernet();
if (tableId == NwConstants.L3_SUBNET_ROUTE_TABLE) {
LOG.trace("{} onPacketReceived: Some packet received as {}", LOGGING_PREFIX, notification);
try {
- res.deserialize(data, 0, data.length * NetUtils.NUM_BITS_IN_A_BYTE);
+ res.deserialize(data, 0, data.length * Byte.SIZE);
} catch (PacketException e) {
LOG.error("{} onPacketReceived: Failed to decode Packet ", LOGGING_PREFIX, e);
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(CounterUtility.getSubnetRouteInvalidPacket());
+ counter.increment();
return;
}
+ byte[] srcIpBytes = null;
+ byte[] dstIpBytes = null;
+ String srcIpStr;
+ String dstIpStr;
+ String srcMac = NWUtil.toStringMacAddress(res.getSourceMACAddress());
try {
Packet pkt = res.getPayload();
if (pkt instanceof IPv4) {
IPv4 ipv4 = (IPv4) pkt;
- byte[] srcIp = Ints.toByteArray(ipv4.getSourceAddress());
- byte[] dstIp = Ints.toByteArray(ipv4.getDestinationAddress());
- String dstIpStr = NWUtil.toStringIpAddress(dstIp);
- String srcIpStr = NWUtil.toStringIpAddress(srcIp);
+ srcIpBytes = Ints.toByteArray(ipv4.getSourceAddress());
+ dstIpBytes = Ints.toByteArray(ipv4.getDestinationAddress());
+ srcIpStr = NWUtil.toStringIpAddress(srcIpBytes);
+ dstIpStr = NWUtil.toStringIpAddress(dstIpBytes);
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_recived.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
// It is an ARP request on a configured VPN. So we must
// attempt to respond.
- long vpnId = MetaDataUtil.getVpnIdFromMetadata(metadata);
-
- LOG.info("{} onPacketReceived: Processing IPv4 Packet received with Source IP {} and Target IP {}"
- + " and vpnId {}", LOGGING_PREFIX, srcIpStr, dstIpStr, vpnId);
-
- Optional<VpnIds> vpnIdsOptional = SingleTransactionDataBroker.syncReadOptional(dataBroker,
- LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId));
-
- if (!vpnIdsOptional.isPresent()) {
- // Donot trigger subnetroute logic for packets from
- // unknown VPNs
- vpnManagerCounters.subnetRoutePacketIgnored();
- LOG.info("{} onPacketReceived: Ignoring IPv4 packet with destination Ip {} and source Ip {}"
- + " as it came on unknown VPN with ID {}", LOGGING_PREFIX, dstIpStr, srcIpStr, vpnId);
- return;
- }
-
- String vpnIdVpnInstanceName = vpnIdsOptional.get().getVpnInstanceName();
- if (VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnIdVpnInstanceName, dstIpStr) != null) {
- vpnManagerCounters.subnetRoutePacketIgnored();
- LOG.info("{} onPacketReceived: IPv4 Packet received with Target IP {} source IP {} vpnId {} "
- + "is a valid Neutron port,ignoring subnet route processing", LOGGING_PREFIX, dstIpStr,
- srcIp, vpnId);
- return;
- }
-
- if (VpnUtil.getLearntVpnVipToPort(dataBroker, vpnIdVpnInstanceName, dstIpStr) != null) {
- vpnManagerCounters.subnetRoutePacketIgnored();
- LOG.info("{} onPacketReceived: IPv4 Packet received with Target IP {} source Ip {} vpnId {}"
- + " is an already discovered IPAddress, ignoring subnet route processing",
- LOGGING_PREFIX, dstIpStr, srcIp, vpnId);
- return;
- }
-
- long elanTag = MetaDataUtil.getElanTagFromMetadata(metadata);
- if (elanTag == 0L) {
- vpnManagerCounters.subnetRoutePacketFailed();
- LOG.error("{} onPacketReceived: elanTag value from metadata found to be 0, for IPv4 "
- + " Packet received with Target IP {} src Ip {} vpnId {}",
- LOGGING_PREFIX, dstIpStr, srcIp, vpnId);
- return;
- }
-
- if (!vpnIdsOptional.get().isExternalVpn()) {
- handleInternalVpnSubnetRoutePacket(metadata, dstIp, srcIpStr, dstIpStr,
- ipv4.getDestinationAddress(), vpnIdVpnInstanceName, elanTag);
- return;
+ } else {
+ // IPv6 case
+ // TODO: IPv6 deserializer
+ int ethType = BitBufferHelper.getInt(
+ BitBufferHelper.getBits(data, VpnConstants.ETHTYPE_START, VpnConstants.TWO_BYTES));
+ if (ethType == VpnConstants.IP_V6_ETHTYPE) {
+ srcIpBytes = BitBufferHelper.getBits(data, VpnConstants.IP_V6_HDR_START + 64, 128);
+ dstIpBytes = BitBufferHelper.getBits(data, VpnConstants.IP_V6_HDR_START + 192, 128);
}
-
- byte[] srcMac = res.getSourceMACAddress();
- handleBgpVpnSubnetRoute(ipv4, srcMac, dstIp, dstIpStr, srcIpStr, elanTag);
}
- } catch (UnknownHostException | InterruptedException | ExecutionException ex) {
+ if (srcIpBytes == null || dstIpBytes == null) {
+ LOG.trace("{} onPacketReceived: Non-IP packet received as {}", LOGGING_PREFIX, notification);
+ return;
+ }
+ handleIpPackets(srcIpBytes, dstIpBytes, NWUtil.toStringIpAddress(srcIpBytes),
+ NWUtil.toStringIpAddress(dstIpBytes), srcMac, metadata);
+
+ } catch (InterruptedException | ExecutionException | BufferException ex) {
// Failed to handle packet
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(NWUtil.toStringIpAddress(srcIpBytes) + "." + NWUtil.toStringIpAddress(srcIpBytes));
+ counter.increment();
LOG.error("{} onPacketReceived: Failed to handle subnetroute packet.", LOGGING_PREFIX, ex);
- } catch (ReadFailedException e) {
- vpnManagerCounters.subnetRoutePacketFailed();
- LOG.error("{} onPacketReceived: Failed to read data-store.", LOGGING_PREFIX, e);
+ } catch (UnknownHostException e) {
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(CounterUtility.getSubnetRouteInvalidPacket());
+ counter.increment();
+ LOG.error("{} onPacketReceived: Unknown host detected while handling subnetroute", LOGGING_PREFIX, e);
}
return;
}
}
- private void handleBgpVpnSubnetRoute(IPv4 ipv4, byte[] srcMac, byte[] dstIp, String dstIpStr, String srcIpStr,
+ private void handleIpPackets(byte[] srcIp, byte[] dstIp, String srcIpStr, String dstIpStr, String srcMac,
+ Uint64 metadata)
+ throws UnknownHostException, InterruptedException, ExecutionException {
+ Uint32 vpnId = Uint32.valueOf(MetaDataUtil.getVpnIdFromMetadata(metadata));
+
+ LOG.info("{} onPacketReceived: Processing IP Packet received with Source IP {} and Target IP {}"
+ + " and vpnId {}", LOGGING_PREFIX, srcIpStr, dstIpStr, vpnId);
+
+ Optional<VpnIds> vpnIdsOptional = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId));
+
+ if (!vpnIdsOptional.isPresent()) {
+ // Donot trigger subnetroute logic for packets from
+ // unknown VPNs
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_drop.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
+ LOG.info("{} onPacketReceived: Ignoring IPv4 packet with destination Ip {} and source Ip {}"
+ + " as it came on unknown VPN with ID {}", LOGGING_PREFIX, dstIpStr, srcIpStr, vpnId);
+ return;
+ }
+
+ String vpnIdVpnInstanceName = vpnIdsOptional.get().getVpnInstanceName();
+ VpnPortipToPort persistedIP =
+ vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnIdVpnInstanceName, dstIpStr);
+ if (persistedIP != null && !persistedIP.isLearntIp()) {
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_drop.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
+ LOG.info("{} onPacketReceived: IP Packet received with Target IP {} source IP {} vpnId {} "
+ + "is a valid Neutron port,ignoring subnet route processing", LOGGING_PREFIX, dstIpStr,
+ srcIp, vpnId);
+ return;
+ }
+
+ if (vpnUtil.getLearntVpnVipToPort(vpnIdVpnInstanceName, dstIpStr) != null) {
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
+ LOG.info("{} onPacketReceived: IP Packet received with Target IP {} source Ip {} vpnId {}"
+ + " is an already discovered IPAddress, ignoring subnet route processing",
+ LOGGING_PREFIX, dstIpStr, srcIp, vpnId);
+ return;
+ }
+
+ long elanTag = MetaDataUtil.getElanTagFromMetadata(metadata);
+ if (elanTag == 0L) {
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
+ LOG.error("{} onPacketReceived: elanTag value from metadata found to be 0, for IP "
+ + " Packet received with Target IP {} src Ip {} vpnId {}",
+ LOGGING_PREFIX, dstIpStr, srcIp, vpnId);
+ return;
+ }
+
+ if (!vpnIdsOptional.get().isExternalVpn()) {
+ handleInternalVpnSubnetRoutePacket(metadata, dstIp, srcIpStr, dstIpStr, vpnIdVpnInstanceName,
+ elanTag);
+ return;
+ }
+
+ handleBgpVpnSubnetRoute(srcMac, dstIp, dstIpStr, srcIpStr, elanTag);
+ }
+
+ private void handleBgpVpnSubnetRoute(String srcMac, byte[] dstIp, String dstIpStr, String srcIpStr,
long elanTag) throws UnknownHostException {
- LOG.info("{} handleBgpVpnSubnetRoute: Processing IPv4 Packet received with Source IP {} and Target IP {}"
+ LOG.info("{} handleBgpVpnSubnetRoute: Processing IP Packet received with Source IP {} and Target IP {}"
+ " and elan Tag {}", LOGGING_PREFIX, srcIpStr, dstIpStr, elanTag);
SubnetOpDataEntry targetSubnetForPacketOut =
- getTargetSubnetForPacketOut(dataBroker, elanTag, ipv4.getDestinationAddress());
-
+ getTargetSubnetForPacketOut(elanTag, dstIpStr);
if (targetSubnetForPacketOut != null) {
// Handle subnet routes ip requests
- transmitArpPacket(targetSubnetForPacketOut.getNhDpnId(), srcIpStr, NWUtil.toStringMacAddress(srcMac), dstIp,
- elanTag);
+ transmitArpOrNsPacket(targetSubnetForPacketOut.getNhDpnId(),
+ srcIpStr, srcMac, dstIp, dstIpStr, elanTag);
} else {
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
LOG.debug("{} handleBgpVpnSubnetRoute: Could not find target subnet for packet out {}", LOGGING_PREFIX,
dstIpStr);
}
}
- private void handleInternalVpnSubnetRoutePacket(BigInteger metadata, byte[] dstIp, String srcIpStr, String dstIpStr,
- int destinationAddress, String vpnIdVpnInstanceName, long elanTag)
+ private void handleInternalVpnSubnetRoutePacket(Uint64 metadata, byte[] dstIp, String srcIpStr, String dstIpStr,
+ String vpnIdVpnInstanceName, long elanTag)
throws InterruptedException, ExecutionException, UnknownHostException {
- String vmVpnInterfaceName = VpnUtil.getVpnInterfaceName(odlInterfaceRpcService, metadata);
+ String vmVpnInterfaceName = vpnUtil.getVpnInterfaceName(metadata);
if (isTunnel(vmVpnInterfaceName)) {
- handlePacketFromTunnelToExternalNetwork(vpnIdVpnInstanceName,
- srcIpStr, dstIp, elanTag);
+ handlePacketFromTunnelToExternalNetwork(vpnIdVpnInstanceName, srcIpStr, dstIp, dstIpStr, elanTag);
}
- VpnInterface vmVpnInterface = VpnUtil.getVpnInterface(dataBroker, vmVpnInterfaceName);
+ VpnInterface vmVpnInterface = vpnUtil.getVpnInterface(vmVpnInterfaceName);
if (vmVpnInterface == null) {
LOG.error("Vpn interface {} doesn't exist.", vmVpnInterfaceName);
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
return;
}
if (VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnIdVpnInstanceName,
vmVpnInterface.getVpnInstanceNames())
- && !VpnUtil.isBgpVpnInternet(dataBroker, vpnIdVpnInstanceName)) {
+ && !vpnUtil.isBgpVpnInternet(vpnIdVpnInstanceName)) {
LOG.trace("Unknown IP is in internal network");
- handlePacketToInternalNetwork(dstIp, dstIpStr, destinationAddress, elanTag);
+ handlePacketToInternalNetwork(dstIp, dstIpStr, elanTag, srcIpStr);
} else {
LOG.trace("Unknown IP is in external network");
- String vpnName = VpnUtil.getInternetVpnFromVpnInstanceList(dataBroker,
- vmVpnInterface.getVpnInstanceNames());
+ String vpnName = vpnUtil.getInternetVpnFromVpnInstanceList(vmVpnInterface.getVpnInstanceNames());
if (vpnName != null) {
- handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName),
- vpnName, dstIp, elanTag);
+ handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName), vpnName, dstIp, dstIpStr, elanTag);
} else {
vpnName = VpnHelper.getFirstVpnNameFromVpnInterface(vmVpnInterface);
- LOG.trace("Unknown IP is in external network, but internet VPN not found."
- + " fallback to first VPN");
- handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName),
- vpnName, dstIp, elanTag);
+ LOG.trace("Unknown IP is in external network, but internet VPN not found." + " fallback to first VPN");
+ handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName), vpnName, dstIp, dstIpStr, elanTag);
}
}
}
- private void transmitArpPacket(BigInteger dpnId, String sourceIpAddress, String sourceMac, byte[] dstIp,
- long elanTag) throws UnknownHostException {
- LOG.debug("Sending arp with elan tag {}", elanTag);
- vpnManagerCounters.subnetRoutePacketArpSent();
+ private void transmitArpOrNsPacket(Uint64 dpnId, String sourceIpAddress, String sourceMac, byte[] dstIpBytes,
+ String dstIpAddress, long elanTag) throws UnknownHostException {
long groupid = VpnUtil.getRemoteBCGroup(elanTag);
- TransmitPacketInput arpRequestInput = ArpUtils.createArpRequestInput(dpnId, groupid,
- HexEncode.bytesFromHexString(sourceMac), InetAddress.getByName(sourceIpAddress).getAddress(), dstIp);
-
- JdkFutures.addErrorLogging(packetService.transmitPacket(arpRequestInput), LOG, "Transmit packet");
+ if (NWUtil.isIpv4Address(dstIpAddress)) {
+ LOG.debug("Sending ARP: srcIp={}, srcMac={}, dstIp={}, dpId={}, elan-tag={}, groupid={}", sourceIpAddress,
+ sourceMac, dstIpAddress, dpnId, elanTag, groupid);
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_arp_sent.toString())
+ .label(sourceIpAddress + "." + dstIpAddress);
+ counter.increment();
+
+ TransmitPacketInput packetInput =
+ ArpUtils.createArpRequestInput(dpnId, groupid, HexEncode.bytesFromHexString(sourceMac),
+ InetAddress.getByName(sourceIpAddress).getAddress(), dstIpBytes);
+ JdkFutures.addErrorLogging(packetService.transmitPacket(packetInput), LOG, "Transmit packet");
+ } else {
+ // IPv6 case
+ LOG.debug("Sending NS: srcIp={}, srcMac={}, dstIp={}, dpId={}, elan-tag={}, groupid={}", sourceIpAddress,
+ sourceMac, dstIpAddress, dpnId, elanTag, groupid);
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_ns_sent.toString())
+ .label(sourceIpAddress + "." + dstIpAddress);
+ counter.increment();
+
+ VpnUtil.sendNeighborSolicationToOfGroup(this.ipv6NdUtilService, new Ipv6Address(sourceIpAddress),
+ new MacAddress(sourceMac), new Ipv6Address(dstIpAddress), groupid, dpnId);
+ }
}
- private void handlePacketToInternalNetwork(byte[] dstIp, String dstIpStr, int destinationAddress, long elanTag)
+ private void handlePacketToInternalNetwork(byte[] dstIp, String dstIpStr, long elanTag, String srcIpStr)
throws UnknownHostException {
try {
SubnetOpDataEntry targetSubnetForPacketOut =
- getTargetSubnetForPacketOut(dataBroker, elanTag, destinationAddress);
+ getTargetSubnetForPacketOut(elanTag, dstIpStr);
if (targetSubnetForPacketOut == null) {
LOG.debug("Couldn't find matching subnet for elan tag {} and destination ip {}", elanTag, dstIpStr);
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
return;
}
VpnUtil.buildSubnetmapIdentifier(targetSubnetForPacketOut.getSubnetId()));
if (!subnetMap.isPresent()) {
LOG.debug("Couldn't find subnet map for subnet {}", targetSubnetForPacketOut.getSubnetId());
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(srcIpStr + "." + dstIpStr);
+ counter.increment();
return;
}
String sourceIp = subnetMap.get().getRouterInterfaceFixedIp();
if (sourceIp == null) {
LOG.debug("Subnet map {} doesn't have a router interface ip defined", subnetMap.get().getId());
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label("." + dstIpStr);
+ counter.increment();
return;
}
if (sourceMac == null) {
LOG.debug("Subnet map {} doesn't have a router interface mac address defined",
subnetMap.get().getId());
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(sourceIp + "." + dstIpStr);
+ counter.increment();
return;
}
- transmitArpPacket(targetSubnetForPacketOut.getNhDpnId(), sourceIp, sourceMac, dstIp, elanTag);
- } catch (ReadFailedException e) {
+ transmitArpOrNsPacket(targetSubnetForPacketOut.getNhDpnId(),
+ sourceIp, sourceMac, dstIp, dstIpStr, elanTag);
+ } catch (InterruptedException | ExecutionException e) {
LOG.error("handlePacketToInternalNetwork: Failed to read data store for destIp {} elanTag {}", dstIpStr,
elanTag);
}
}
- private void handlePacketFromTunnelToExternalNetwork(String vpnIdVpnInstanceName,
- String srcIpStr, byte[] dstIp, long elanTag)
- throws UnknownHostException {
- String routerId = VpnUtil.getAssociatedExternalRouter(dataBroker, srcIpStr);
+ private void handlePacketFromTunnelToExternalNetwork(String vpnIdVpnInstanceName, String srcIpStr, byte[] dstIp,
+ String dstIpStr, long elanTag) throws UnknownHostException {
+ String routerId = vpnUtil.getAssociatedExternalRouter(srcIpStr);
if (null == routerId) {
LOG.debug("This ip is not associated with any external router: {}", srcIpStr);
+ return;
}
- handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName), routerId, dstIp, elanTag);
+ handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName), routerId, dstIp, dstIpStr, elanTag);
}
- private void handlePacketToExternalNetwork(Uuid vpnInstanceNameUuid, String routerId, byte[] dstIp,
+ private void handlePacketToExternalNetwork(Uuid vpnInstanceNameUuid, String routerId, byte[] dstIp, String dstIpStr,
long elanTag) throws UnknownHostException {
- Routers externalRouter = VpnUtil.getExternalRouter(dataBroker, routerId);
+ Routers externalRouter = vpnUtil.getExternalRouter(routerId);
if (externalRouter == null) {
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label("." + dstIpStr);
+ counter.increment();
LOG.debug("{} handlePacketToExternalNetwork: Can't find external router with id {}", LOGGING_PREFIX,
routerId);
return;
List<ExternalIps> externalIps = externalRouter.getExternalIps();
if (externalIps == null || externalIps.isEmpty()) {
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label("." + dstIpStr);
+ counter.increment();
LOG.debug("{} handlePacketToExternalNetwork: Router {} doesn't have any external ips.",
LOGGING_PREFIX, externalRouter.getRouterName());
return;
java.util.Optional<ExternalIps> externalIp = externalRouter.getExternalIps().stream()
.filter(eip -> vpnInstanceNameUuid.equals(eip.getSubnetId())).findFirst();
if (!externalIp.isPresent()) {
- vpnManagerCounters.subnetRoutePacketFailed();
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(externalIp.get().getIpAddress() + "." + dstIpStr);
+ counter.increment();
LOG.debug("{} handlePacketToExternalNetwork: Router {} doesn't have an external ip for subnet id {}.",
LOGGING_PREFIX, externalRouter.getRouterName(), vpnInstanceNameUuid);
return;
}
- BigInteger dpnId = centralizedSwitchProvider.getPrimarySwitchForRouter(externalRouter.getRouterName());
- if (BigInteger.ZERO.equals(dpnId)) {
- vpnManagerCounters.subnetRoutePacketFailed();
+ Uint64 dpnId = centralizedSwitchProvider.getPrimarySwitchForRouter(externalRouter.getRouterName());
+ if (Uint64.ZERO.equals(dpnId)) {
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_failed.toString())
+ .label(externalIp.get().getIpAddress() + "." + dstIpStr);
+ counter.increment();
LOG.debug("{} handlePacketToExternalNetwork: Could not find primary switch for router {}.",
LOGGING_PREFIX, externalRouter.getRouterName());
return;
}
- transmitArpPacket(dpnId, externalIp.get().getIpAddress(), externalRouter.getExtGwMacAddress(), dstIp, elanTag);
+ transmitArpOrNsPacket(dpnId, externalIp.get().getIpAddress(), externalRouter.getExtGwMacAddress(), dstIp,
+ dstIpStr, elanTag);
+
+ Counter counter = packetInCounter.label(CounterUtility.subnet_route_packet_processed.toString())
+ .label(externalIp.get().getIpAddress() + "." + dstIpStr);
+ counter.increment();
}
// return only the first VPN subnetopdataentry
- private static SubnetOpDataEntry getTargetSubnetForPacketOut(DataBroker broker, long elanTag, int ipAddress) {
- ElanTagName elanInfo = VpnUtil.getElanInfoByElanTag(broker, elanTag);
+ @Nullable
+ private SubnetOpDataEntry getTargetSubnetForPacketOut(long elanTag, String ipAddress) {
+ ElanTagName elanInfo = vpnUtil.getElanInfoByElanTag(elanTag);
if (elanInfo == null) {
LOG.error("{} getTargetDpnForPacketOut: Unable to retrieve ElanInfo for elanTag {}", LOGGING_PREFIX,
elanTag);
return null;
}
try {
- Optional<NetworkMap> optionalNetworkMap = SingleTransactionDataBroker.syncReadOptional(broker,
+ Optional<NetworkMap> optionalNetworkMap = SingleTransactionDataBroker.syncReadOptional(dataBroker,
LogicalDatastoreType.CONFIGURATION, VpnUtil.buildNetworkMapIdentifier(new Uuid(
elanInfo.getName())));
if (!optionalNetworkMap.isPresent()) {
List<Uuid> subnetList = optionalNetworkMap.get().getSubnetIdList();
LOG.debug("{} getTargetDpnForPacketOut: Obtained subnetList as {} for network {}", LOGGING_PREFIX,
subnetList, elanInfo.getName());
- for (Uuid subnetId : subnetList) {
- String vpnName = null;
- Subnetmap sn = VpnUtil.getSubnetmapFromItsUuid(broker, subnetId);
- if (sn != null && sn.getVpnId() != null) {
- vpnName = sn.getVpnId().getValue();
- }
- if (vpnName == null) {
- continue;
- }
- Optional<SubnetOpDataEntry> optionalSubs;
- optionalSubs = SingleTransactionDataBroker.syncReadOptional(broker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.buildSubnetOpDataEntryInstanceIdentifier(subnetId));
- if (!optionalSubs.isPresent()) {
- continue;
- }
- SubnetOpDataEntry subOpEntry = optionalSubs.get();
- if (subOpEntry.getNhDpnId() != null) {
- LOG.trace("{} getTargetDpnForPacketOut: Viewing Subnet {}", LOGGING_PREFIX, subnetId.getValue());
- boolean match = NWUtil.isIpInSubnet(ipAddress, subOpEntry.getSubnetCidr());
- LOG.trace("{} getTargetDpnForPacketOut: Viewing Subnet {} matching {}", LOGGING_PREFIX,
+ if (subnetList != null) {
+ for (Uuid subnetId : subnetList) {
+ String vpnName = null;
+ Subnetmap sn = vpnUtil.getSubnetmapFromItsUuid(subnetId);
+ if (sn != null && sn.getVpnId() != null) {
+ vpnName = sn.getVpnId().getValue();
+ }
+ if (vpnName == null) {
+ continue;
+ }
+ Optional<SubnetOpDataEntry> optionalSubs = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+ LogicalDatastoreType.OPERATIONAL, VpnUtil.buildSubnetOpDataEntryInstanceIdentifier(subnetId));
+ if (!optionalSubs.isPresent()) {
+ continue;
+ }
+ SubnetOpDataEntry subOpEntry = optionalSubs.get();
+ if (subOpEntry.getNhDpnId() != null) {
+ LOG.trace("{} getTargetDpnForPacketOut: Viewing Subnet {}", LOGGING_PREFIX,
+ subnetId.getValue());
+ IpPrefix cidr = IpPrefixBuilder.getDefaultInstance(subOpEntry.getSubnetCidr());
+ boolean match = NWUtil.isIpAddressInRange(IpAddressBuilder.getDefaultInstance(ipAddress), cidr);
+ LOG.trace("{} getTargetDpnForPacketOut: Viewing Subnet {} matching {}", LOGGING_PREFIX,
subnetId.getValue(), match);
- if (match) {
- return subOpEntry;
+ if (match) {
+ return subOpEntry;
+ }
}
}
}
- } catch (ReadFailedException e) {
+ } catch (InterruptedException | ExecutionException e) {
LOG.error("{} getTargetDpnForPacketOut: Failed to read data store for elan {}", LOGGING_PREFIX,
elanInfo.getName());
}
}
public boolean isTunnel(String interfaceName) {
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
- .ietf.interfaces.rev140508.interfaces.Interface configIface =
- interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName);
- return configIface.augmentation(IfTunnel.class) != null;
+ return interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName).augmentation(IfTunnel.class) != null;
}
}