Avoid programming TMAC entries for BSOD vlans

When an interfaces is defined with tagged VLAN(s) and no IP addresses, do not install TMAC entries for that VLAN(s).

Change-Id: I5beeb38c0b21cdd69a0da90943f768c3aeddb720
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 64fe2fc..90da4b4 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
@@ -998,7 +998,23 @@
 
     private boolean processSinglePortFiltersInternal(DeviceId deviceId, PortNumber portnum,
                                                       boolean pushVlan, VlanId vlanId, boolean install) {
-        FilteringObjective.Builder fob = buildFilteringObjective(deviceId, portnum, pushVlan, vlanId);
+        boolean doTMAC = true;
+
+        if (!pushVlan) {
+            // Skip the tagged vlans belonging to an interface without an IP address
+            Set<Interface> ifaces = srManager.interfaceService
+                    .getInterfacesByPort(new ConnectPoint(deviceId, portnum))
+                    .stream()
+                    .filter(intf -> intf.vlanTagged().contains(vlanId) && intf.ipAddressesList().isEmpty())
+                    .collect(Collectors.toSet());
+            if (!ifaces.isEmpty()) {
+                log.debug("processSinglePortFiltersInternal: skipping TMAC for vlan {} at {}/{} - no IP",
+                          vlanId, deviceId, portnum);
+                doTMAC = false;
+            }
+        }
+
+        FilteringObjective.Builder fob = buildFilteringObjective(deviceId, portnum, pushVlan, vlanId, doTMAC);
         if (fob == null) {
             // error encountered during build
             return false;
@@ -1019,7 +1035,7 @@
     }
 
     private FilteringObjective.Builder buildFilteringObjective(DeviceId deviceId, PortNumber portnum,
-                                                               boolean pushVlan, VlanId vlanId) {
+                                                               boolean pushVlan, VlanId vlanId, boolean doTMAC) {
         MacAddress deviceMac;
         try {
             deviceMac = config.getDeviceMac(deviceId);
@@ -1028,9 +1044,15 @@
             return null;
         }
         FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
-        fob.withKey(Criteria.matchInPort(portnum))
-            .addCondition(Criteria.matchEthDst(deviceMac))
-            .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
+
+        if (doTMAC) {
+            fob.withKey(Criteria.matchInPort(portnum))
+                    .addCondition(Criteria.matchEthDst(deviceMac))
+                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
+        } else {
+            fob.withKey(Criteria.matchInPort(portnum))
+                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
+        }
 
         TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
 
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
index d834b48..f53610a 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
@@ -511,7 +511,7 @@
 
         if (ethCriterion == null || ethCriterion.mac().equals(NONE)) {
             // NOTE: it is possible that a filtering objective only has vidCriterion
-            log.warn("filtering objective missing dstMac, cannot program TMAC table");
+            log.debug("filtering objective missing dstMac, won't program TMAC table");
         } else {
             MacAddress unicastMac = readEthDstFromTreatment(filt.meta());
             List<List<FlowRule>> allStages = processEthDstFilter(portCriterion, ethCriterion,