[CORD-1895] Incorrect VLAN DHCPV6 message to client

Change-Id: I462ec928f3ded6247c9d9699f0cdf3bf3c842eba
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
index c9ffe9b..1bf33b4 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
@@ -630,11 +630,11 @@
      * @param dhcp6Packet the dhcp6 payload
      * @param clientPacket client's ethernet packet
      * @param clientIpv6 client's Ipv6 packet
-     * @param clientInterfaces set of client interfaces
+     * @param clientInterface client interfaces
      */
     private void removeHostOrRoute(boolean directConnFlag, DHCP6 dhcp6Packet,
                                    Ethernet clientPacket, IPv6 clientIpv6,
-                                   Set<Interface> clientInterfaces) {
+                                   Interface clientInterface) {
         log.debug("extractPrefix  enters {}", dhcp6Packet);
         // add host or route
         if (isDhcp6Release(dhcp6Packet)) {
@@ -643,7 +643,7 @@
                 // Add to host store if it is connected to network directly
                 ip = extractIpAddress(dhcp6Packet);
                 if (ip != null) {
-                    VlanId vlanId = clientInterfaces.iterator().next().vlan();
+                    VlanId vlanId = clientInterface.vlan();
                     MacAddress clientMac = clientPacket.getSourceMAC();
                     HostId hostId = HostId.hostId(clientMac, vlanId);
                     log.debug("remove Host {} ip for directly connected.", hostId.toString());
@@ -693,12 +693,12 @@
      * @param dhcp6Relay the dhcp6 payload
      * @param embeddedDhcp6 client's ethernet packetthe dhcp6 payload within relay
      * @param clientMac client macAddress
-     * @param clientInterfaces set of client interfaces
+     * @param clientInterface client interface
      */
     private void addHostOrRoute(boolean directConnFlag, DHCP6 dhcp6Relay,
                                    DHCP6 embeddedDhcp6,
                                    MacAddress clientMac,
-                                   Set<Interface> clientInterfaces) {
+                                   Interface clientInterface) {
         log.debug("addHostOrRoute entered.");
         // add host or route
         if (isDhcp6Reply(dhcp6Relay)) {
@@ -710,10 +710,10 @@
                     Set<IpAddress> ips = Sets.newHashSet(ip);
 
                     // FIXME: we should use vlan id from original packet (solicit, request)
-                    VlanId vlanId = clientInterfaces.iterator().next().vlan();
+                    VlanId vlanId = clientInterface.vlan();
                     HostId hostId = HostId.hostId(clientMac, vlanId);
                     Host host = hostService.getHost(hostId);
-                    HostLocation hostLocation = new HostLocation(clientInterfaces.iterator().next().connectPoint(),
+                    HostLocation hostLocation = new HostLocation(clientInterface.connectPoint(),
                                                                  System.currentTimeMillis());
                     Set<HostLocation> hostLocations = Sets.newHashSet(hostLocation);
 
@@ -809,14 +809,13 @@
             return null;
         }
 
-        etherReply.setDestinationMACAddress(directConnFlag ? this.dhcpConnectMac : this.indirectDhcpConnectMac);
-        etherReply.setVlanID(directConnFlag ? this.dhcpConnectVlan.toShort() : this.indirectDhcpConnectVlan.toShort());
+        etherReply.setDestinationMACAddress(this.dhcpConnectMac);
+        etherReply.setVlanID(this.dhcpConnectVlan.toShort());
 
         IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
         byte[] peerAddress = clientIpv6.getSourceAddress();
         ipv6Packet.setSourceAddress(relayAgentIp.toOctets());
-        ipv6Packet.setDestinationAddress(directConnFlag ? this.dhcpServerIp.toOctets() :
-                                                          this.indirectDhcpServerIp.toOctets());
+        ipv6Packet.setDestinationAddress(this.dhcpServerIp.toOctets());
 
         UDP udpPacket = (UDP) ipv6Packet.getPayload();
         udpPacket.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
@@ -825,8 +824,15 @@
 
         // notify onos and quagga to release PD
         //releasePD(dhcp6Packet);
+        ConnectPoint clientConnectionPoint = context.inPacket().receivedFrom();
+        VlanId vlanIdInUse = VlanId.vlanId(clientPacket.getVlanID());
+        Interface clientInterface = interfaceService.getInterfacesByPort(clientConnectionPoint)
+                 .stream()
+                 .filter(iface -> interfaceContainsVlan(iface, vlanIdInUse))
+                 .findFirst()
+                 .orElse(null);
 
-        removeHostOrRoute(directConnFlag, dhcp6Packet, clientPacket, clientIpv6, clientInterfaces);
+        removeHostOrRoute(directConnFlag, dhcp6Packet, clientPacket, clientIpv6, clientInterface);
 
         DHCP6 dhcp6Relay = new DHCP6();
         dhcp6Relay.setMsgType(DHCP6.MsgType.RELAY_FORW.value());
@@ -857,10 +863,9 @@
                  ipv6Packet.setDestinationAddress(this.indirectDhcpServerIp.toOctets());
 
              }
-
              if (this.indirectRelayAgentIpFromCfg == null) {
                  dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
-                 log.warn("indirect connection: relayAgentIp NOT availale from config file! {}",
+                 log.warn("indirect connection: relayAgentIp NOT availale from config file! Use dynamic. {}",
                          HexString.toHexString(relayAgentIp.toOctets(), ":"));
 
              } else {
@@ -891,17 +896,24 @@
         options.add(relayMessage);
 
         // create interfaceId option
-        String inPortString = "-" + context.inPacket().receivedFrom().toString();
+        String inPortString = "-" + context.inPacket().receivedFrom().toString() + ":";
         Dhcp6Option interfaceId = new Dhcp6Option();
         interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
         byte[] clientSoureMacBytes = clientPacket.getSourceMACAddress();
         byte[] inPortStringBytes = inPortString.getBytes();
-        byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +  inPortStringBytes.length];
-        log.debug("Length: interfaceIdBytes  {} clientSoureMacBytes {} inPortStringBytes {} ",
-                interfaceIdBytes.length, clientSoureMacBytes.length, inPortStringBytes.length);
+        byte[] vlanIdBytes = new byte[2];
+        vlanIdBytes[0] = (byte) (clientPacket.getVlanID() & 0xff);
+        vlanIdBytes[1] = (byte) ((clientPacket.getVlanID() >> 8) & 0xff);
+        byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +
+                                           inPortStringBytes.length + vlanIdBytes.length];
+        log.debug("Length: interfaceIdBytes  {} clientSoureMacBytes {} inPortStringBytes {} vlan {}",
+                interfaceIdBytes.length, clientSoureMacBytes.length, inPortStringBytes.length,
+                vlanIdBytes.length);
 
         System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
         System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length, inPortStringBytes.length);
+        System.arraycopy(vlanIdBytes, 0, interfaceIdBytes, clientSoureMacBytes.length + inPortStringBytes.length,
+                vlanIdBytes.length);
 
         interfaceId.setData(interfaceIdBytes);
         interfaceId.setLength((short) interfaceIdBytes.length);
@@ -977,13 +989,17 @@
         String clientConnectionPointStr = new String(interfaceIdOption.getInPort());
 
         ConnectPoint clientConnectionPoint = ConnectPoint.deviceConnectPoint(clientConnectionPointStr);
-
-        Set<Interface> clientInterfaces = interfaceService.getInterfacesByPort(clientConnectionPoint);
-        if (clientInterfaces.isEmpty()) {
-            log.warn("Can not get client interface from packet, abort..");
+        VlanId vlanIdInUse = VlanId.vlanId(interfaceIdOption.getVlanId());
+        Interface clientInterface = interfaceService.getInterfacesByPort(clientConnectionPoint)
+                .stream()
+                .filter(iface -> interfaceContainsVlan(iface, vlanIdInUse))
+                .findFirst()
+                .orElse(null);
+        if (clientInterface == null) {
+            log.warn("Cannot get client interface for from packet, abort... vlan {}", vlanIdInUse.toString());
             return null;
         }
-        MacAddress relayAgentMac = clientInterfaces.iterator().next().mac();
+        MacAddress relayAgentMac = clientInterface.mac();
         if (relayAgentMac == null) {
             log.warn("Can not get interface mac, abort packet..");
             return null;
@@ -1030,7 +1046,7 @@
 
 
         // add host or route
-        addHostOrRoute(directConnFlag, dhcp6Relay, embeddedDhcp6, clientMac, clientInterfaces);
+        addHostOrRoute(directConnFlag, dhcp6Relay, embeddedDhcp6, clientMac, clientInterface);
 
         udpPacket.setPayload(embeddedDhcp6);
         udpPacket.resetChecksum();
@@ -1299,4 +1315,21 @@
             }
         }
     }
+    /**
+     * Determind if an Interface contains a vlan id.
+     *
+     * @param iface the Interface
+     * @param vlanId the vlan id
+     * @return true if the Interface contains the vlan id
+     */
+    private boolean interfaceContainsVlan(Interface iface, VlanId vlanId) {
+        if (vlanId.equals(VlanId.NONE)) {
+            // untagged packet, check if vlan untagged or vlan native is not NONE
+            return !iface.vlanUntagged().equals(VlanId.NONE) ||
+                    !iface.vlanNative().equals(VlanId.NONE);
+        }
+        // tagged packet, check if the interface contains the vlan
+        return iface.vlanTagged().contains(vlanId);
+    }
+
 }
diff --git a/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/DhcpRelayManagerTest.java b/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/DhcpRelayManagerTest.java
index 6011d11..883bf2f 100644
--- a/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/DhcpRelayManagerTest.java
+++ b/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/DhcpRelayManagerTest.java
@@ -174,6 +174,8 @@
                                                                        CLIENT2_IFACE_MAC,
                                                                        CLIENT2_VLAN,
                                                                        CLIENT2_VLAN_NATIVE);
