use of org.onlab.packet.EthType in project trellis-control by opennetworkinglab.
the class HostHandler method processHostMovedEventInternal.
private void processHostMovedEventInternal(HostEvent event) {
// This method will be called when one of the following value has changed:
// (1) locations (2) auxLocations or (3) both locations and auxLocations.
// We only need to proceed when effectiveLocation has changed.
Set<HostLocation> newLocations = effectiveLocations(event.subject());
Set<HostLocation> prevLocations = effectiveLocations(event.prevSubject());
if (newLocations.equals(prevLocations)) {
log.info("effectiveLocations of {} has not changed. Skipping {}", event.subject().id(), event);
return;
}
Host host = event.subject();
Host prevHost = event.prevSubject();
MacAddress hostMac = host.mac();
VlanId hostVlanId = host.vlan();
Set<IpAddress> prevIps = prevHost.ipAddresses();
Set<IpAddress> newIps = host.ipAddresses();
EthType hostTpid = host.tpid();
boolean doubleTaggedHost = isDoubleTaggedHost(host);
log.info("Host {}/{} is moved from {} to {}", hostMac, hostVlanId, prevLocations, newLocations);
Set<DeviceId> newDeviceIds = newLocations.stream().map(HostLocation::deviceId).collect(Collectors.toSet());
// For each old location
Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
// Remove routing rules for old IPs
Sets.difference(prevIps, newIps).forEach(ip -> {
if (doubleTaggedHost) {
processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
} else {
processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, ip, true);
}
});
// Redirect the flows to pair link if configured
// Note: Do not continue removing any rule
Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId());
Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(prevLocation.deviceId());
if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream().anyMatch(location -> location.deviceId().equals(pairDeviceId.get())) && newLocations.stream().noneMatch(location -> location.deviceId().equals(prevLocation.deviceId()))) {
// NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
// when the host is untagged
VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(prevLocation)).orElse(hostVlanId);
processBridgingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId, false);
newIps.forEach(ip -> processRoutingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId, ip, false));
return;
}
// Otherwise, do not remove and let the adding part update the old flow
if (!newDeviceIds.contains(prevLocation.deviceId())) {
processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
Sets.intersection(prevIps, newIps).forEach(ip -> {
if (doubleTaggedHost) {
processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
} else {
processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, ip, true);
}
});
}
// Otherwise, do not remove and let the adding part update the old flow
if (newLocations.stream().noneMatch(newLocation -> {
VlanId oldAssignedVlan = srManager.getInternalVlanId(prevLocation);
VlanId newAssignedVlan = srManager.getInternalVlanId(newLocation);
// Host is tagged and the new location has the host vlan in vlan-tagged
return srManager.interfaceService.getTaggedVlanId(newLocation).contains(hostVlanId) || (oldAssignedVlan != null && newAssignedVlan != null && // Host is untagged and the new location has the same assigned vlan
oldAssignedVlan.equals(newAssignedVlan));
})) {
processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
}
// Remove routing rules for unchanged IPs if none of the subnet of new location contains
// the IP. Otherwise, do not remove and let the adding part update the old flow
Sets.intersection(prevIps, newIps).forEach(ip -> {
if (newLocations.stream().noneMatch(newLocation -> srManager.deviceConfiguration.inSameSubnet(newLocation, ip))) {
if (doubleTaggedHost) {
processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
} else {
processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, ip, true);
}
}
});
});
// For each new location, add all new IPs.
Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
processBridgingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId, false);
newIps.forEach(ip -> {
if (doubleTaggedHost) {
processDoubleTaggedRoutingRule(newLocation.deviceId(), newLocation.port(), hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, false);
} else {
processRoutingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId, ip, false);
}
});
// But will also cover [1A/x] -> [1A/y] -> [1A/y, 1B/y]
if (srManager.activeProbing) {
srManager.getPairDeviceId(newLocation.deviceId()).ifPresent(pairDeviceId -> srManager.getPairLocalPort(pairDeviceId).ifPresent(pairRemotePort -> probe(host, newLocation, pairDeviceId, pairRemotePort)));
}
});
// For each unchanged location, add new IPs and remove old IPs.
Sets.intersection(newLocations, prevLocations).forEach(unchangedLocation -> {
Sets.difference(prevIps, newIps).forEach(ip -> {
if (doubleTaggedHost) {
processDoubleTaggedRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
} else {
processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac, hostVlanId, ip, true);
}
});
Sets.difference(newIps, prevIps).forEach(ip -> {
if (doubleTaggedHost) {
processDoubleTaggedRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, false);
} else {
processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac, hostVlanId, ip, false);
}
});
// Verify existing location and see if it is still valid
srManager.probingService.probeHost(host, unchangedLocation, ProbeMode.VERIFY);
});
// ensure dual-homed host locations have viable uplinks
if (newLocations.size() > prevLocations.size() || srManager.singleHomedDown) {
newLocations.forEach(loc -> {
if (srManager.shouldProgram(loc.deviceId())) {
srManager.linkHandler.checkUplinksForHost(loc);
}
});
}
}
use of org.onlab.packet.EthType in project trellis-control by opennetworkinglab.
the class HostHandler method processHostUpdatedEventInternal.
private void processHostUpdatedEventInternal(HostEvent event) {
Host host = event.subject();
MacAddress hostMac = host.mac();
VlanId hostVlanId = host.vlan();
EthType hostTpid = host.tpid();
Set<HostLocation> locations = effectiveLocations(host);
Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
Set<IpAddress> newIps = host.ipAddresses();
log.info("Host {}/{} is updated", hostMac, hostVlanId);
locations.forEach(location -> {
Sets.difference(prevIps, newIps).forEach(ip -> {
if (isDoubleTaggedHost(host)) {
processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
} else {
processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, true);
}
});
Sets.difference(newIps, prevIps).forEach(ip -> {
if (isDoubleTaggedHost(host)) {
processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, false);
} else {
processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, false);
}
});
});
// Use the pair link temporarily before the second location of a dual-homed host shows up.
// This do not affect single-homed hosts since the flow will be blocked in
// processBridgingRule or processRoutingRule due to VLAN or IP mismatch respectively
locations.forEach(location -> srManager.getPairDeviceId(location.deviceId()).ifPresent(pairDeviceId -> {
if (locations.stream().noneMatch(l -> l.deviceId().equals(pairDeviceId))) {
Set<IpAddress> ipsToAdd = Sets.difference(newIps, prevIps);
Set<IpAddress> ipsToRemove = Sets.difference(prevIps, newIps);
srManager.getPairLocalPort(pairDeviceId).ifPresent(pairRemotePort -> {
// NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
// when the host is untagged
VlanId vlanId = vlanForPairPort(hostVlanId, location);
if (vlanId == null) {
return;
}
ipsToRemove.forEach(ip -> processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, ip, true));
ipsToAdd.forEach(ip -> processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, ip, false));
if (srManager.activeProbing) {
probe(host, location, pairDeviceId, pairRemotePort);
}
});
}
}));
}
Aggregations