VOL-2734 Adding inner vlan id field to McastConfig to configure inner vlan id
value for double-tagged multicast flows. The full path of the task:
https://jira.opencord.org/browse/VOL-2734

Change-Id: I45dcd26fd91fba81184e4bf59640f6e43da535cc
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/McastConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/McastConfig.java
index 3d96bee..17a78b6 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/McastConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/McastConfig.java
@@ -28,11 +28,12 @@
 public class McastConfig extends Config<ApplicationId> {
     private static final String INGRESS_VLAN = "ingressVlan";
     private static final String EGRESS_VLAN = "egressVlan";
+    private static final String EGRESS_INNER_VLAN = "egressInnerVlan";
 
     @Override
     public boolean isValid() {
-        return hasOnlyFields(INGRESS_VLAN, EGRESS_VLAN) &&
-                ingressVlan() != null && egressVlan() != null;
+        return hasOnlyFields(INGRESS_VLAN, EGRESS_VLAN, EGRESS_INNER_VLAN) &&
+                ingressVlan() != null && egressVlan() != null && egressInnerVlan() != null;
     }
 
     /**
@@ -98,4 +99,36 @@
         }
         return this;
     }
+
+    /**
+     * Gets egress inner VLAN of multicast traffic.
+     *
+     * @return Egress inner VLAN ID
+     */
+    public VlanId egressInnerVlan() {
+        if (!object.has(EGRESS_INNER_VLAN)) {
+            return VlanId.NONE;
+        }
+
+        try {
+            return VlanId.vlanId(object.path(EGRESS_INNER_VLAN).asText());
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Sets egress inner VLAN of multicast traffic.
+     *
+     * @param vlanId Egress inner VLAN ID
+     * @return this {@link McastConfig}
+     */
+    public McastConfig setEgressInnerVlan(VlanId vlanId) {
+        if (vlanId == null) {
+            object.remove(EGRESS_INNER_VLAN);
+        } else {
+            object.put(EGRESS_INNER_VLAN, vlanId.toString());
+        }
+        return this;
+    }
 }
diff --git a/core/api/src/test/java/org/onosproject/net/config/basics/McastConfigTest.java b/core/api/src/test/java/org/onosproject/net/config/basics/McastConfigTest.java
index 03536cd..c53037d 100644
--- a/core/api/src/test/java/org/onosproject/net/config/basics/McastConfigTest.java
+++ b/core/api/src/test/java/org/onosproject/net/config/basics/McastConfigTest.java
@@ -45,11 +45,15 @@
             new TestApplicationId(CoreService.CORE_APP_NAME);
     private McastConfig config;
     private McastConfig invalidConfig;
+    private McastConfig configForInnerVlan;
+    private McastConfig invalidConfigForInnerVlan;
 
     private static final VlanId INGRESS_VLAN_1 = VlanId.NONE;
     private static final VlanId EGRESS_VLAN_1 = VlanId.NONE;
+    private static final VlanId EGRESS_INNER_VLAN_1 = VlanId.NONE;
     private static final VlanId INGRESS_VLAN_2 = VlanId.vlanId((short) 100);
     private static final VlanId EGRESS_VLAN_2 = VlanId.vlanId((short) 100);
+    private static final VlanId EGRESS_INNER_VLAN_2 = VlanId.vlanId((short) 100);
 
     /**
      * Initialize test related variables.
@@ -62,18 +66,28 @@
                 .getResourceAsStream("/mcast-config.json");
         InputStream invalidJsonStream = McastConfigTest.class
                 .getResourceAsStream("/mcast-config-invalid.json");
+        InputStream jsonStreamForInnerVlan = McastConfigTest.class
+                .getResourceAsStream("/mcast-config-inner.json");
+        InputStream invalidJsonStreamForInnerVlan = McastConfigTest.class
+                .getResourceAsStream("/mcast-config-invalid-inner.json");
 
         ApplicationId subject = APP_ID;
         String key = CoreService.CORE_APP_NAME;
         ObjectMapper mapper = new ObjectMapper();
         JsonNode jsonNode = mapper.readTree(jsonStream);
         JsonNode invalidJsonNode = mapper.readTree(invalidJsonStream);
+        JsonNode jsonNodeForInnerVlan = mapper.readTree(jsonStreamForInnerVlan);
+        JsonNode invalidJsonNodeForInnerVlan = mapper.readTree(invalidJsonStreamForInnerVlan);
         ConfigApplyDelegate delegate = new MockDelegate();
 
         config = new McastConfig();
         config.init(subject, key, jsonNode, mapper, delegate);
         invalidConfig = new McastConfig();
         invalidConfig.init(subject, key, invalidJsonNode, mapper, delegate);
+        configForInnerVlan = new McastConfig();
+        configForInnerVlan.init(subject, key, jsonNodeForInnerVlan, mapper, delegate);
+        invalidConfigForInnerVlan = new McastConfig();
+        invalidConfigForInnerVlan.init(subject, key, invalidJsonNodeForInnerVlan, mapper, delegate);
     }
 
     /**
@@ -85,6 +99,8 @@
     public void isValid() throws Exception {
         assertTrue(config.isValid());
         assertFalse(invalidConfig.isValid());
+        assertTrue(configForInnerVlan.isValid());
+        assertFalse(invalidConfigForInnerVlan.isValid());
     }
 
     /**
@@ -139,6 +155,33 @@
         assertThat(egressVlan, is(EGRESS_VLAN_2));
     }
 
+    /**
+     * Tests egress inner VLAN getter.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void egressInnerVlan() {
+        VlanId egressInnerVlan = config.egressInnerVlan();
+        assertNotNull("egressInnerVlan should not be null", egressInnerVlan);
+        assertThat(egressInnerVlan, is(EGRESS_INNER_VLAN_1));
+    }
+
+
+    /**
+     * Tests egress inner VLAN setter.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void setEgressInnerVlan() {
+        config.setEgressInnerVlan(EGRESS_INNER_VLAN_2);
+
+        VlanId egressInnerVlan = config.egressInnerVlan();
+        assertNotNull("egressInnerVlan should not be null", egressInnerVlan);
+        assertThat(egressInnerVlan, is(EGRESS_INNER_VLAN_2));
+    }
+
     private class MockDelegate implements ConfigApplyDelegate {
         @Override
         public void onApply(Config config) {
diff --git a/core/api/src/test/resources/mcast-config-inner.json b/core/api/src/test/resources/mcast-config-inner.json
new file mode 100644
index 0000000..cfeeaae
--- /dev/null
+++ b/core/api/src/test/resources/mcast-config-inner.json
@@ -0,0 +1,3 @@
+{
+  "egressInnerVlan" : "None"
+}
\ No newline at end of file
diff --git a/core/api/src/test/resources/mcast-config-invalid-inner.json b/core/api/src/test/resources/mcast-config-invalid-inner.json
new file mode 100644
index 0000000..e3be43f
--- /dev/null
+++ b/core/api/src/test/resources/mcast-config-invalid-inner.json
@@ -0,0 +1,3 @@
+{
+  "egressInnerVlan" : "5000"
+}
\ No newline at end of file