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))
+        );
+    }
 }