Adding a component config to take down single homed host ports when all uplinks are lost.
In addition:
- handle port updates that may be lost if mastership changes at same time
- fix javadoc in DeviceService
Change-Id: I032909e8ab9564cf9c978b1d66abd3ab32c814d7
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index e8f7019..8b83f24 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -1224,6 +1224,7 @@
private MastershipEvent me;
private static final long CLUSTER_EVENT_THRESHOLD = 4500; // ms
private static final long DEVICE_EVENT_THRESHOLD = 2000; // ms
+ private static final long EDGE_PORT_EVENT_THRESHOLD = 10000; //ms
MasterChange(DeviceId devId, MastershipEvent me) {
this.devId = devId;
@@ -1261,12 +1262,16 @@
return;
}
+ long lepe = Instant.now().toEpochMilli()
+ - srManager.lastEdgePortEvent.toEpochMilli();
+ boolean edgePortEvent = lepe < EDGE_PORT_EVENT_THRESHOLD;
+
// if it gets here, then mastership change is likely due to onos
// instance failure, or network partition in onos cluster
// normally a mastership change like this does not require re-programming
// but if topology changes happen at the same time then we may miss events
if (!isRoutingStable() && clusterEvent) {
- log.warn("Mastership changed for dev: {}/{} while programming "
+ log.warn("Mastership changed for dev: {}/{} while programming route-paths "
+ "due to clusterEvent {} ms ago .. attempting full reroute",
devId, me.roleInfo(), lce);
if (srManager.mastershipService.isLocalMaster(devId)) {
@@ -1278,6 +1283,19 @@
// XXX right now we have no fine-grained way to only make changes
// for the route paths affected by this device.
populateAllRoutingRules();
+
+ } else if (edgePortEvent && clusterEvent) {
+ log.warn("Mastership changed for dev: {}/{} due to clusterEvent {} ms ago "
+ + "while edge-port event happened {} ms ago "
+ + " .. reprogramming all edge-ports",
+ devId, me.roleInfo(), lce, lepe);
+ if (shouldProgram(devId)) {
+ srManager.deviceService.getPorts(devId).stream()
+ .filter(p -> srManager.interfaceService
+ .isConfigured(new ConnectPoint(devId, p.number())))
+ .forEach(p -> srManager.processPortUpdated(devId, p));
+ }
+
} else {
log.debug("Stable route-paths .. full reroute not attempted for "
+ "mastership change {}/{} deviceEvent/timeSince: {}/{} "
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index 5fdbf69..6b49215 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -76,10 +76,10 @@
private void processHostAdded(Host host) {
host.locations().forEach(location -> processHostAddedAtLocation(host, location));
// ensure dual-homed host locations have viable uplinks
- if (host.locations().size() > 1) {
+ if (host.locations().size() > 1 || srManager.singleHomedDown) {
host.locations().forEach(loc -> {
if (srManager.mastershipService.isLocalMaster(loc.deviceId())) {
- srManager.linkHandler.checkUplinksForDualHomedHosts(loc);
+ srManager.linkHandler.checkUplinksForHost(loc);
}
});
}
@@ -104,7 +104,7 @@
// processBridgingRule or processRoutingRule due to VLAN or IP mismatch respectively
srManager.getPairDeviceId(location.deviceId()).ifPresent(pairDeviceId -> {
if (host.locations().stream().noneMatch(l -> l.deviceId().equals(pairDeviceId))) {
- srManager.getPairLocalPorts(pairDeviceId).ifPresent(pairRemotePort -> {
+ 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 = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(hostVlanId);
@@ -140,7 +140,7 @@
// Also remove redirection flows on the pair device if exists.
Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
- Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(location.deviceId());
+ Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(location.deviceId());
if (pairDeviceId.isPresent() && pairLocalPort.isPresent()) {
// NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
// when the host is untagged
@@ -182,7 +182,7 @@
// 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.getPairLocalPorts(prevLocation.deviceId());
+ Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(prevLocation.deviceId());
if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream()
.anyMatch(location -> location.deviceId().equals(pairDeviceId.get()))) {
// NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
@@ -254,10 +254,10 @@
});
// ensure dual-homed host locations have viable uplinks
- if (newLocations.size() > prevLocations.size()) {
+ if (newLocations.size() > prevLocations.size() || srManager.singleHomedDown) {
newLocations.forEach(loc -> {
if (srManager.mastershipService.isLocalMaster(loc.deviceId())) {
- srManager.linkHandler.checkUplinksForDualHomedHosts(loc);
+ srManager.linkHandler.checkUplinksForHost(loc);
}
});
}
@@ -290,7 +290,7 @@
Set<IpAddress> ipsToAdd = Sets.difference(newIps, prevIps);
Set<IpAddress> ipsToRemove = Sets.difference(prevIps, newIps);
- srManager.getPairLocalPorts(pairDeviceId).ifPresent(pairRemotePort -> {
+ 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 = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(hostVlanId);
@@ -319,7 +319,7 @@
* @param cp connect point
*/
void processPortUp(ConnectPoint cp) {
- if (cp.port().equals(srManager.getPairLocalPorts(cp.deviceId()).orElse(null))) {
+ if (cp.port().equals(srManager.getPairLocalPort(cp.deviceId()).orElse(null))) {
return;
}
if (srManager.activeProbing) {
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
index 23caadc..5e41dc5 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
@@ -23,6 +23,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostLocation;
@@ -160,7 +161,7 @@
if (srManager.mastershipService.isLocalMaster(ulink.src().deviceId())) {
// handle edge-ports for dual-homed hosts
- updateDualHomedHostPorts(ulink, true);
+ updateHostPorts(ulink, true);
// It's possible that linkUp causes no route-path change as ECMP graph does
// not change if the link is a parallel link (same src-dst as
@@ -207,7 +208,7 @@
updateSeenLink(link, false);
// handle edge-ports for dual-homed hosts
if (srManager.mastershipService.isLocalMaster(link.src().deviceId())) {
- updateDualHomedHostPorts(link, false);
+ updateHostPorts(link, false);
}
// device availability check helps to ensure that multiple link-removed
@@ -329,13 +330,15 @@
/**
* Administratively enables or disables edge ports if the link that was
- * added or removed was the only uplink port from an edge device. Only edge
- * ports that belong to dual-homed hosts are considered.
+ * added or removed was the only uplink port from an edge device. Edge ports
+ * that belong to dual-homed hosts are always processed. In addition,
+ * single-homed host ports are optionally processed depending on the
+ * singleHomedDown property.
*
* @param link the link to be processed
* @param added true if link was added, false if link was removed
*/
- private void updateDualHomedHostPorts(Link link, boolean added) {
+ private void updateHostPorts(Link link, boolean added) {
if (added) {
DeviceConfiguration devConfig = srManager.deviceConfiguration;
try {
@@ -361,20 +364,38 @@
return;
}
// find dual homed hosts on this dev to disable
- Set<PortNumber> dhp = srManager.hostHandler
- .getDualHomedHostPorts(link.src().deviceId());
- log.warn("Link src {} -->dst {} removed was the last uplink, "
- + "disabling dual homed ports: {}", link.src().deviceId(),
- link.dst().deviceId(), (dhp.isEmpty()) ? "no ports" : dhp);
- dhp.forEach(pnum -> srManager.deviceAdminService
- .changePortState(link.src().deviceId(), pnum, false));
- if (!dhp.isEmpty()) {
+ DeviceId dev = link.src().deviceId();
+ Set<PortNumber> dp = srManager.hostHandler
+ .getDualHomedHostPorts(dev);
+ log.warn("Link src {} --> dst {} removed was the last uplink, "
+ + "disabling dual homed ports: {}", dev,
+ link.dst().deviceId(), (dp.isEmpty()) ? "no ports" : dp);
+ dp.forEach(pnum -> srManager.deviceAdminService
+ .changePortState(dev, pnum, false));
+ if (srManager.singleHomedDown) {
+ // get all configured ports and down them if they haven't already
+ // been downed
+ srManager.deviceService.getPorts(dev).stream()
+ .filter(p -> p.isEnabled() && !dp.contains(p.number()))
+ .filter(p -> srManager.interfaceService
+ .isConfigured(new ConnectPoint(dev, p.number())))
+ .filter(p -> !srManager.deviceConfiguration
+ .isPairLocalPort(dev, p.number()))
+ .forEach(p -> {
+ log.warn("Last uplink gone src {} -> dst {} .. removing "
+ + "configured port {}", p.number());
+ srManager.deviceAdminService
+ .changePortState(dev, p.number(), false);
+ dp.add(p.number());
+ });
+ }
+ if (!dp.isEmpty()) {
// update global store
- Set<PortNumber> p = downedPortStore.get(link.src().deviceId());
+ Set<PortNumber> p = downedPortStore.get(dev);
if (p == null) {
- p = dhp;
+ p = dp;
} else {
- p.addAll(dhp);
+ p.addAll(dp);
}
downedPortStore.put(link.src().deviceId(), p);
}
@@ -632,11 +653,12 @@
/**
* Administratively disables the host location switchport if the edge device
- * has no viable uplinks.
+ * has no viable uplinks. The caller needs to determine if such behavior is
+ * desired for the single or dual-homed host.
*
- * @param loc one of the locations of the dual-homed host
+ * @param loc the host location
*/
- void checkUplinksForDualHomedHosts(HostLocation loc) {
+ void checkUplinksForHost(HostLocation loc) {
try {
for (Link l : srManager.linkService.getDeviceLinks(loc.deviceId())) {
if (srManager.deviceConfiguration.isEdgeDevice(l.dst().deviceId())
@@ -651,8 +673,7 @@
+ "config " + e.getMessage());
return;
}
- log.warn("Dual homed host location {} has no valid uplinks; "
- + "disabling dual homed port", loc);
+ log.warn("Host location {} has no valid uplinks disabling port", loc);
srManager.deviceAdminService.changePortState(loc.deviceId(), loc.port(),
false);
Set<PortNumber> p = downedPortStore.get(loc.deviceId());
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
index 9f97987..d930923 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
@@ -213,7 +213,7 @@
// Also remove redirection flows on the pair device if exists.
Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
- Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(location.deviceId());
+ Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(location.deviceId());
if (pairDeviceId.isPresent() && pairLocalPort.isPresent()) {
// NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
// when the host is untagged
@@ -245,7 +245,7 @@
// 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.getPairLocalPorts(prevLocation.deviceId());
+ Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(prevLocation.deviceId());
if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream()
.anyMatch(location -> location.deviceId().equals(pairDeviceId.get()))) {
// NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 06b650d..9774a61 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -1193,7 +1193,7 @@
srManager.flowObjectiveService.forward(deviceId, obj);
});
- srManager.getPairLocalPorts(deviceId).ifPresent(port -> {
+ srManager.getPairLocalPort(deviceId).ifPresent(port -> {
ForwardingObjective pairFwdObj;
// Do not punt ARP packets from pair port
pairFwdObj = arpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1)
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 0322201..c12918b 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -226,6 +226,11 @@
label = "Enable active probing to discover dual-homed hosts.")
boolean activeProbing = true;
+ @Property(name = "singleHomedDown", boolValue = false,
+ label = "Enable administratively taking down single-homed hosts "
+ + "when all uplinks are gone")
+ boolean singleHomedDown = false;
+
ArpHandler arpHandler = null;
IcmpHandler icmpHandler = null;
IpHandler ipHandler = null;
@@ -342,6 +347,8 @@
*/
public static final VlanId INTERNAL_VLAN = VlanId.vlanId((short) 4094);
+ Instant lastEdgePortEvent = Instant.EPOCH;
+
@Activate
protected void activate(ComponentContext context) {
appId = coreService.registerApplication(APP_NAME);
@@ -540,11 +547,29 @@
String strActiveProving = Tools.get(properties, "activeProbing");
boolean expectActiveProbing = Boolean.parseBoolean(strActiveProving);
-
if (expectActiveProbing != activeProbing) {
activeProbing = expectActiveProbing;
log.info("{} active probing", activeProbing ? "Enabling" : "Disabling");
}
+
+ String strSingleHomedDown = Tools.get(properties, "singleHomedDown");
+ boolean expectSingleHomedDown = Boolean.parseBoolean(strSingleHomedDown);
+ if (expectSingleHomedDown != singleHomedDown) {
+ singleHomedDown = expectSingleHomedDown;
+ log.info("{} downing of single homed hosts for lost uplinks",
+ singleHomedDown ? "Enabling" : "Disabling");
+ if (singleHomedDown && linkHandler != null) {
+ hostService.getHosts().forEach(host -> host.locations()
+ .forEach(loc -> {
+ if (interfaceService.isConfigured(loc)) {
+ linkHandler.checkUplinksForHost(loc);
+ }
+ }));
+ } else {
+ log.warn("Disabling singleHomedDown does not re-enable already "
+ + "downed ports for single-homed hosts");
+ }
+ }
}
@Override
@@ -879,7 +904,7 @@
* @param deviceId device ID
* @return optional pair device ID. Might be empty if pair device is not configured
*/
- Optional<PortNumber> getPairLocalPorts(DeviceId deviceId) {
+ public Optional<PortNumber> getPairLocalPort(DeviceId deviceId) {
SegmentRoutingDeviceConfig deviceConfig =
cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
return Optional.ofNullable(deviceConfig).map(SegmentRoutingDeviceConfig::pairLocalPort);
@@ -1087,7 +1112,7 @@
event.subject(),
((DeviceEvent) event).port(),
event.type());
- processPortUpdated(((Device) event.subject()),
+ processPortUpdatedInternal(((Device) event.subject()),
((DeviceEvent) event).port());
} else if (event.type() == TopologyEvent.Type.TOPOLOGY_CHANGED) {
// Process topology event, needed for all modules relying on
@@ -1298,73 +1323,88 @@
.forEach(entry -> dsNextObjStore.remove(entry.getKey()));
}
- private void processPortUpdated(Device device, Port port) {
+ private void processPortUpdatedInternal(Device device, Port port) {
if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
log.warn("Device configuration uploading. Not handling port event for"
+ "dev: {} port: {}", device.id(), port.number());
return;
}
+ if (interfaceService.isConfigured(new ConnectPoint(device.id(), port.number()))) {
+ lastEdgePortEvent = Instant.now();
+ }
+
if (!mastershipService.isLocalMaster(device.id())) {
log.debug("Not master for dev:{} .. not handling port updated event"
+ "for port {}", device.id(), port.number());
return;
}
+ processPortUpdated(device.id(), port);
+ }
+ /**
+ * Adds or remove filtering rules for the given switchport. If switchport is
+ * an edge facing port, additionally handles host probing and broadcast
+ * rules. Must be called by local master of device.
+ *
+ * @param deviceId the device identifier
+ * @param port the port to update
+ */
+ void processPortUpdated(DeviceId deviceId, Port port) {
// first we handle filtering rules associated with the port
if (port.isEnabled()) {
log.info("Switchport {}/{} enabled..programming filters",
- device.id(), port.number());
- routingRulePopulator.processSinglePortFilters(device.id(), port.number(), true);
+ deviceId, port.number());
+ routingRulePopulator.processSinglePortFilters(deviceId, port.number(), true);
} else {
log.info("Switchport {}/{} disabled..removing filters",
- device.id(), port.number());
- routingRulePopulator.processSinglePortFilters(device.id(), port.number(), false);
+ deviceId, port.number());
+ routingRulePopulator.processSinglePortFilters(deviceId, port.number(), false);
}
// portUpdated calls are for ports that have gone down or up. For switch
// to switch ports, link-events should take care of any re-routing or
// group editing necessary for port up/down. Here we only process edge ports
// that are already configured.
- ConnectPoint cp = new ConnectPoint(device.id(), port.number());
+ ConnectPoint cp = new ConnectPoint(deviceId, port.number());
VlanId untaggedVlan = getUntaggedVlanId(cp);
VlanId nativeVlan = getNativeVlanId(cp);
Set<VlanId> taggedVlans = getTaggedVlanId(cp);
if (untaggedVlan == null && nativeVlan == null && taggedVlans.isEmpty()) {
log.debug("Not handling port updated event for non-edge port (unconfigured) "
- + "dev/port: {}/{}", device.id(), port.number());
+ + "dev/port: {}/{}", deviceId, port.number());
return;
}
if (untaggedVlan != null) {
- processEdgePort(device, port, untaggedVlan, true);
+ processEdgePort(deviceId, port, untaggedVlan, true);
}
if (nativeVlan != null) {
- processEdgePort(device, port, nativeVlan, true);
+ processEdgePort(deviceId, port, nativeVlan, true);
}
if (!taggedVlans.isEmpty()) {
- taggedVlans.forEach(tag -> processEdgePort(device, port, tag, false));
+ taggedVlans.forEach(tag -> processEdgePort(deviceId, port, tag, false));
}
}
- private void processEdgePort(Device device, Port port, VlanId vlanId,
+ private void processEdgePort(DeviceId deviceId, Port port, VlanId vlanId,
boolean popVlan) {
boolean portUp = port.isEnabled();
if (portUp) {
- log.info("Device:EdgePort {}:{} is enabled in vlan: {}", device.id(),
+ log.info("Device:EdgePort {}:{} is enabled in vlan: {}", deviceId,
port.number(), vlanId);
- hostHandler.processPortUp(new ConnectPoint(device.id(), port.number()));
+ hostHandler.processPortUp(new ConnectPoint(deviceId, port.number()));
} else {
- log.info("Device:EdgePort {}:{} is disabled in vlan: {}", device.id(),
+ log.info("Device:EdgePort {}:{} is disabled in vlan: {}", deviceId,
port.number(), vlanId);
}
- DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
+ DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
if (groupHandler != null) {
groupHandler.processEdgePort(port.number(), vlanId, popVlan, portUp);
} else {
log.warn("Group handler not found for dev:{}. Not handling edge port"
- + " {} event for port:{}", device.id(),
+ + " {} event for port:{}", deviceId,
(portUp) ? "UP" : "DOWN", port.number());
}
}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
index 0282fa4..626109a 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
@@ -725,4 +725,7 @@
}
}
+ public boolean isPairLocalPort(DeviceId devId, PortNumber pnum) {
+ return pnum.equals(srManager.getPairLocalPort(devId).orElse(null));
+ }
}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java
index 2819c9d..fe5df5d 100644
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java
+++ b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java
@@ -29,7 +29,7 @@
}
@Override
- void checkUplinksForDualHomedHosts(HostLocation loc) {
+ void checkUplinksForHost(HostLocation loc) {
// currently does nothing - can be extended to be a useful mock when
// implementing unit tests for link handling
}
diff --git a/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java b/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
index 2e42254..bd1602f 100644
--- a/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
+++ b/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
@@ -421,6 +421,23 @@
.filter(intf -> intf.ipAddressesList().contains(ip))
.collect(Collectors.toSet());
}
+
+ @Override
+ public boolean isConfigured(ConnectPoint connectPoint) {
+ for (Interface intf : AVAILABLE_INTERFACES) {
+ if (!intf.connectPoint().equals(connectPoint)) {
+ continue;
+ }
+ if (!intf.ipAddressesList().isEmpty()
+ || intf.vlan() != VlanId.NONE
+ || intf.vlanNative() != VlanId.NONE
+ || intf.vlanUntagged() != VlanId.NONE
+ || !intf.vlanTagged().isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
diff --git a/core/api/src/main/java/org/onosproject/net/device/DeviceService.java b/core/api/src/main/java/org/onosproject/net/device/DeviceService.java
index f86a98a..86d9025 100644
--- a/core/api/src/main/java/org/onosproject/net/device/DeviceService.java
+++ b/core/api/src/main/java/org/onosproject/net/device/DeviceService.java
@@ -187,11 +187,11 @@
/**
- * Indicates how long ago the device connected or disconnected from this
- * controller instance as a time offset.
+ * Indicates the time at which the given device connected or disconnected
+ * from this controller instance.
*
* @param deviceId device identifier
- * @return time offset in miliseconds
+ * @return time offset in miliseconds from Epoch
*/
long getLastUpdatedInstant(DeviceId deviceId);
diff --git a/core/api/src/main/java/org/onosproject/net/intf/InterfaceService.java b/core/api/src/main/java/org/onosproject/net/intf/InterfaceService.java
index 3e2f742..09743df 100644
--- a/core/api/src/main/java/org/onosproject/net/intf/InterfaceService.java
+++ b/core/api/src/main/java/org/onosproject/net/intf/InterfaceService.java
@@ -87,4 +87,13 @@
* @return a set of interfaces
*/
Set<Interface> getMatchingInterfaces(IpAddress ip);
+
+ /**
+ * Returns true if given connectPoint has an IP address or vlan configured
+ * on any of its interfaces.
+ *
+ * @param connectPoint the port on a device
+ * @return true if connectpoint has a configured interface
+ */
+ boolean isConfigured(ConnectPoint connectPoint);
}
diff --git a/core/api/src/test/java/org/onosproject/net/intf/InterfaceServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/intf/InterfaceServiceAdapter.java
index 8eb2214..b5f1673 100644
--- a/core/api/src/test/java/org/onosproject/net/intf/InterfaceServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/intf/InterfaceServiceAdapter.java
@@ -70,4 +70,9 @@
public void removeListener(InterfaceListener listener) {
}
+
+ @Override
+ public boolean isConfigured(ConnectPoint connectPoint) {
+ return false;
+ }
}
diff --git a/core/net/src/main/java/org/onosproject/net/intf/impl/InterfaceManager.java b/core/net/src/main/java/org/onosproject/net/intf/impl/InterfaceManager.java
index 7a28bc48..b4e01b7 100644
--- a/core/net/src/main/java/org/onosproject/net/intf/impl/InterfaceManager.java
+++ b/core/net/src/main/java/org/onosproject/net/intf/impl/InterfaceManager.java
@@ -168,6 +168,23 @@
.collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
}
+ @Override
+ public boolean isConfigured(ConnectPoint connectPoint) {
+ Set<Interface> intfs = interfaces.get(connectPoint);
+ if (intfs == null) {
+ return false;
+ }
+ for (Interface intf : intfs) {
+ if (!intf.ipAddressesList().isEmpty() || intf.vlan() != VlanId.NONE
+ || intf.vlanNative() != VlanId.NONE
+ || intf.vlanUntagged() != VlanId.NONE
+ || !intf.vlanTagged().isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void updateInterfaces(InterfaceConfig intfConfig) {
try {
Set<Interface> old = interfaces.put(intfConfig.subject(),
@@ -268,4 +285,5 @@
}
}
}
+
}
diff --git a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
index a1d3d4d..f7b2f77 100644
--- a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
+++ b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
@@ -1190,6 +1190,7 @@
return null;
}
+ @Override
public Set<Interface> getInterfacesByIp(IpAddress ip) {
if (ip.equals(GW_IFACE_ADDR.ipAddress())) {
return ImmutableSet.of(GW_IFACE);
@@ -1222,5 +1223,10 @@
public void removeListener(InterfaceListener listener) {
}
+
+ @Override
+ public boolean isConfigured(ConnectPoint connectPoint) {
+ return false;
+ }
}
}