[CORD-2811] Fix VLAN cases in Mcast

Change-Id: I0b051a4502e48b4278723a1b782f49e0d6a2dffa
(cherry picked from commit 3cc7e66059ac9be3cdfbd266563690ec53badc9b)
diff --git a/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java b/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
index b323c17..d35d253 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
@@ -94,6 +94,9 @@
 import static org.onosproject.net.mcast.McastEvent.Type.SOURCE_ADDED;
 import static org.onosproject.net.mcast.McastEvent.Type.SOURCE_UPDATED;
 import static org.onosproject.segmentrouting.SegmentRoutingManager.INTERNAL_VLAN;
+import static org.onosproject.segmentrouting.mcast.McastRole.EGRESS;
+import static org.onosproject.segmentrouting.mcast.McastRole.INGRESS;
+import static org.onosproject.segmentrouting.mcast.McastRole.TRANSIT;
 
 /**
  * Handles Multicast related events.
@@ -355,10 +358,10 @@
                                                                   mcastIp, assignedVlan(newSource)));
             }
             addFilterToDevice(newSource.deviceId(), newSource.port(),
-                              assignedVlan(newSource), mcastIp);
+                              assignedVlan(newSource), mcastIp, INGRESS);
             // Setup mcast roles
             mcastRoleStore.put(new McastStoreKey(mcastIp, newSource.deviceId()),
-                               McastRole.INGRESS);
+                               INGRESS);
         } finally {
             mcastUnlock();
         }
@@ -376,11 +379,11 @@
             log.debug("Processing route removed for group {}", mcastIp);
 
             // Find out the ingress, transit and egress device of the affected group
-            DeviceId ingressDevice = getDevice(mcastIp, McastRole.INGRESS)
+            DeviceId ingressDevice = getDevice(mcastIp, INGRESS)
                     .stream().findAny().orElse(null);
-            DeviceId transitDevice = getDevice(mcastIp, McastRole.TRANSIT)
+            DeviceId transitDevice = getDevice(mcastIp, TRANSIT)
                     .stream().findAny().orElse(null);
-            Set<DeviceId> egressDevices = getDevice(mcastIp, McastRole.EGRESS);
+            Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS);
 
             // Verify leadership on the operation
             if (!isLeader(source)) {
@@ -491,7 +494,8 @@
             }
 
             // Process the ingress device
-            addFilterToDevice(source.deviceId(), source.port(), assignedVlan(source), mcastIp);
+            addFilterToDevice(source.deviceId(), source.port(),
+                              assignedVlan(source), mcastIp, INGRESS);
 
             // When source and sink are on the same device
             if (source.deviceId().equals(sink.deviceId())) {
@@ -502,7 +506,7 @@
                     return;
                 }
                 addPortToDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan(source));
-                mcastRoleStore.put(new McastStoreKey(mcastIp, sink.deviceId()), McastRole.INGRESS);
+                mcastRoleStore.put(new McastStoreKey(mcastIp, sink.deviceId()), INGRESS);
                 return;
             }
 
@@ -516,7 +520,8 @@
                 links.forEach(link -> {
                     addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp,
                                     assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
-                    addFilterToDevice(link.dst().deviceId(), link.dst().port(), assignedVlan(null), mcastIp);
+                    addFilterToDevice(link.dst().deviceId(), link.dst().port(),
+                                      assignedVlan(null), mcastIp, null);
                 });
 
                 // Process the egress device
@@ -524,11 +529,11 @@
 
                 // Setup mcast roles
                 mcastRoleStore.put(new McastStoreKey(mcastIp, source.deviceId()),
-                                   McastRole.INGRESS);
+                                   INGRESS);
                 mcastRoleStore.put(new McastStoreKey(mcastIp, links.get(0).dst().deviceId()),
-                                   McastRole.TRANSIT);
+                                   TRANSIT);
                 mcastRoleStore.put(new McastStoreKey(mcastIp, sink.deviceId()),
-                                   McastRole.EGRESS);
+                                   EGRESS);
             } else {
                 log.warn("Unable to find a path from {} to {}. Abort sinkAdded",
                          source.deviceId(), sink.deviceId());
@@ -554,11 +559,11 @@
                           affectedLink, mcastIp);
 
                 // Find out the ingress, transit and egress device of affected group
-                DeviceId ingressDevice = getDevice(mcastIp, McastRole.INGRESS)
+                DeviceId ingressDevice = getDevice(mcastIp, INGRESS)
                         .stream().findAny().orElse(null);
-                DeviceId transitDevice = getDevice(mcastIp, McastRole.TRANSIT)
+                DeviceId transitDevice = getDevice(mcastIp, TRANSIT)
                         .stream().findAny().orElse(null);
-                Set<DeviceId> egressDevices = getDevice(mcastIp, McastRole.EGRESS);
+                Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS);
                 ConnectPoint source = getSource(mcastIp);
 
                 // Do not proceed if any of these info is missing
@@ -622,11 +627,11 @@
                           deviceDown, mcastIp);
 
                 // Find out the ingress, transit and egress device of affected group
-                DeviceId ingressDevice = getDevice(mcastIp, McastRole.INGRESS)
+                DeviceId ingressDevice = getDevice(mcastIp, INGRESS)
                         .stream().findAny().orElse(null);
-                DeviceId transitDevice = getDevice(mcastIp, McastRole.TRANSIT)
+                DeviceId transitDevice = getDevice(mcastIp, TRANSIT)
                         .stream().findAny().orElse(null);
-                Set<DeviceId> egressDevices = getDevice(mcastIp, McastRole.EGRESS);
+                Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS);
                 ConnectPoint source = getSource(mcastIp);
 
                 // Do not proceed if ingress device or source of this group are missing
@@ -714,7 +719,8 @@
      * @param port ingress port number
      * @param assignedVlan assigned VLAN ID
      */
