Only remove TMAC flow when it is the last port within the same VLAN if TMAC doesn't support in_port matching
- Address an edge case that was not considered in 16418
- Add some unit tests
Change-Id: Ie999850ce0101b528391d45989390924411817f9
diff --git a/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index f37caea..c152b99 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -65,6 +65,7 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.packet.Ethernet.TYPE_ARP;
@@ -846,16 +847,7 @@
// NOTE: Some switch hardware share the same filtering flow among different ports.
// We use this metadata to let the driver know that there is no more enabled port
// within the same VLAN on this device.
- boolean noMoreEnabledPort = srManager.interfaceService.getInterfaces().stream()
- .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
- .filter(intf -> intf.vlanTagged().contains(vlanId) ||
- intf.vlanUntagged().equals(vlanId) ||
- intf.vlanNative().equals(vlanId))
- .noneMatch(intf -> {
- Port port = srManager.deviceService.getPort(intf.connectPoint());
- return port != null && port.isEnabled();
- });
- if (noMoreEnabledPort) {
+ if (noMoreEnabledPort(deviceId, vlanId)) {
tBuilder.wipeDeferred();
}
@@ -1247,4 +1239,28 @@
}
}
}
+
+ /**
+ * Checks if there is other enabled port within the given VLAN on the given device.
+ *
+ * @param deviceId device ID
+ * @param vlanId VLAN ID
+ * @return true if there is no more port enabled within the given VLAN on the given device
+ */
+ boolean noMoreEnabledPort(DeviceId deviceId, VlanId vlanId) {
+ Set<ConnectPoint> enabledPorts = srManager.deviceService.getPorts(deviceId).stream()
+ .filter(Port::isEnabled)
+ .map(port -> new ConnectPoint(port.element().id(), port.number()))
+ .collect(Collectors.toSet());
+
+ return enabledPorts.stream().noneMatch(cp ->
+ // Given vlanId is included in the vlan-tagged configuration
+ srManager.getTaggedVlanId(cp).contains(vlanId) ||
+ // Given vlanId is INTERNAL_VLAN and the interface is not configured
+ (srManager.getTaggedVlanId(cp).isEmpty() && srManager.getInternalVlanId(cp) == null &&
+ vlanId.equals(INTERNAL_VLAN)) ||
+ // interface is configured and either vlan-untagged or vlan-native matches given vlanId
+ (srManager.getInternalVlanId(cp) != null && srManager.getInternalVlanId(cp).equals(vlanId))
+ );
+ }
}