Yes, you are correct. I am misled by the fact that the bit mask starts with two 
0s from right to left (has discontiguous 1-bits). This can be 
explained by the byte order. 


However, there are still some cases that byte order cannot explain. I installed 
two rules, 


ovs-ofctl add-flow br0 
in_port=1,dl_type=0x0800,nw_src=10.2.10.0/24,nw_proto=6,tcp_dst=0x0050,priority=1,actions=drop
ovs-ofctl add-flow br0 
in_port=1,dl_type=0x0800,nw_src=10.2.0.0/16,nw_proto=6,tcp_dst=0x1f90,priority=1,actions=drop


and test the rules with packet (nw_src = 10.2.2.1 and tcp_dst = 8080).  I got 
the nw_src mask (in network byte order) 0x8ffff. 
Even you change it to host byte order the bit mask still has discontiguous 
1-bits 0xFFFF08 = 1111 1111 1111 1111 0000 1000.
I checked the code and find the problem lies in the 
*miniflow_and_mask_matches_flow_wc*.


/* If we have narrowed down to a single rule already, check whether         * 
that rule matches.  Either way, we're done.         *         * (Rare) hash 
collisions may cause us to miss the opportunity for this         * 
optimization. */if (!cmap_node_next(inode)) {conststruct cls_match *head;

            ASSIGN_CONTAINER(head, inode - i, index_nodes);
            if (miniflow_and_mask_matches_flow_wc(&head->flow, &subtable->mask,
                                                  flow, wc)) {/* Return highest 
priority rule that is visible. */CLS_MATCH_FOR_EACH (rule, head) {if 
(OVS_LIKELY(cls_match_visible_in_version(rule,
                                                                version))) 
{return rule;
                    }}}
This function is called in the find_match_wc, that when doing staged lookup if 
the current hash table contains only
one rule, the find_match_wc will directly check if the packet matches the rule. 
*miniflow_and_mask_matches_flow_wc* still 
needs to calculate the wildcards mask. In the implementation, if the packet 
does not match the rule, the function only set the 
first different bit in the mask. Here is the code in the function:


staticinlineboolminiflow_and_mask_matches_flow_wc(conststruct miniflow *flow,
                                  conststruct minimask *mask,
                                  conststruct flow *target,
                                  struct flow_wildcards *wc)
{const uint64_t *flowp = miniflow_get_values(flow);
    const uint64_t *maskp = miniflow_get_values(&mask->masks);
    int idx;

    MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
        uint64_t mask = *maskp++;
        uint64_t diff = (*flowp++ ^ flow_u64_value(target, idx)) & mask;

        if (diff) {/* Only unwildcard if none of the differing bits is already  
           * exact-matched. */if (!(flow_u64_value(&wc->masks, idx) & diff)) 
{/* Keep one bit of the difference.  The selected bit may be                 * 
different in big-endian v.s. little-endian systems. */
                *flow_u64_lvalue(&wc->masks, idx) |= rightmost_1bit(diff);
            }returnfalse;
        }/* Fill in the bits that were looked at. */
        *flow_u64_lvalue(&wc->masks, idx) |= mask;
    }returntrue;
}
Consider this case, two rules reside in two hash tables with different masks. 
The first tuple contains the rule (10.2.10.0/24, 80), which mismatches the 
packet (10.2.2.1, 8080), however, the first unmatched bit is at the position of 
21, the mask is therefore 0x80000. The second tuple contains (10.2.0.0/16, 
8080), which matches the packet, this generates the mask with the first 16 bits 
set, e.g. 0x8FFFF. However there are four bits unset in this case, and the mask 
should be 0xF8FFFF (in network byte order), that is the prefix 10.2.0.0/21 that 
should be put in the megaflow. 


Hope I am clear and please check the code. 
Thanks. 








At 2016-03-05 07:36:25, "Ben Pfaff" <b...@ovn.org> wrote:
>On Fri, Mar 04, 2016 at 02:51:42PM +0800, Peng He wrote:
>> Hi, 
>>     I installed some rulesets generated by ClassBench (a ruleset benchmark 
>> for generating ACL and FW rules) in Open vSwitch, and I find many megaflow's 
>> mask has 
>> discontiguous bits. Like mask = 0xfc in network byte order. After some code 
>> investigation I find the problem is in the function *mask_set_prefix_bits*: 
>> 
>> 
>> 
>> 
>> staticvoidmask_set_prefix_bits(struct flow_wildcards *wc, uint8_t be32ofs,
>>                      unsignedint n_bits)
>> {
>>     ovs_be32 *mask = &((ovs_be32 *)&wc->masks)[be32ofs];
>>     unsignedint i;
>> 
>>     for (i = 0; i < n_bits / 32; i++) {
>>         mask[i] = OVS_BE32_MAX;
>>     }if (n_bits % 32) {
>>         mask[i] |= htonl(~0u << (32 - n_bits % 32));
>>     }}
>> For example, if the input n_bits = 6, the mask should be 0x2f, as there is 6 
>> contiguous bits. However, the current code will generate 0xfc:
>> (0xFFFFFFFF << (32 - 6) ) = 0xFC000000
>> and htonl (0xFC000000) = 0xFC. 
>> I am writing this to make sure that I am correct. The OVS code I use is 2.4 
>> release version. 
>
>0xffffffff << (32 - 6) == 0xfc000000, which yields the bytes "fc 00 00
>00" in hex, or "11111100 00000000 00000000 00000000" in binary, when
>stored into memory in network byte order.
>
>I don't see the problem.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to