-    private void addFilterToDevice(DeviceId deviceId, PortNumber port, VlanId assignedVlan, IpAddress mcastIp) {
+    private void addFilterToDevice(DeviceId deviceId, PortNumber port,
+                                   VlanId assignedVlan, IpAddress mcastIp, McastRole mcastRole) {
         // Do nothing if the port is configured as suppressed
         ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
         SegmentRoutingAppConfig appConfig = srManager.cfgService
@@ -733,7 +739,7 @@
         }
 
         FilteringObjective.Builder filtObjBuilder =
-                filterObjBuilder(port, assignedVlan, mcastIp, routerMac);
+                filterObjBuilder(port, assignedVlan, mcastIp, routerMac, mcastRole);
         ObjectiveContext context = new DefaultObjectiveContext(
                 (objective) -> log.debug("Successfully add filter on {}/{}, vlan {}",
                         deviceId, port.toLong(), assignedVlan),
@@ -909,15 +915,15 @@
         links.forEach(link -> {
             addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp,
                             assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
-            addFilterToDevice(link.dst().deviceId(), link.dst().port(), assignedVlan(null),
-                              mcastIp);
+            addFilterToDevice(link.dst().deviceId(), link.dst().port(),
+                              assignedVlan(null), mcastIp, null);
         });
         // Setup new transit mcast role
         mcastRoleStore.put(new McastStoreKey(mcastIp, links.get(0).dst().deviceId()),
-                           McastRole.TRANSIT);
+                           TRANSIT);
         // Setup new ingress mcast role
         mcastRoleStore.put(new McastStoreKey(mcastIp, links.get(0).src().deviceId()),
-                           McastRole.INGRESS);
+                           INGRESS);
     }
 
     /**
@@ -1003,28 +1009,33 @@
      * @return filtering objective builder
      */
     private FilteringObjective.Builder filterObjBuilder(PortNumber ingressPort,
-            VlanId assignedVlan, IpAddress mcastIp, MacAddress routerMac) {
+            VlanId assignedVlan, IpAddress mcastIp, MacAddress routerMac, McastRole mcastRole) {
         FilteringObjective.Builder filtBuilder = DefaultFilteringObjective.builder();
-
-        if (mcastIp.isIp4()) {
-            filtBuilder.withKey(Criteria.matchInPort(ingressPort))
-            .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST,
-                    MacAddress.IPV4_MULTICAST_MASK))
-            .addCondition(Criteria.matchVlanId(egressVlan()))
-            .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
+        // Let's add the in port matching and the priority
+        filtBuilder.withKey(Criteria.matchInPort(ingressPort))
+                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
+        // According to the mcast role we match on the proper vlan
+        // If the role is null we are on the transit or on the egress
+        if (mcastRole == null) {
+            filtBuilder.addCondition(Criteria.matchVlanId(egressVlan()));
         } else {
-            filtBuilder.withKey(Criteria.matchInPort(ingressPort))
-            .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV6_MULTICAST,
-                     MacAddress.IPV6_MULTICAST_MASK))
-            .addCondition(Criteria.matchVlanId(egressVlan()))
-            .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
+            filtBuilder.addCondition(Criteria.matchVlanId(ingressVlan()));
         }