+    private static final VlanId CLIENT_BOGUS_VLAN = VlanId.vlanId("108");
+
 
     // Outer relay information
     private static final Ip4Address OUTER_RELAY_IP = Ip4Address.valueOf("10.0.5.253");
@@ -599,8 +601,9 @@
     public void relayDhcp6WithoutAgentInfo() {
         replay(mockHostProviderService);
         // send request
-        packetService.processPacket(new TestDhcp6RequestPacketContext(CLIENT_MAC,
-                                                                     VlanId.NONE,
+        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
+                                                                     CLIENT_MAC,
+                                                                     CLIENT_VLAN,
                                                                      CLIENT_CP,
                                                                      INTERFACE_IP_V6.ipAddress().getIp6Address(),
                                                                      0));
@@ -614,7 +617,8 @@
                                              capture(capturedHostDesc), eq(false));
         replay(mockHostProviderService);
         // send reply
-        packetService.processPacket(new TestDhcp6ReplyPacketContext(CLIENT_CP, CLIENT_MAC,
+        packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
+                                                                    CLIENT_CP, CLIENT_MAC,
                                                                     CLIENT_VLAN,
                                                                     INTERFACE_IP_V6.ipAddress().getIp6Address(),
                                                                     0));
@@ -627,6 +631,16 @@
         assertEquals(CLIENT_CP.port(), host.location().port());
         assertEquals(1, host.ipAddress().size());
         assertEquals(IP_FOR_CLIENT_V6, host.ipAddress().iterator().next());
