For each attribute: - copy ct2 attrs to ct1 (so they're the same) - change value of attr - call nfct_cmp to check of cmp now fails Unfortunately, most attributes fail this test at this time, thus added a TODO exclusion list to make the test pass for now. Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- It would be nice if others could have a look at the FIXME switch in the patch below, and perhaps add comments for those attributes that are intentionally omitted from comparisions. diff --git a/qa/test_api.c b/qa/test_api.c index aea4bc0..583feb8 100644 --- a/qa/test_api.c +++ b/qa/test_api.c @@ -36,6 +36,7 @@ static void test_nfct_bitmask(void) { struct nfct_bitmask *a, *b; unsigned short int maxb, i; + struct nf_conntrack *ct1, *ct2; printf("== test nfct_bitmask_* API ==\n"); @@ -79,9 +80,168 @@ static void test_nfct_bitmask(void) } nfct_bitmask_destroy(b); + + ct1 = nfct_new(); + ct2 = nfct_new(); + + maxb = rand() & 0xff; + maxb += 128; + maxb /= 2; + a = nfct_bitmask_new(maxb * 2); + b = nfct_bitmask_new(maxb); + nfct_set_attr(ct1, ATTR_CONNLABELS, a); + nfct_set_attr(ct2, ATTR_CONNLABELS, b); + + assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); + + nfct_bitmask_set_bit(a, maxb); + nfct_bitmask_set_bit(b, maxb); + assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); + + nfct_bitmask_set_bit(a, maxb * 2); + assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 0); + nfct_destroy(ct1); + nfct_destroy(ct2); printf("OK\n"); } +/* These attributes cannot be set, ignore them. */ +static int attr_is_readonly(int attr) +{ + switch (attr) { + case ATTR_ORIG_COUNTER_PACKETS: + case ATTR_REPL_COUNTER_PACKETS: + case ATTR_ORIG_COUNTER_BYTES: + case ATTR_REPL_COUNTER_BYTES: + case ATTR_USE: + case ATTR_SECCTX: + case ATTR_TIMESTAMP_START: + case ATTR_TIMESTAMP_STOP: + return 1; + } + return 0; +} + + +static int test_nfct_cmp_api_single(struct nf_conntrack *ct1, + struct nf_conntrack *ct2, int attr) +{ + char data[256]; + struct nfct_bitmask *b; + int bit; + + if (attr_is_readonly(attr)) + return 0; + + switch (attr) { + case ATTR_SECMARK: /* obsolete */ + return 0; + + /* FIXME: not implemented comparators: */ + case ATTR_SNAT_IPV4: + case ATTR_DNAT_IPV4: + case ATTR_SNAT_PORT: + case ATTR_DNAT_PORT: + + case ATTR_TCP_FLAGS_ORIG: + case ATTR_TCP_FLAGS_REPL: + case ATTR_TCP_MASK_ORIG: + case ATTR_TCP_MASK_REPL: + + case ATTR_MASTER_IPV4_SRC: + case ATTR_MASTER_IPV4_DST: + case ATTR_MASTER_IPV6_SRC: + case ATTR_MASTER_IPV6_DST: + case ATTR_MASTER_PORT_SRC: + case ATTR_MASTER_PORT_DST: + case ATTR_MASTER_L3PROTO: + case ATTR_MASTER_L4PROTO: + + case ATTR_ORIG_NAT_SEQ_CORRECTION_POS: + case ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE: + case ATTR_ORIG_NAT_SEQ_OFFSET_AFTER: + case ATTR_REPL_NAT_SEQ_CORRECTION_POS: + case ATTR_REPL_NAT_SEQ_OFFSET_BEFORE: + case ATTR_REPL_NAT_SEQ_OFFSET_AFTER: + + case ATTR_SCTP_VTAG_ORIG: + case ATTR_SCTP_VTAG_REPL: + + case ATTR_HELPER_NAME: + + case ATTR_DCCP_ROLE: + case ATTR_DCCP_HANDSHAKE_SEQ: + + case ATTR_TCP_WSCALE_ORIG: + case ATTR_TCP_WSCALE_REPL: + + case ATTR_HELPER_INFO: + return 0; /* XXX */ + + default: + break; + } + + if (attr >= ATTR_SCTP_STATE) { + nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_SCTP); + nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_SCTP); + } else if (attr >= ATTR_TCP_FLAGS_ORIG) { + nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP); + nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP); + } else if (attr >= ATTR_ICMP_CODE) { + nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_ICMP); + nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_ICMP); + } else if (attr >= ATTR_ORIG_PORT_SRC) { + nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP); + nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP); + } + + nfct_copy(ct2, ct1, NFCT_CP_OVERRIDE); + memset(data, 42, sizeof(data)); + + assert(nfct_attr_is_set(ct1, attr)); + assert(nfct_attr_is_set(ct2, attr)); + + switch (attr) { + case ATTR_CONNLABELS: + case ATTR_CONNLABELS_MASK: + b = (void *) nfct_get_attr(ct1, attr); + assert(b); + b = nfct_bitmask_clone(b); + assert(b); + bit = nfct_bitmask_maxbit(b); + if (nfct_bitmask_test_bit(b, bit)) { + nfct_bitmask_unset_bit(b, bit); + assert(!nfct_bitmask_test_bit(b, bit)); + } else { + nfct_bitmask_set_bit(b, bit); + assert(nfct_bitmask_test_bit(b, bit)); + } + assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); + nfct_set_attr(ct2, attr, b); + break; + case ATTR_HELPER_INFO: + nfct_set_attr_l(ct2, attr, "test", 4); + break; + default: + nfct_set_attr(ct2, attr, data); + break; + } + + if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL) != 0) { + fprintf(stderr, "nfct_cmp assert failure for attr %d\n", attr); + fprintf(stderr, "%p, %p, %x, %x\n", nfct_get_attr(ct1, attr), + nfct_get_attr(ct2, attr), + nfct_get_attr_u32(ct1, attr), nfct_get_attr_u32(ct2, attr)); + return -1; + } + if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) != 0) { + fprintf(stderr, "nfct_cmp strict assert failure for attr %d\n", attr); + return -1; + } + return 0; +} + static void test_nfct_cmp_api(struct nf_conntrack *ct1, struct nf_conntrack *ct2) { int i; @@ -111,6 +271,10 @@ static void test_nfct_cmp_api(struct nf_conntrack *ct1, struct nf_conntrack *ct2 assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 0); assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_MASK) == 0); } + + for (i=0; i < ATTR_MAX ; i++) + assert(test_nfct_cmp_api_single(ct1, ct2, i) == 0); + nfct_copy(ct2, ct1, NFCT_CP_OVERRIDE); for (i=0; i < ATTR_MAX ; i++) { nfct_attr_unset(ct1, i); @@ -240,17 +404,9 @@ int main(void) ret = fork(); if (ret == 0) { for (i=0; i<ATTR_MAX; i++) { - /* These attributes cannot be set, ignore them. */ - switch(i) { - case ATTR_ORIG_COUNTER_PACKETS: - case ATTR_REPL_COUNTER_PACKETS: - case ATTR_ORIG_COUNTER_BYTES: - case ATTR_REPL_COUNTER_BYTES: - case ATTR_USE: - case ATTR_SECCTX: - case ATTR_TIMESTAMP_START: - case ATTR_TIMESTAMP_STOP: + if (attr_is_readonly(i)) continue; + switch(i) { /* These attributes require special handling */ case ATTR_HELPER_INFO: nfct_set_attr_l(ct, i, data, sizeof(data)); -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html