+        // According to the IP type we set the proper match on the mac address
+        if (mcastIp.isIp4()) {
+            filtBuilder.addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST,
+                    MacAddress.IPV4_MULTICAST_MASK));
+        } else {
+            filtBuilder.addCondition(Criteria.matchEthDstMasked(MacAddress.IPV6_MULTICAST,
+                     MacAddress.IPV6_MULTICAST_MASK));
+        }
+        // We finally build the meta treatment
         TrafficTreatment tt = DefaultTrafficTreatment.builder()
                 .pushVlan().setVlanId(assignedVlan)
                 .setEthDst(routerMac)
                 .build();
         filtBuilder.withMeta(tt);
-
+        // Done, we return a permit filtering objective
         return filtBuilder.permit().fromApp(srManager.appId());
     }
 
@@ -1238,6 +1249,17 @@
     }
 
     /**
+     * Gets ingress VLAN from McastConfig.
+     *
+     * @return ingress VLAN or VlanId.NONE if not configured
+     */
+    private VlanId ingressVlan() {
+        McastConfig mcastConfig =
+                srManager.cfgService.getConfig(coreAppId, McastConfig.class);
+        return (mcastConfig != null) ? mcastConfig.ingressVlan() : VlanId.NONE;
+    }
+
+    /**
      * Gets egress VLAN from McastConfig.
      *
      * @return egress VLAN or VlanId.NONE if not configured
@@ -1286,7 +1308,7 @@
      * @return spine-facing port on ingress device
      */
     private PortNumber ingressTransitPort(IpAddress mcastIp) {
-        DeviceId ingressDevice = getDevice(mcastIp, McastRole.INGRESS)
+        DeviceId ingressDevice = getDevice(mcastIp, INGRESS)
                 .stream().findAny().orElse(null);
         if (ingressDevice != null) {
             NextObjective nextObj = mcastNextObjStore
@@ -1347,7 +1369,8 @@
      * @param assignedVlan assigned VLAN ID
      * @param mcastIp multicast IP address
      */
-    private void removeFilterToDevice(DeviceId deviceId, PortNumber port, VlanId assignedVlan, IpAddress mcastIp) {
+    private void removeFilterToDevice(DeviceId deviceId, PortNumber port,
+                                      VlanId assignedVlan, IpAddress mcastIp, McastRole mcastRole) {
         // Do nothing if the port is configured as suppressed
         ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
         SegmentRoutingAppConfig appConfig = srManager.cfgService
@@ -1366,7 +1389,7 @@
         }
 
         FilteringObjective.Builder filtObjBuilder =
-                filterObjBuilder(port, assignedVlan, mcastIp, routerMac);
+                filterObjBuilder(port, assignedVlan, mcastIp, routerMac, mcastRole);
         ObjectiveContext context = new DefaultObjectiveContext(
                 (objective) -> log.debug("Successfully removed filter on {}/{}, vlan {}",
                                          deviceId, port.toLong(), assignedVlan),
@@ -1397,9 +1420,9 @@
                 ConnectPoint source = srManager.multicastRouteService.fetchSource(mcastRoute);
                 if (source.deviceId().equals(deviceId) && source.port().equals(portNum)) {
                     if (install) {
-                        addFilterToDevice(deviceId, portNum, vlanId, mcastRoute.group());
+                        addFilterToDevice(deviceId, portNum, vlanId, mcastRoute.group(), INGRESS);
                     } else {
-                        removeFilterToDevice(deviceId, portNum, vlanId, mcastRoute.group());
+                        removeFilterToDevice(deviceId, portNum, vlanId, mcastRoute.group(), null);
                     }
                 }
             });
@@ -1455,11 +1478,11 @@
 
                         // For each group we get current information in the store
                         // and issue a check of the next objectives in place
-                        DeviceId ingressDevice = getDevice(mcastIp, McastRole.INGRESS)
+                        DeviceId ingressDevice = getDevice(mcastIp, INGRESS)
                                 .stream().findAny().orElse(null);
-                        DeviceId transitDevice = getDevice(mcastIp, McastRole.TRANSIT)
+                        DeviceId transitDevice = getDevice(mcastIp, TRANSIT)
                                 .stream().findAny().orElse(null);
-                        Set<DeviceId> egressDevices = getDevice(mcastIp, McastRole.EGRESS);
+                        Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS);
                         // Get source and sinks from Mcast Route Service and warn about errors
                         ConnectPoint source = getSource(mcastIp);
                         Set<ConnectPoint> sinks = getSinks(mcastIp);