+
+        // send release
+        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.RELEASE.value(),
+                CLIENT_MAC,
+                CLIENT_VLAN,
+                CLIENT_CP,
+                INTERFACE_IP_V6.ipAddress().getIp6Address(),
+                0));
+
+        assertEquals(null, manager.hostService.getHost(HostId.hostId(CLIENT_MAC, CLIENT_VLAN)));
     }
 
     /**
@@ -637,7 +651,74 @@
         replay(mockHostProviderService);
         // Assume outer dhcp6 relay agent exists in store already
         // send request
-        packetService.processPacket(new TestDhcp6RequestPacketContext(CLIENT2_MAC,
+        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
+                CLIENT2_MAC,
+                CLIENT2_VLAN,
+                CLIENT2_CP,
+                OUTER_RELAY_IP_V6,
+                1));
+
+        assertEquals(0, mockRouteStore.routes.size());
+
+        // send reply
+        packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(), CLIENT2_CP,
+                CLIENT2_MAC,
+                CLIENT2_VLAN,
+                OUTER_RELAY_IP_V6,
+                1));
+
+        // won't trigger the host provider service
+        verify(mockHostProviderService);
+        reset(mockHostProviderService);
+        assertEquals(2, mockRouteStore.routes.size()); // ipAddress and prefix
+
+        Route aRoute = mockRouteStore.routes.stream()
+                             .filter(rt -> rt.prefix().contains(IP_FOR_CLIENT_V6))
+                             .findFirst()
+                             .orElse(null);
+        assertNotEquals(null, aRoute);
+
+        aRoute = mockRouteStore.routes.stream()
+                .filter(rt -> rt.prefix().contains(PREFIX_FOR_CLIENT_V6))
+                .findFirst()
+                .orElse(null);
+        assertNotEquals(null, aRoute);
+
+        // send release msg
+        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.RELEASE.value(),
+                CLIENT2_MAC,
+                CLIENT2_VLAN,
+                CLIENT2_CP,
+                OUTER_RELAY_IP_V6,
+                1));
+
+        aRoute = mockRouteStore.routes.stream()
+                .filter(rt -> rt.prefix().contains(IP_FOR_CLIENT_V6))
+                .findFirst()
+                .orElse(null);
+        assertEquals(null, aRoute);
+
+        aRoute = mockRouteStore.routes.stream()
+                .filter(rt -> rt.prefix().contains(PREFIX_FOR_CLIENT_V6))
+                .findFirst()
+                .orElse(null);
+        assertEquals(null, aRoute);
+
+        assertEquals(0, mockRouteStore.routes.size());
+
+    }
+
+    /**
+     * Relay a DHCP6 packet with Relay Message opion (Indirectly connected host) and server responded
+     * with vlan differnt from client interface vlan.
+     */
+    @Test
+    public void relayDhcp6WithAgentInfoWrongVlan() {
+        replay(mockHostProviderService);
+        // Assume outer dhcp6 relay agent exists in store already
+        // send request
+        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
+                CLIENT2_MAC,
                 CLIENT2_VLAN,
                 CLIENT2_CP,
                 INTERFACE_IP_V6.ipAddress().getIp6Address(),
@@ -646,23 +727,21 @@
         assertEquals(0, mockRouteStore.routes.size());
 
         // send reply
-        packetService.processPacket(new TestDhcp6ReplyPacketContext(CLIENT2_CP,
+        packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
+                CLIENT2_CP,
                 CLIENT2_MAC,
-                CLIENT2_VLAN,
+                CLIENT_BOGUS_VLAN,  // mismatch
                 INTERFACE_IP_V6.ipAddress().getIp6Address(),
                 1));
 
         // won't trigger the host provider service
         verify(mockHostProviderService);
         reset(mockHostProviderService);
-        assertEquals(2, mockRouteStore.routes.size()); // ipAddress and prefix
+        assertEquals(0, mockRouteStore.routes.size()); // ipAddress and prefix
 
-        Route route = mockRouteStore.routes.get(0);
-        assertEquals(OUTER_RELAY_IP_V6, route.nextHop());
-        assertEquals(IP_FOR_CLIENT_V6.toIpPrefix(), route.prefix());
-        assertEquals(Route.Source.STATIC, route.source());
     }
 
