use of org.onlab.packet.IpAddress in project trellis-control by opennetworkinglab.
the class IcmpHandler method processIcmpv6.
// /////////////////////////////////////////
// ICMPv6 Echo/Reply Protocol //
// /////////////////////////////////////////
/**
* Process incoming ICMPv6 packet.
* If it is an ICMPv6 request to router, then sends an ICMPv6 response.
* Otherwise ignore the packet.
*
* @param eth the incoming ICMPv6 packet
* @param inPort the input port
*/
public void processIcmpv6(Ethernet eth, ConnectPoint inPort) {
DeviceId deviceId = inPort.deviceId();
IPv6 ipv6Packet = (IPv6) eth.getPayload();
ICMP6 icmp6 = (ICMP6) ipv6Packet.getPayload();
Ip6Address destinationAddress = Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
IpAddress routerIp;
// Only proceed with echo request
if (icmp6.getIcmpType() != ICMP6.ECHO_REQUEST) {
return;
}
try {
routerIp = config.getRouterIpv6(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting processPacketIn.");
return;
}
// Get pair ip - if it exists
IpAddress pairRouterIp;
try {
DeviceId pairDeviceId = config.getPairDeviceId(deviceId);
pairRouterIp = pairDeviceId != null ? config.getRouterIpv6(pairDeviceId) : null;
} catch (DeviceConfigNotFoundException e) {
pairRouterIp = null;
}
Optional<Ip6Address> linkLocalIp = getLinkLocalIp(inPort);
// Ensure ICMP to the router IP, EUI-64 link-local IP, or gateway IP
if (destinationAddress.equals(routerIp.getIp6Address()) || (linkLocalIp.isPresent() && destinationAddress.equals(linkLocalIp.get())) || (pairRouterIp != null && destinationAddress.equals(pairRouterIp.getIp6Address())) || gatewayIpAddresses.contains(destinationAddress)) {
sendIcmpv6Response(eth, inPort);
} else {
log.trace("Ignore ICMPv6 that targets for {}", destinationAddress);
}
}
use of org.onlab.packet.IpAddress in project trellis-control by opennetworkinglab.
the class IcmpHandler method processIcmp.
// ////////////////////////////////////
// ICMP Echo/Reply Protocol //
// ////////////////////////////////////
/**
* Process incoming ICMP packet.
* If it is an ICMP request to router, then sends an ICMP response.
* Otherwise ignore the packet.
*
* @param eth inbound ICMP packet
* @param inPort the input port
*/
public void processIcmp(Ethernet eth, ConnectPoint inPort) {
DeviceId deviceId = inPort.deviceId();
IPv4 ipv4Packet = (IPv4) eth.getPayload();
ICMP icmp = (ICMP) ipv4Packet.getPayload();
Ip4Address destinationAddress = Ip4Address.valueOf(ipv4Packet.getDestinationAddress());
Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
IpAddress routerIp;
// Only proceed with echo request
if (icmp.getIcmpType() != ICMP.TYPE_ECHO_REQUEST) {
return;
}
try {
routerIp = config.getRouterIpv4(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting processPacketIn.");
return;
}
// Get pair ip - if it exists
IpAddress pairRouterIp;
try {
DeviceId pairDeviceId = config.getPairDeviceId(deviceId);
pairRouterIp = pairDeviceId != null ? config.getRouterIpv4(pairDeviceId) : null;
} catch (DeviceConfigNotFoundException e) {
pairRouterIp = null;
}
// ICMP to the router IP or gateway IP
if (destinationAddress.equals(routerIp.getIp4Address()) || (pairRouterIp != null && destinationAddress.equals(pairRouterIp.getIp4Address())) || gatewayIpAddresses.contains(destinationAddress)) {
sendIcmpResponse(eth, inPort);
} else {
log.trace("Ignore ICMP that targets for {}", destinationAddress);
}
}
use of org.onlab.packet.IpAddress in project trellis-control by opennetworkinglab.
the class SegmentRoutingManager method removeSubnetConfig.
private void removeSubnetConfig(ConnectPoint cp, Set<InterfaceIpAddress> ipAddressSet) {
Set<IpPrefix> ipPrefixSet = ipAddressSet.stream().map(InterfaceIpAddress::subnetAddress).collect(Collectors.toSet());
Set<InterfaceIpAddress> deviceIntfIpAddrs = interfaceService.getInterfaces().stream().filter(intf -> intf.connectPoint().deviceId().equals(cp.deviceId())).filter(intf -> !intf.connectPoint().equals(cp)).flatMap(intf -> intf.ipAddressesList().stream()).collect(Collectors.toSet());
// 1. Partial subnet population
// Remove routing rules for removed subnet from previous configuration,
// which does not also exist in other interfaces in the same device
Set<IpPrefix> deviceIpPrefixSet = deviceIntfIpAddrs.stream().map(InterfaceIpAddress::subnetAddress).collect(Collectors.toSet());
Set<IpPrefix> subnetsToBeRevoked = ipPrefixSet.stream().filter(ipPrefix -> !deviceIpPrefixSet.contains(ipPrefix)).collect(Collectors.toSet());
// Check if any of the subnets to be revoked is configured in the pairDevice.
// If any, repopulate the subnet with pairDevice connectPoint instead of revoking.
Optional<DeviceId> pairDevice = getPairDeviceId(cp.deviceId());
if (pairDevice.isPresent()) {
Set<IpPrefix> pairDeviceIpPrefix = getDeviceSubnetMap().get(pairDevice.get());
Set<IpPrefix> subnetsExistingInPairDevice = subnetsToBeRevoked.stream().filter(ipPrefix -> pairDeviceIpPrefix.contains(ipPrefix)).collect(Collectors.toSet());
// Update the subnets existing in pair device with pair device connect point.
if (!subnetsExistingInPairDevice.isEmpty()) {
// PortNumber of connect point is not relevant in populate subnet and hence providing as ANY.
ConnectPoint pairDeviceCp = new ConnectPoint(pairDevice.get(), PortNumber.ANY);
log.debug("Updating the subnets: {} with pairDevice connectPoint as it exists in the Pair device: {}", subnetsExistingInPairDevice, pairDeviceCp);
defaultRoutingHandler.populateSubnet(Collections.singleton(pairDeviceCp), subnetsExistingInPairDevice);
}
// Remove only the subnets that are not configured in the pairDevice.
subnetsToBeRevoked = Sets.difference(subnetsToBeRevoked, subnetsExistingInPairDevice);
}
if (!subnetsToBeRevoked.isEmpty()) {
log.debug("Removing subnets for connectPoint: {}, subnets: {}", cp, subnetsToBeRevoked);
defaultRoutingHandler.revokeSubnet(subnetsToBeRevoked, cp.deviceId());
}
// 2. Interface IP punts
// Remove IP punts for old Intf address
Set<IpAddress> deviceIpAddrs = deviceIntfIpAddrs.stream().map(InterfaceIpAddress::ipAddress).collect(Collectors.toSet());
ipAddressSet.stream().map(InterfaceIpAddress::ipAddress).filter(interfaceIpAddress -> !deviceIpAddrs.contains(interfaceIpAddress)).forEach(interfaceIpAddress -> routingRulePopulator.revokeSingleIpPunts(cp.deviceId(), interfaceIpAddress));
// 3. Host unicast routing rule
// Remove unicast routing rule
hostEventExecutor.execute(() -> hostHandler.processIntfIpUpdatedEvent(cp, ipPrefixSet, false));
}
use of org.onlab.packet.IpAddress in project trellis-control by opennetworkinglab.
the class SegmentRoutingNeighbourHandler method getSenderInfo.
/**
* Retrieve router (device) info.
*
* @param mac where to copy the mac
* @param ip where to copy the ip
* @param deviceId the device id
* @param targetAddress the target address
* @return true if it was possible to get the necessary info.
* False for errors
*/
protected boolean getSenderInfo(byte[] mac, byte[] ip, DeviceId deviceId, IpAddress targetAddress) {
byte[] senderMacAddress;
byte[] senderIpAddress;
IpAddress sender;
try {
senderMacAddress = config.getDeviceMac(deviceId).toBytes();
if (targetAddress.isIp4()) {
sender = config.getRouterIpAddressForASubnetHost(targetAddress.getIp4Address());
} else {
sender = config.getRouterIpAddressForASubnetHost(targetAddress.getIp6Address());
}
// If sender is null we abort.
if (sender == null) {
log.warn("Sender ip is null. Aborting getSenderInfo");
return false;
}
senderIpAddress = sender.toOctets();
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting getSenderInfo");
return false;
}
System.arraycopy(senderMacAddress, 0, mac, 0, senderMacAddress.length);
System.arraycopy(senderIpAddress, 0, ip, 0, senderIpAddress.length);
return true;
}
use of org.onlab.packet.IpAddress in project trellis-control by opennetworkinglab.
the class McastHandler method recoverFailure.
/**
* General failure recovery procedure.
*
* @param mcastIp the group to recover
* @param failedElement the failed element
*/
private void recoverFailure(IpAddress mcastIp, Object failedElement) {
// Do not proceed if we are not the leaders
if (!mcastUtils.isLeader(mcastIp)) {
log.debug("Skip {} due to lack of leadership", mcastIp);
return;
}
// Skip if it is not an infra failure
Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT);
if (!mcastUtils.isInfraFailure(transitDevices, failedElement)) {
log.debug("Skip {} not an infrastructure failure", mcastIp);
return;
}
// Do not proceed if the sources of this group are missing
Set<ConnectPoint> sources = getSources(mcastIp);
if (sources.isEmpty()) {
log.warn("Missing sources for group {}", mcastIp);
return;
}
// Get all the paths, affected paths, good links and good devices
Set<List<Link>> storedPaths = getStoredPaths(mcastIp);
Set<List<Link>> affectedPaths = mcastUtils.getAffectedPaths(storedPaths, failedElement);
Set<Link> goodLinks = Sets.newHashSet();
Map<DeviceId, Set<DeviceId>> goodDevicesBySource = Maps.newHashMap();
Map<DeviceId, Set<ConnectPoint>> processedSourcesByEgress = Maps.newHashMap();
Sets.difference(storedPaths, affectedPaths).forEach(goodPath -> {
goodLinks.addAll(goodPath);
DeviceId srcDevice = goodPath.get(0).src().deviceId();
Set<DeviceId> goodDevices = Sets.newHashSet();
goodPath.forEach(link -> goodDevices.add(link.src().deviceId()));
goodDevicesBySource.compute(srcDevice, (k, v) -> {
v = v == null ? Sets.newHashSet() : v;
v.addAll(goodDevices);
return v;
});
});
affectedPaths.forEach(affectedPath -> {
// TODO remove
log.info("Good links {}", goodLinks);
// TODO remove
log.info("Good devices {}", goodDevicesBySource);
// TODO trace
log.info("Healing the path {}", affectedPath);
DeviceId srcDevice = affectedPath.get(0).src().deviceId();
DeviceId dstDevice = affectedPath.get(affectedPath.size() - 1).dst().deviceId();
// Fix in one shot multiple sources
Set<ConnectPoint> affectedSources = sources.stream().filter(device -> device.deviceId().equals(srcDevice)).collect(Collectors.toSet());
Set<ConnectPoint> processedSources = processedSourcesByEgress.getOrDefault(dstDevice, Collections.emptySet());
Optional<Path> alternativePath = getPath(srcDevice, dstDevice, mcastIp, null);
// If an alternative is possible go ahead
if (alternativePath.isPresent()) {
// TODO trace
log.info("Alternative path {}", alternativePath.get().links());
} else {
// Otherwise try to come up with an alternative
// TODO trace
log.info("No alternative path");
Set<ConnectPoint> notAffectedSources = Sets.difference(sources, affectedSources);
Set<ConnectPoint> remainingSources = Sets.difference(notAffectedSources, processedSources);
alternativePath = recoverSinks(dstDevice, mcastIp, affectedSources, remainingSources);
processedSourcesByEgress.compute(dstDevice, (k, v) -> {
v = v == null ? Sets.newHashSet() : v;
v.addAll(affectedSources);
return v;
});
}
// Recover from the failure if possible
Optional<Path> finalPath = alternativePath;
affectedSources.forEach(affectedSource -> {
// Update the mcastPath store
McastPathStoreKey mcastPathStoreKey = new McastPathStoreKey(mcastIp, affectedSource);
// Verify if there are local sinks
Set<DeviceId> localSinks = getSinks(mcastIp, srcDevice, affectedSource).stream().map(ConnectPoint::deviceId).collect(Collectors.toSet());
Set<DeviceId> goodDevices = goodDevicesBySource.compute(affectedSource.deviceId(), (k, v) -> {
v = v == null ? Sets.newHashSet() : v;
v.addAll(localSinks);
return v;
});
// TODO remove
log.info("Good devices {}", goodDevicesBySource);
Collection<? extends List<Link>> storedPathsBySource = Versioned.valueOrElse(mcastPathStore.get(mcastPathStoreKey), Lists.newArrayList());
Optional<? extends List<Link>> storedPath = storedPathsBySource.stream().filter(path -> path.equals(affectedPath)).findFirst();
// Remove bad links
affectedPath.forEach(affectedLink -> {
DeviceId affectedDevice = affectedLink.src().deviceId();
// If there is overlap with good paths - skip it
if (!goodLinks.contains(affectedLink)) {
removePortFromDevice(affectedDevice, affectedLink.src().port(), mcastIp, mcastUtils.assignedVlan(affectedDevice.equals(affectedSource.deviceId()) ? affectedSource : null));
}
// Remove role on the affected links if last
if (!goodDevices.contains(affectedDevice)) {
mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, affectedDevice, affectedSource));
}
});
// trying with the original object as workaround
if (storedPath.isPresent()) {
mcastPathStore.remove(mcastPathStoreKey, storedPath.get());
} else {
log.warn("Unable to find the corresponding path - trying removeal");
mcastPathStore.remove(mcastPathStoreKey, affectedPath);
}
// Program new links
if (finalPath.isPresent()) {
List<Link> links = finalPath.get().links();
installPath(mcastIp, affectedSource, links);
mcastPathStore.put(mcastPathStoreKey, links);
links.forEach(link -> goodDevices.add(link.src().deviceId()));
goodDevicesBySource.compute(srcDevice, (k, v) -> {
v = v == null ? Sets.newHashSet() : v;
v.addAll(goodDevices);
return v;
});
goodLinks.addAll(finalPath.get().links());
}
});
});
}
Aggregations