static int
test_match_1(void)
{
    of_match_v1_t *m_v1;
    of_match_v2_t *m_v2;
    of_match_v3_t *m_v3;
    of_match_v4_t *m_v4;
    of_match_t match;
    int value = 1;
    int idx;
    uint32_t exp_value;

    /* Verify default values for ip mask map */
    for (idx = 0; idx < 64; idx++) {
        exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
        TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
        if (idx < 32) {
            TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
        }
    }

    /* Create/populate/convert and delete for version OF_VERSION_1_0 */
    m_v1 = of_match_v1_new(OF_VERSION_1_0);
    TEST_ASSERT(m_v1 != NULL);
    TEST_ASSERT((value = of_match_populate(&match, OF_VERSION_1_0, value)) > 0);
    TEST_OK(of_match_to_wire_match_v1(&match, m_v1));
    of_match_v1_delete(m_v1);

    /* Create/populate/convert and delete for version OF_VERSION_1_1 */
    m_v2 = of_match_v2_new(OF_VERSION_1_1);
    TEST_ASSERT(m_v2 != NULL);
    TEST_ASSERT((value = of_match_populate(&match, OF_VERSION_1_1, value)) > 0);
    TEST_OK(of_match_to_wire_match_v2(&match, m_v2));
    of_match_v2_delete(m_v2);

    /* Create/populate/convert and delete for version OF_VERSION_1_2 */
    m_v3 = of_match_v3_new(OF_VERSION_1_2);
    TEST_ASSERT(m_v3 != NULL);
    TEST_ASSERT((value = of_match_populate(&match, OF_VERSION_1_2, value)) > 0);
    TEST_OK(of_match_to_wire_match_v3(&match, m_v3));
    of_match_v3_delete(m_v3);

    /* Create/populate/convert and delete for version OF_VERSION_1_3 */
    m_v4 = of_match_v4_new(OF_VERSION_1_3);
    TEST_ASSERT(m_v4 != NULL);
    TEST_ASSERT((value = of_match_populate(&match, OF_VERSION_1_3, value)) > 0);
    TEST_OK(of_match_to_wire_match_v4(&match, m_v4));
    of_match_v4_delete(m_v4);

    return TEST_PASS;
}
static int
test_match_2(void)
{
    of_match_v1_t *m_v1;
    of_match_v2_t *m_v2;
    of_match_v3_t *m_v3;
    of_match_v3_t *m_v4;
    of_match_t match1;
    of_match_t match2;
    int value = 1;

    TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_0, value)) > 0);
    m_v1 = of_match_v1_new(OF_VERSION_1_0);
    TEST_ASSERT(m_v1 != NULL);
    TEST_OK(of_match_to_wire_match_v1(&match1, m_v1));
    TEST_OK(of_match_v1_to_match(m_v1, &match2));
    TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
    of_match_v1_delete(m_v1);

    TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_1, value)) > 0);
    m_v2 = of_match_v2_new(OF_VERSION_1_1);
    TEST_ASSERT(m_v2 != NULL);
    TEST_OK(of_match_to_wire_match_v2(&match1, m_v2));
    TEST_OK(of_match_v2_to_match(m_v2, &match2));
    TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
    of_match_v2_delete(m_v2);

    TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_2, value)) > 0);
    m_v3 = of_match_v3_new(OF_VERSION_1_2);
    TEST_ASSERT(m_v3 != NULL);
    TEST_OK(of_match_to_wire_match_v3(&match1, m_v3));
    TEST_OK(of_match_v3_to_match(m_v3, &match2));
    TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
    of_match_v3_delete(m_v3);

    TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_3, value)) > 0);
    m_v4 = of_match_v4_new(OF_VERSION_1_3);
    TEST_ASSERT(m_v4 != NULL);
    TEST_OK(of_match_to_wire_match_v4(&match1, m_v4));
    TEST_OK(of_match_v4_to_match(m_v4, &match2));
    TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
    of_match_v4_delete(m_v4);

    return TEST_PASS;
}
static int
test_match_3(void)
{
    of_match_t match1;
    of_match_t match2;
    int value = 1;
    of_octets_t octets;
    of_object_storage_t storage;
    memset(&storage, 0, sizeof(storage));
    storage.obj.wbuf = &storage.wbuf;

    /* Serialize to version OF_VERSION_1_0 */
    TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_0, value)) > 0);
    TEST_ASSERT(of_match_serialize(OF_VERSION_1_0, &match1, &octets) ==
        OF_ERROR_NONE);
    storage.obj.wbuf->buf = octets.data;
    storage.obj.wbuf->alloc_bytes = octets.bytes;
    storage.obj.wbuf->current_bytes = octets.bytes;
    TEST_ASSERT(of_match_deserialize(OF_VERSION_1_0, &match2, &storage.obj, 0, octets.bytes) ==
        OF_ERROR_NONE);
    TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
    FREE(octets.data);

    /* Serialize to version OF_VERSION_1_1 */
    TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_1, value)) > 0);
    TEST_ASSERT(of_match_serialize(OF_VERSION_1_1, &match1, &octets) ==
        OF_ERROR_NONE);
    storage.obj.wbuf->buf = octets.data;
    storage.obj.wbuf->alloc_bytes = octets.bytes;
    storage.obj.wbuf->current_bytes = octets.bytes;
    TEST_ASSERT(of_match_deserialize(OF_VERSION_1_1, &match2, &storage.obj, 0, octets.bytes) ==
        OF_ERROR_NONE);
    TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
    FREE(octets.data);

    /* Serialize to version OF_VERSION_1_2 */
    TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_2, value)) > 0);
    TEST_ASSERT(of_match_serialize(OF_VERSION_1_2, &match1, &octets) ==
        OF_ERROR_NONE);
    storage.obj.wbuf->buf = octets.data;
    storage.obj.wbuf->alloc_bytes = octets.bytes;
    storage.obj.wbuf->current_bytes = octets.bytes;
    TEST_ASSERT(of_match_deserialize(OF_VERSION_1_2, &match2, &storage.obj, 0, octets.bytes) ==
        OF_ERROR_NONE);
    TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
    FREE(octets.data);

    /* Serialize to version OF_VERSION_1_3 */
    TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_3, value)) > 0);
    TEST_ASSERT(of_match_serialize(OF_VERSION_1_3, &match1, &octets) ==
        OF_ERROR_NONE);
    storage.obj.wbuf->buf = octets.data;
    storage.obj.wbuf->alloc_bytes = octets.bytes;
    storage.obj.wbuf->current_bytes = octets.bytes;
    TEST_ASSERT(of_match_deserialize(OF_VERSION_1_3, &match2, &storage.obj, 0, octets.bytes) ==
        OF_ERROR_NONE);
    TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
    FREE(octets.data);

    return TEST_PASS;
}
int
test_match_utils(void)
{
    of_mac_addr_t m1 = {{0,0,1,1,3,3}};
    of_mac_addr_t m2 = {{0,0,1,1,3,3}};  /* m1 == m2 */
    of_mac_addr_t m3 = {{0,0,1,1,1,1}};  /* m1 is more specific than m3 */
    of_mac_addr_t m4 = {{0xf,0,1,1,3,3}};  /* m1 is not more specific m4 */
    of_mac_addr_t m5 = {{0,0,1,1,3,0xf}};  /* m1 is not more specific m5 */

    of_mac_addr_t m_mask1 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
    of_mac_addr_t m_mask2 = {{0xff, 0xff, 0xff, 0xff, 0, 0}};

    /* m1 matches m2 for mask1 */
    /* m1 matches m2 for mask2 */
    /* m1 does not match m3, m4, m5 for mask1 */
    /* m1 matches m3, m5 for mask2 */
    /* m1 does not match m4 for mask2 */

    of_ipv6_t i1 = {{0,0,0,0,1,1,1,1,3,3,3,3,7,7,7,7}};  /* same as above */
    of_ipv6_t i2 = {{0,0,0,0,1,1,1,1,3,3,3,3,7,7,7,7}};  
    of_ipv6_t i3 = {{0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1}};
    of_ipv6_t i4 = {{0xf,0,0,0,1,1,1,1,3,3,3,3,7,7,7,7}};
    of_ipv6_t i5 = {{0,0,0,0,1,1,1,1,3,3,3,3,7,7,7,0xf}};

    of_ipv6_t i_mask1 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
    of_ipv6_t i_mask2 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                          0, 0, 0, 0, 0, 0, 0, 0}};

    /* Same relationships as above */

    uint32_t v1 = 3;  /* same as above */
    uint32_t v2 = 3;
    uint32_t v3 = 1;
    uint32_t v4 = 4;
    uint32_t v5 = (1 << 31) | 1;

    uint32_t u32_mask1 = -1;
    uint32_t u32_mask2 = 1;

    uint64_t w1 = 3;  /* same as above */
    uint64_t w2 = 3;
    uint64_t w3 = 1;
    uint64_t w4 = 4;
    uint64_t w5 = (1LL << 63) | 1LL;

    uint64_t u64_mask1 = -1;
    uint64_t u64_mask2 = 1;

    /* Match structures */
    of_match_t match1, match2;

    TEST_ASSERT(OF_MORE_SPECIFIC_MAC_ADDR(&m1, &m2));
    TEST_ASSERT(OF_MORE_SPECIFIC_MAC_ADDR(&m1, &m3));
    TEST_ASSERT(!OF_MORE_SPECIFIC_MAC_ADDR(&m1, &m4));
    TEST_ASSERT(!OF_MORE_SPECIFIC_MAC_ADDR(&m1, &m5));

    TEST_ASSERT(OF_MORE_SPECIFIC_IPV6(&i1, &i2));
    TEST_ASSERT(OF_MORE_SPECIFIC_IPV6(&i1, &i3));
    TEST_ASSERT(!OF_MORE_SPECIFIC_IPV6(&i1, &i4));
    TEST_ASSERT(!OF_MORE_SPECIFIC_IPV6(&i1, &i5));

    TEST_ASSERT(OF_MORE_SPECIFIC_INT(v1, v2));
    TEST_ASSERT(OF_MORE_SPECIFIC_INT(v1, v3));
    TEST_ASSERT(!OF_MORE_SPECIFIC_INT(v1, v4));
    TEST_ASSERT(!OF_MORE_SPECIFIC_INT(v1, v5));

    TEST_ASSERT(OF_MORE_SPECIFIC_INT(w1, w2));
    TEST_ASSERT(OF_MORE_SPECIFIC_INT(w1, w3));
    TEST_ASSERT(!OF_MORE_SPECIFIC_INT(w1, w4));
    TEST_ASSERT(!OF_MORE_SPECIFIC_INT(w1, w5));

    /* Test restricted matches on macs */
    TEST_ASSERT(OF_RESTRICTED_MATCH_MAC_ADDR(&m1, &m2, &m_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_MAC_ADDR(&m1, &m3, &m_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_MAC_ADDR(&m1, &m4, &m_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_MAC_ADDR(&m1, &m5, &m_mask1));

    TEST_ASSERT(OF_RESTRICTED_MATCH_MAC_ADDR(&m1, &m2, &m_mask2));
    TEST_ASSERT(OF_RESTRICTED_MATCH_MAC_ADDR(&m1, &m3, &m_mask2));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_MAC_ADDR(&m1, &m4, &m_mask2));
    TEST_ASSERT(OF_RESTRICTED_MATCH_MAC_ADDR(&m1, &m5, &m_mask2));

    /* Test overlap */
    TEST_ASSERT(OF_OVERLAP_MAC_ADDR(&m1, &m2, &m_mask1, &m_mask2));
    TEST_ASSERT(OF_OVERLAP_MAC_ADDR(&m1, &m3, &m_mask1, &m_mask2));
    TEST_ASSERT(!OF_OVERLAP_MAC_ADDR(&m1, &m3, &m_mask1, &m_mask1));
    TEST_ASSERT(!OF_OVERLAP_MAC_ADDR(&m1, &m4, &m_mask1, &m_mask2));
    TEST_ASSERT(OF_OVERLAP_MAC_ADDR(&m1, &m5, &m_mask1, &m_mask2));

    /* Test restricted matches on ipv6 */
    TEST_ASSERT(OF_RESTRICTED_MATCH_IPV6(&i1, &i2, &i_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_IPV6(&i1, &i3, &i_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_IPV6(&i1, &i4, &i_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_IPV6(&i1, &i5, &i_mask1));

    TEST_ASSERT(OF_RESTRICTED_MATCH_IPV6(&i1, &i2, &i_mask2));
    TEST_ASSERT(OF_RESTRICTED_MATCH_IPV6(&i1, &i3, &i_mask2));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_IPV6(&i1, &i4, &i_mask2));
    TEST_ASSERT(OF_RESTRICTED_MATCH_IPV6(&i1, &i5, &i_mask2));

    /* Test overlap */
    TEST_ASSERT(OF_OVERLAP_IPV6(&i1, &i2, &i_mask1, &i_mask2));
    TEST_ASSERT(OF_OVERLAP_IPV6(&i1, &i3, &i_mask1, &i_mask2));
    TEST_ASSERT(!OF_OVERLAP_IPV6(&i1, &i3, &i_mask1, &i_mask1));
    TEST_ASSERT(!OF_OVERLAP_IPV6(&i1, &i4, &i_mask1, &i_mask2));
    TEST_ASSERT(OF_OVERLAP_IPV6(&i1, &i5, &i_mask1, &i_mask2));

    /* Test restricted matches on uint32 */
    TEST_ASSERT(OF_RESTRICTED_MATCH_INT(v1, v2, u32_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_INT(v1, v3, u32_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_INT(v1, v4, u32_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_INT(v1, v5, u32_mask1));

    TEST_ASSERT(OF_RESTRICTED_MATCH_INT(v1, v2, u32_mask2));
    TEST_ASSERT(OF_RESTRICTED_MATCH_INT(v1, v3, u32_mask2));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_INT(v1, v4, u32_mask2));
    TEST_ASSERT(OF_RESTRICTED_MATCH_INT(v1, v5, u32_mask2));

    /* Test overlap */
    TEST_ASSERT(OF_OVERLAP_INT(v1, v2, u32_mask1, u32_mask2));
    TEST_ASSERT(OF_OVERLAP_INT(v1, v3, u32_mask1, u32_mask2));
    TEST_ASSERT(!OF_OVERLAP_INT(v1, v3, u32_mask1, u32_mask1));
    TEST_ASSERT(!OF_OVERLAP_INT(v1, v4, u32_mask1, u32_mask2));
    TEST_ASSERT(OF_OVERLAP_INT(v1, v5, u32_mask1, u32_mask2));

    /* Test restricted matches on uint64 */
    TEST_ASSERT(OF_RESTRICTED_MATCH_INT(w1, w2, u64_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_INT(w1, w3, u64_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_INT(w1, w4, u64_mask1));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_INT(w1, w5, u64_mask1));

    TEST_ASSERT(OF_RESTRICTED_MATCH_INT(w1, w2, u64_mask2));
    TEST_ASSERT(OF_RESTRICTED_MATCH_INT(w1, w3, u64_mask2));
    TEST_ASSERT(!OF_RESTRICTED_MATCH_INT(w1, w4, u64_mask2));
    TEST_ASSERT(OF_RESTRICTED_MATCH_INT(w1, w5, u64_mask2));

    /* Test overlap */
    TEST_ASSERT(OF_OVERLAP_INT(w1, w2, u64_mask1, u64_mask2));
    TEST_ASSERT(OF_OVERLAP_INT(w1, w3, u64_mask1, u64_mask2));
    TEST_ASSERT(!OF_OVERLAP_INT(w1, w3, u64_mask1, u64_mask1));
    TEST_ASSERT(!OF_OVERLAP_INT(w1, w4, u64_mask1, u64_mask2));
    TEST_ASSERT(OF_OVERLAP_INT(w1, w5, u64_mask1, u64_mask2));

    /* Test match stuctures */
    of_match_populate(&match1, OF_VERSION_1_2, 1);
    of_match_populate(&match2, OF_VERSION_1_2, 1);
    TEST_ASSERT(of_match_eq(&match1, &match2));
    TEST_ASSERT(of_match_eq(&match2, &match1));
    TEST_ASSERT(of_match_more_specific(&match1, &match2));
    TEST_ASSERT(of_match_more_specific(&match2, &match1));
    TEST_ASSERT(of_match_overlap(&match1, &match2));
    TEST_ASSERT(of_match_overlap(&match2, &match1));

    /* Change match2 so it still is extended by match1 */
    memset(&match2.masks.eth_dst, 0, sizeof(of_mac_addr_t));
    TEST_ASSERT(of_match_more_specific(&match1, &match2));
    TEST_ASSERT(!of_match_more_specific(&match2, &match1));
    TEST_ASSERT(!of_match_eq(&match1, &match2));
    TEST_ASSERT(of_match_overlap(&match1, &match2));
    TEST_ASSERT(of_match_overlap(&match2, &match1));

    /* Now change a value so that matches disagree */
    match2.fields.in_port++;
    TEST_ASSERT(!of_match_more_specific(&match1, &match2));
    TEST_ASSERT(!of_match_overlap(&match1, &match2));
    TEST_ASSERT(!of_match_overlap(&match2, &match1));
    /* Clear inport mask on match2 and should extend again */
    match2.masks.in_port = 0;
    TEST_ASSERT(of_match_more_specific(&match1, &match2));
    TEST_ASSERT(of_match_overlap(&match1, &match2));
    TEST_ASSERT(of_match_overlap(&match2, &match1));

    /* Now change mask so the overlap, but not more specific */
    match1.fields.in_port = 0x7;
    match1.masks.in_port = 0x7;
    match2.fields.in_port = 0xe;
    match2.masks.in_port = 0xe;
    TEST_ASSERT(!of_match_more_specific(&match1, &match2));
    TEST_ASSERT(!of_match_more_specific(&match2, &match1));
    TEST_ASSERT(of_match_overlap(&match1, &match2));
    TEST_ASSERT(of_match_overlap(&match2, &match1));
    
    return TEST_PASS;
}