/* * Copyright (c) 2014 NEC Corporation * All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.openflow.protocol.OFMatch.OFPFW_ALL; import static org.openflow.protocol.OFMatch.OFPFW_DL_VLAN; import static org.openflow.protocol.OFMatch.OFPFW_DL_VLAN_PCP; import static org.openflow.protocol.OFMatch.OFPFW_IN_PORT; import java.nio.ByteBuffer; import org.junit.Test; /** * JUnit test for {@link V6Match}. */ public class V6MatchTest { /** * Header of a match entry for input port field without a mask. * The vendor-specific value is 0, and the length of value is 2. */ private static int HEADER_INPUT_PORT = (0 << 9) | 2; /** * Header of a match entry for VLAN TCI field without a mask. * The vendor-specific value is 4, and the length of value is 2. */ private static int HEADER_VLAN_TCI= (4 << 9) | 2; /** * Header of a match entry for VLAN TCI field with a mask. * The vendor-specific value is 4, and the length of value is 4. */ private static int HEADER_VLAN_TCI_W = (4 << 9) | (1 << 8) | 4; /** * Length of a match entry for input port field. * Header (4 bytes) + value (2 bytes) = 6 bytes. */ private static short MATCH_LEN_INPUT_PORT = 6; /** * Length of a match entry for VLAN TCI field without a mask. * Header (4 bytes) + value (2 bytes) = 6 bytes. */ private static short MATCH_LEN_VLAN_TCI = 6; /** * Length of a match entry for VLAN TCI field with a mask. * Header (4 bytes) + value (2 bytes) + bitmask (2 bytes) = 8 bytes. */ private static short MATCH_LEN_VLAN_TCI_WITH_MASK = 8; /** * Value of OFP_VLAN_NONE defined by OpenFlow 1.0. */ private static final short OFP_VLAN_NONE = (short)0xffff; /** * CFI bit in VLAN TCI field. */ private static final int VLAN_TCI_CFI = 1 << 12; /** * Test case for {@link V6Match#fromString(String)} about VLAN TCI field. * This test passes values to "dl_vlan" and "dl_vpcp". */ @Test public void testFromStringVlanTci() { // Test for "dl_vlan" using non OFP_VLAN_NONE values. short vlans[] = {1, 10, 1000, 4095}; short mask = 0; for (short vlan: vlans) { V6Match match = new V6Match(); match.fromString("dl_vlan=" + vlan); assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen()); assertEquals(vlan, match.getDataLayerVirtualLan()); int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN; assertEquals(wildcards, match.getWildcards()); } // Test for "dl_vpcp". byte pcps[] = {1, 3, 7}; for (byte pcp: pcps) { V6Match match = new V6Match(); match.fromString("dl_vpcp=" + pcp); assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen()); assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint()); int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN_PCP; assertEquals(wildcards, match.getWildcards()); } // Set "dl_vlan" field firstly, "dl_vpcp" field secondly. for (short vlan: vlans) { for (byte pcp: pcps) { V6Match match = new V6Match(); match.fromString("dl_vlan=" + vlan); match.fromString("dl_vpcp=" + pcp); assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen()); assertEquals(vlan, match.getDataLayerVirtualLan()); assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint()); } } // Set "dl_vpcp" field firstly, "dl_vlan" field secondly. for (short vlan: vlans) { for (byte pcp: pcps) { V6Match match = new V6Match(); match.fromString("dl_vpcp=" + pcp); match.fromString("dl_vlan=" + vlan); assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen()); assertEquals(vlan, match.getDataLayerVirtualLan()); assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint()); } } // Test for OFP_VLAN_NONE when VLAN PCP is not set. V6Match match = new V6Match(); match.fromString("dl_vlan=" + OFP_VLAN_NONE); assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen()); assertEquals(OFP_VLAN_NONE, match.getDataLayerVirtualLan()); // Test for OFP_VLAN_NONE when VLAN PCP is set. match = new V6Match(); match.fromString("dl_vpcp=" + 1); try { match.fromString("dl_vlan=" + OFP_VLAN_NONE); fail("Throwing exception was expected."); } catch (IllegalArgumentException e) { // Throwing exception was expected. } } /** * Test case for {@link V6Match#writeTo(ByteBuffer)} for VLAN TCI field. */ @Test public void testWriteToVlanTci() { byte mask = 0; // Set only VLAN ID. short vlans[] = {1, 10, 1000, 4095}; for (short vlan: vlans) { V6Match match = new V6Match(); match.setDataLayerVirtualLan(vlan, mask); ByteBuffer data = ByteBuffer.allocate(10); match.writeTo(data); assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, data.position()); data.flip(); // Header assertEquals(HEADER_VLAN_TCI_W, data.getInt()); // Value short expectedTci = (short) (VLAN_TCI_CFI | vlan); assertEquals(expectedTci, data.getShort()); // Mask short expectedMask = 0x1fff; assertEquals(expectedMask, data.getShort()); } // Set only VLAN PCP. byte pcps[] = {1, 3, 7}; for (byte pcp: pcps) { V6Match match = new V6Match(); match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask); ByteBuffer data = ByteBuffer.allocate(10); match.writeTo(data); assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, data.position()); data.flip(); // Header assertEquals(HEADER_VLAN_TCI_W, data.getInt()); // Value short expectedTci = (short) (pcp << 13 | VLAN_TCI_CFI); assertEquals(expectedTci, data.getShort()); // Mask short expectedMask = (short) 0xf000; assertEquals(expectedMask, data.getShort()); } // Set both VLAN ID and PCP. for (short vlan: vlans) { for (byte pcp: pcps) { V6Match match = new V6Match(); match.setDataLayerVirtualLan(vlan, mask); match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask); ByteBuffer data = ByteBuffer.allocate(10); match.writeTo(data); assertEquals(MATCH_LEN_VLAN_TCI, data.position()); data.flip(); // Header assertEquals(HEADER_VLAN_TCI, data.getInt()); // Value short expectedTci = (short) (pcp << 13 | VLAN_TCI_CFI | vlan); assertEquals(expectedTci, data.getShort()); } } // Set OFP_VLAN_NONE. V6Match match = new V6Match(); match.setDataLayerVirtualLan(OFP_VLAN_NONE, mask); ByteBuffer data = ByteBuffer.allocate(10); match.writeTo(data); assertEquals(MATCH_LEN_VLAN_TCI, data.position()); data.flip(); // Header assertEquals(HEADER_VLAN_TCI, data.getInt()); // Value assertEquals(0, data.getShort()); } /** * Test case for {@link V6Match#writeTo(ByteBuffer)} for input port field. */ @Test public void testWriteToInputPort() { // Set input port. short ports[] = {1, 10, 100, 1000}; for (short port: ports) { V6Match match = new V6Match(); match.setInputPort(port, (short) 0); ByteBuffer data = ByteBuffer.allocate(10); match.writeTo(data); assertEquals(MATCH_LEN_INPUT_PORT, data.position()); data.flip(); // Header assertEquals(HEADER_INPUT_PORT, data.getInt()); // Value assertEquals(port, data.getShort()); } } /** * Test case for {@link V6Match#readFrom(ByteBuffer)} for VLAN TCI field. */ @Test public void testReadFromVlanTci() { // Test for an exact match a TCI value with CFI=1. // It matches packets that have an 802.1Q header with a specified // VID and PCP. short vlans[] = {1, 10, 1000, 4095}; byte pcps[] = {1, 3, 7}; for (short vlan: vlans) { for (byte pcp: pcps) { ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_VLAN_TCI); data.putInt(HEADER_VLAN_TCI); short tci = (short) (pcp << 13 | VLAN_TCI_CFI | vlan); data.putShort(tci); data.flip(); V6Match match = new V6Match(); match.readFrom(data); assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen()); assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint()); assertEquals(vlan, match.getDataLayerVirtualLan()); int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN_PCP & ~OFPFW_DL_VLAN; assertEquals(wildcards, match.getWildcards()); } } // Test with a specific VID and CFI=1 with mask=0x1fff. // It matches packets that have an 802.1Q header with that VID // and any PCP. for (short vlan: vlans) { ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_VLAN_TCI_WITH_MASK); data.putInt(HEADER_VLAN_TCI_W); short tci = (short) (VLAN_TCI_CFI | vlan); data.putShort(tci); short mask = (short) 0x1fff; data.putShort(mask); data.flip(); V6Match match = new V6Match(); match.readFrom(data); assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen()); assertEquals(vlan, match.getDataLayerVirtualLan()); int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN; assertEquals(wildcards, match.getWildcards()); } // Test with a specific PCP and CFI=1 with mask=0xf000. // It matches packets that have an 802.1Q header with that PCP // and any VID. for (byte pcp: pcps) { ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_VLAN_TCI_WITH_MASK); data.putInt(HEADER_VLAN_TCI_W); short tci = (short) (pcp << 13| VLAN_TCI_CFI); data.putShort(tci); short mask = (short) 0xf000; data.putShort(mask); data.flip(); V6Match match = new V6Match(); match.readFrom(data); assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen()); assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint()); int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN_PCP; assertEquals(wildcards, match.getWildcards()); } // Test for an exact match with 0. // It matches only packets without an 802.1Q header. ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_VLAN_TCI); data.putInt(HEADER_VLAN_TCI); short tci = 0; data.putShort(tci); data.flip(); V6Match match = new V6Match(); match.readFrom(data); assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen()); assertEquals(OFP_VLAN_NONE, match.getDataLayerVirtualLan()); int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN; assertEquals(wildcards, match.getWildcards()); } /** * Test case for {@link V6Match#readFrom(ByteBuffer)} for input port field. */ @Test public void testReadFromInputPort() { // Set input port. short ports[] = {1, 10, 100, 1000}; for (short port: ports) { ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_INPUT_PORT); data.putInt(HEADER_INPUT_PORT); data.putShort(port); data.flip(); V6Match match = new V6Match(); match.readFrom(data); assertEquals(MATCH_LEN_INPUT_PORT, match.getIPv6MatchLen()); assertEquals(port, match.getInputPort()); int wildcards = OFPFW_ALL & ~OFPFW_IN_PORT; assertEquals(wildcards, match.getWildcards()); } } /** * Test case for {@link V6Match#setDataLayerVirtualLan(short, short)}. */ @Test public void testSetDataLayerVirtualLan() { short vlans[] = {1, 10, 1000, 4095}; short mask = 0; for (short vlan: vlans) { V6Match match = new V6Match(); match.setDataLayerVirtualLan(vlan, mask); assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen()); assertEquals(vlan, match.getDataLayerVirtualLan()); } // Test for OFP_VLAN_NONE. V6Match match = new V6Match(); match.setDataLayerVirtualLan(OFP_VLAN_NONE, mask); assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen()); assertEquals(OFP_VLAN_NONE, match.getDataLayerVirtualLan()); } /** * Test case for * {@link V6Match#setDataLayerVirtualLanPriorityCodePoint(byte, byte)}. */ @Test public void testSetDataLayerVirtualLanPriorityCodePoint() { byte pcps[] = {1, 3, 7}; byte mask = 0; for (byte pcp: pcps) { V6Match match = new V6Match(); match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask); assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen()); assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint()); } } /** * Test case for setter methods for VLAN TCI field. * * This test case calls {@link V6Match#setDataLayerVirtualLan(short, short)} * and {@link V6Match#setDataLayerVirtualLanPriorityCodePoint(byte, byte)}. */ @Test public void testSetVlanTCI() { short vlans[] = {1, 10, 1000, 4095}; byte pcps[] = {1, 3, 7}; byte mask = 0; // Call setDataLayerVirtualLan(short, short) firstly, // and setDataLayerVirtualLanPriorityCodePoint(byte, byte) secondly, for (short vlan: vlans) { for (byte pcp: pcps) { V6Match match = new V6Match(); match.setDataLayerVirtualLan(vlan, mask); match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask); assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen()); assertEquals(vlan, match.getDataLayerVirtualLan()); assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint()); } } // Call setDataLayerVirtualLanPriorityCodePoint(byte, byte) firstly, // and setDataLayerVirtualLan(short, short) secondly. for (short vlan: vlans) { for (byte pcp: pcps) { V6Match match = new V6Match(); match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask); match.setDataLayerVirtualLan(vlan, mask); assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen()); assertEquals(vlan, match.getDataLayerVirtualLan()); assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint()); } } // Test for setting OFP_VLAN_NONE when VLAN PCP is set. for (byte pcp: pcps) { V6Match match = new V6Match(); match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask); try { match.setDataLayerVirtualLan(OFP_VLAN_NONE, mask); } catch (IllegalStateException e) { // Throwing exception was expected. } } // Test for set VLAN PCP when OFP_VLAN_NONE is set to VLAN match. for (byte pcp: pcps) { V6Match match = new V6Match(); match.setDataLayerVirtualLan(OFP_VLAN_NONE, mask); try { match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask); } catch (IllegalStateException e) { // Throwing exception was expected. } } } /** * Test case for {@link V6Match#setInputPort(short, short)}. */ @Test public void testSetInputPort() { short ports[] = {1, 10, 100, 1000}; for (short port: ports) { V6Match match = new V6Match(); match.setInputPort(port, (short) 0); assertEquals(MATCH_LEN_INPUT_PORT, match.getIPv6MatchLen()); assertEquals(port, match.getInputPort()); } } }