+
     @Test
     public void testDhcp4DualHome() {
         PacketContext packetContext =
@@ -687,7 +766,8 @@
     @Test
     public void testDhcp6DualHome() {
         PacketContext packetContext =
-                new TestDhcp6ReplyPacketContext(CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
+                new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
+                                                CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
                                                 INTERFACE_IP_V6.ipAddress().getIp6Address(),
                                                 0);
         reset(manager.hostService);
@@ -794,6 +874,11 @@
         public void updateRoute(Route route) {
             routes.add(route);
         }
+
+        @Override
+        public void removeRoute(Route route) {
+            routes.remove(route);
+        }
     }
 
     private class MockInterfaceService extends InterfaceServiceAdapter {
@@ -1166,11 +1251,15 @@
 
         byte[] macAddr = new byte[MacAddress.MAC_ADDRESS_LENGTH];
         byte[] port =  new byte[21];
+        short vlan;
         bb.get(macAddr);
         bb.get();  // separator
         bb.get(port);
+        bb.get();  // separator
+        vlan = bb.getShort();
         interfaceIdOption.setMacAddress(MacAddress.valueOf(macAddr));
         interfaceIdOption.setInPort(port);
+        interfaceIdOption.setVlanId(vlan);
 
         options.add(interfaceIdOption);
 
@@ -1186,14 +1275,19 @@
 
         dhcp6Relay.setOptions(options);
     }
-    private byte[] buildInterfaceId(MacAddress clientMac, ConnectPoint clientCp) {
-        String inPortString = "-" + clientCp.toString();
+    private byte[] buildInterfaceId(MacAddress clientMac, short vlanId, ConnectPoint clientCp) {
+        String inPortString = "-" + clientCp.toString() + ":";
         byte[] clientSoureMacBytes = clientMac.toBytes();
         byte[] inPortStringBytes = inPortString.getBytes();
-        byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +  inPortStringBytes.length];
+        byte[] vlanIdBytes = new byte[2];
+        vlanIdBytes[0] = (byte) ((vlanId >> 8) & 0xff);  // high-order byte first
+        vlanIdBytes[1] = (byte) (vlanId & 0xff);
+        byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +  inPortStringBytes.length + vlanIdBytes.length];
 
         System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
         System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length, inPortStringBytes.length);
