use of org.onosproject.net.Host in project trellis-control by opennetworkinglab.
the class HostHandlerTest method testDelayedIpAndLocation.
@Test
public void testDelayedIpAndLocation() {
Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
// Add a dual-home host with only one location and no IP
// Expect: only bridging redirection works
hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
assertEquals(0, ROUTING_TABLE.size());
assertEquals(2, BRIDGING_TABLE.size());
assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
// Discover IP
// Expect: routing redirection should also work
hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
assertEquals(2, ROUTING_TABLE.size());
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(2, BRIDGING_TABLE.size());
assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
// Expect probe to be sent out on pair device
assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, ProbeMode.DISCOVER));
// Discover location
// Expect: cancel all redirections
hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
assertEquals(2, ROUTING_TABLE.size());
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(2, BRIDGING_TABLE.size());
assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
}
use of org.onosproject.net.Host in project trellis-control by opennetworkinglab.
the class HostHandlerTest method testDualHomingBothLocationFail.
@Test
public void testDualHomingBothLocationFail() {
Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
// Add a host
// Expect: add four new routing rules, two new bridging rules
hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
assertEquals(4, ROUTING_TABLE.size());
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
assertEquals(2, BRIDGING_TABLE.size());
assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
// Host becomes single-homed
// Expect: redirect flows from host location to pair link
hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
assertEquals(4, ROUTING_TABLE.size());
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
assertEquals(2, BRIDGING_TABLE.size());
assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
// Host loses both locations
// Expect: Remove last location and all previous redirection flows
hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
assertEquals(0, ROUTING_TABLE.size());
assertEquals(0, BRIDGING_TABLE.size());
}
use of org.onosproject.net.Host in project trellis-control by opennetworkinglab.
the class HostHandlerTest method testHostRemovedWithRouteRemoved.
@Test
public void testHostRemovedWithRouteRemoved() {
Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
// Add a host
// Expect: add one routing rule and one bridging rule
hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
assertEquals(1, ROUTING_TABLE.size());
assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
assertEquals(1, BRIDGING_TABLE.size());
assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
IpPrefix prefix = IpPrefix.valueOf("55.55.55.0/24");
// Setting up mock route service
RouteService routeService = hostHandler.srManager.routeService;
reset(routeService);
IpAddress nextHopIp2 = IpAddress.valueOf("20.0.0.1");
MacAddress nextHopMac2 = MacAddress.valueOf("00:22:33:44:55:66");
VlanId nextHopVlan2 = VlanId.NONE;
Route r1 = new Route(Route.Source.STATIC, prefix, HOST_IP11);
ResolvedRoute rr1 = new ResolvedRoute(r1, HOST_MAC, VlanId.NONE);
Route r2 = new Route(Route.Source.STATIC, prefix, nextHopIp2);
ResolvedRoute rr2 = new ResolvedRoute(r2, nextHopMac2, nextHopVlan2);
RouteInfo routeInfo = new RouteInfo(prefix, rr1, Sets.newHashSet(rr1, rr2));
RouteTableId routeTableId = new RouteTableId("ipv4");
expect(routeService.getRouteTables()).andReturn(Sets.newHashSet(routeTableId));
expect(routeService.getRoutes(routeTableId)).andReturn(Sets.newHashSet(routeInfo));
replay(routeService);
// Setting up mock device configuration
hostHandler.srManager.deviceConfiguration = EasyMock.createNiceMock(DeviceConfiguration.class);
DeviceConfiguration deviceConfiguration = hostHandler.srManager.deviceConfiguration;
expect(deviceConfiguration.inSameSubnet(CP11, HOST_IP11)).andReturn(true);
deviceConfiguration.removeSubnet(CP11, prefix);
expectLastCall();
replay(deviceConfiguration);
// Remove the host
// Expect: add the routing rule and the bridging rule
hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
assertEquals(0, ROUTING_TABLE.size());
assertEquals(0, BRIDGING_TABLE.size());
// Expect: subnet is removed from device config
verify(deviceConfiguration);
}
use of org.onosproject.net.Host in project trellis-control by opennetworkinglab.
the class SegmentRoutingManager method addSubnetConfig.
private void addSubnetConfig(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
// Add routing rules for newly added subnet, 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> subnetsToBePopulated = ipPrefixSet.stream().filter(ipPrefix -> !deviceIpPrefixSet.contains(ipPrefix)).collect(Collectors.toSet());
if (!subnetsToBePopulated.isEmpty()) {
log.debug("Adding subnets for connectPoint: {}, subnets: {}", cp, subnetsToBePopulated);
// check if pair-device has the same subnet configured
Optional<DeviceId> pairDevice = getPairDeviceId(cp.deviceId());
if (pairDevice.isPresent()) {
Set<IpPrefix> pairDeviceIpPrefix = getDeviceSubnetMap().get(pairDevice.get());
Set<IpPrefix> subnetsToBePopulatedAsDualHomed = subnetsToBePopulated.stream().filter(pairDeviceIpPrefix::contains).collect(Collectors.toSet());
Set<IpPrefix> subnetsToBePopulatedAsSingleHomed = Sets.difference(subnetsToBePopulated, subnetsToBePopulatedAsDualHomed);
if (!subnetsToBePopulatedAsSingleHomed.isEmpty()) {
defaultRoutingHandler.populateSubnet(Collections.singleton(cp), subnetsToBePopulatedAsSingleHomed);
}
if (!subnetsToBePopulatedAsDualHomed.isEmpty()) {
Set<ConnectPoint> cpts = new HashSet<>();
cpts.add(cp);
// As Subnets is DualHomed adding the pairDevice also as ConnectPoint.
// PortNumber of connect point is not relevant in populate subnet and hence providing as ANY.
ConnectPoint pairCp = new ConnectPoint(pairDevice.get(), PortNumber.ANY);
cpts.add(pairCp);
log.debug("Adding DualHomed subnets for connectPoint: {} and its pair device: {}, subnets: {}", cp, pairCp, subnetsToBePopulatedAsDualHomed);
// populating the subnets as DualHomed
defaultRoutingHandler.populateSubnet(cpts, subnetsToBePopulated);
// revoking the subnets populated in the device as it is now Dualhomed.
defaultRoutingHandler.revokeSubnet(Collections.singleton(cp.deviceId()), subnetsToBePopulatedAsDualHomed);
}
} else {
defaultRoutingHandler.populateSubnet(Collections.singleton(cp), subnetsToBePopulated);
}
}
// 2. Interface IP punts
// Add IP punts for new 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.populateSingleIpPunts(cp.deviceId(), interfaceIpAddress));
// 3. Host unicast routing rule
// Add unicast routing rule
hostEventExecutor.execute(() -> hostHandler.processIntfIpUpdatedEvent(cp, ipPrefixSet, true));
}
use of org.onosproject.net.Host 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);
}
});
}
}
Aggregations