+        System.arraycopy(vlanIdBytes, 0, interfaceIdBytes, clientSoureMacBytes.length + inPortStringBytes.length,
+                vlanIdBytes.length);
 
         return interfaceIdBytes;
     }
@@ -1204,7 +1298,7 @@
         private InboundPacket inPacket;
 
 
-        public TestDhcp6RequestPacketContext(MacAddress clientMac, VlanId vlanId,
+        public TestDhcp6RequestPacketContext(byte msgType, MacAddress clientMac, VlanId vlanId,
                                             ConnectPoint clientCp,
                                             Ip6Address clientGwAddr,
                                             int relayLevel) {
@@ -1213,14 +1307,14 @@
             DHCP6 dhcp6 = new DHCP6();
             if (relayLevel > 0) {
                 DHCP6 dhcp6Payload = new DHCP6();
-                buildDhcp6Packet(dhcp6Payload, DHCP6.MsgType.REQUEST.value(),
+                buildDhcp6Packet(dhcp6Payload, msgType,
                                  IP_FOR_CLIENT_V6,
-                                 PREFIX_FOR_ZERO);
+                        msgType == DHCP6.MsgType.REQUEST.value() ? PREFIX_FOR_ZERO : PREFIX_FOR_CLIENT_V6);
                 DHCP6 dhcp6Parent = null;
                 DHCP6 dhcp6Child = dhcp6Payload;
                 for (int i = 0; i < relayLevel; i++) {
                     dhcp6Parent = new DHCP6();
-                    byte[] interfaceId = buildInterfaceId(clientMac, clientCp);
+                    byte[] interfaceId = buildInterfaceId(clientMac, vlanId.toShort(), clientCp);
                     buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_FORW.value(),
                             INTERFACE_IP_V6.ipAddress().getIp6Address(),
                             OUTER_RELAY_IP_V6,
@@ -1232,9 +1326,9 @@
                     dhcp6 = dhcp6Parent;
                 }
             } else {
-                buildDhcp6Packet(dhcp6, DHCP6.MsgType.REQUEST.value(),
+                buildDhcp6Packet(dhcp6, msgType,
                                         IP_FOR_CLIENT_V6,
-                                        PREFIX_FOR_ZERO);
+                        msgType == DHCP6.MsgType.REQUEST.value() ? PREFIX_FOR_ZERO : PREFIX_FOR_CLIENT_V6);
             }
 
             UDP udp = new UDP();
@@ -1283,17 +1377,17 @@
     private class TestDhcp6ReplyPacketContext extends PacketContextAdapter {
         private InboundPacket inPacket;
 
-        public TestDhcp6ReplyPacketContext(ConnectPoint clientCp, MacAddress clientMac,
+        public TestDhcp6ReplyPacketContext(byte msgType, ConnectPoint clientCp, MacAddress clientMac,
                                         VlanId clientVlan, Ip6Address clientGwAddr,
                                         int relayLevel) {
             super(0, null, null, false);
 
 
             DHCP6 dhcp6Payload = new DHCP6();
-            buildDhcp6Packet(dhcp6Payload, DHCP6.MsgType.REPLY.value(),
+            buildDhcp6Packet(dhcp6Payload, msgType,
                     IP_FOR_CLIENT_V6,
                     PREFIX_FOR_CLIENT_V6);
-            byte[] interfaceId = buildInterfaceId(clientMac, clientCp);
+            byte[] interfaceId = buildInterfaceId(clientMac, clientVlan.toShort(), clientCp);
             DHCP6 dhcp6 = new DHCP6();
             buildRelayMsg(dhcp6, DHCP6.MsgType.RELAY_REPL.value(),
                           INTERFACE_IP_V6.ipAddress().getIp6Address(),
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6InterfaceIdOption.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6InterfaceIdOption.java
index abb8257..0270032 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6InterfaceIdOption.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6InterfaceIdOption.java
@@ -21,6 +21,7 @@
 import org.onlab.packet.DHCP6;
 import org.onlab.packet.Deserializer;
 import org.onlab.packet.DeserializationException;
+import org.onlab.packet.VlanId;
 
 
 import java.nio.ByteBuffer;
@@ -32,6 +33,8 @@
 public final class Dhcp6InterfaceIdOption extends Dhcp6Option {
     private MacAddress peerMacAddr;
     private byte[] inPort;
+    private short vlanId;
+
     @Override
     public short getCode() {
         return DHCP6.OptionCode.INTERFACE_ID.value();
@@ -71,6 +74,7 @@
         this.peerMacAddr = macAddress;
     }
 
+
     /**
      * Gets Mac address.
      *
@@ -99,6 +103,25 @@
     }
 
     /**
+     * Sets the vlan id of interface id.
+     *
+     * @param vlanId the vlanid of client packet
+     */
+    public void setVlanId(short vlanId) {
+        this.vlanId = vlanId;
+    }
+
+    /**
+     * Gets the vlan id of interface id.
+     *
+     * @return the vlan id
+     *
+     */
+    public short getVlanId() {
+        return vlanId;
+    }
+
+    /**
      * Gets deserializer for DHCPv6 relay option.
      *
      * @return the deserializer
@@ -111,16 +134,20 @@
             }
             Dhcp6InterfaceIdOption interfaceIdOption = new Dhcp6InterfaceIdOption(dhcp6Option);
             byte[] optionData = interfaceIdOption.getData();
-            if (optionData.length >= 28) {
+            if (optionData.length >= 31) {
                 ByteBuffer bb = ByteBuffer.wrap(optionData);
 
                 byte[] macAddr = new byte[MacAddress.MAC_ADDRESS_LENGTH];
                 byte[] port = new byte[21];
+                short vlan;
                 bb.get(macAddr);
-                bb.get();  // separator
+                bb.get();  // separator "-"
                 bb.get(port);
+                bb.get(); // separator ":"
+                vlan = bb.getShort();
                 interfaceIdOption.setMacAddress(MacAddress.valueOf(macAddr));
                 interfaceIdOption.setInPort(port);
+                interfaceIdOption.setVlanId(vlan > VlanId.MAX_VLAN ? VlanId.UNTAGGED : vlan);
             }
             return interfaceIdOption;
         };