Closed dingrui37 closed 6 years ago
@dingrui37 ,
You have a couple of options to achieve what you want, but your program seems to be not quite one of them.
Here are your options:
Happy hacking, Vladimir
@vgurevich, thank you for your reply.
0 mask 0xfe00: parse_llc_header;
0 mask 0xfa00: parse_llc_header;
0x05dc mask 0xffff /* 1500 itself */
-----------------------------------
0 0000 0000 0000 0000
....
512 0000 0010 0000 0000
....
1023 0000 0011 1111 1111
-----------------------------------
mask 1111 1100 0000 0000 ==> 0x fc 00
mask 1111 1110 0000 0000 ==> 0x fe 00 1111 1000 0000 0000 ==> 0x f8 00 why not 0xf800 ?
I think perhaps I have some misunderstanding about the mask operator in select expression. I have read the P4_14 spec. In my opinon, the matching process is shown as below. Please point out my mistakes. 1) convert the mask value to binary; 0xfe00 --> 1111 1110 0000 0000; 2) using the 'etherType' value AND 1111 1110 0000 0000, the result's first 7bits will be ignored; For example,
1500 0000 0101 1101 1100
& 0xfe00 1111 1110 0000 0000
--------------------------------------
0000 0100 0000 0000
3) using the result compares with 0, without the first 7bits, the result is match the first entry.
0 mask 0xfe00: parse_llc_header;
parser parse_ethernet {
extract(ethernet);
return select(latest.etherType) {
0 mask 0xfe00: parse_llc_header;
0 mask 0xfa00: parse_llc_header;
ETHERTYPE_BF_FABRIC : parse_fabric_header;
PARSE_ETHERTYPE;
}
}
@dingrui37 ,
The 1's in the mask indicate which bits in the value matter and 0's indicate which bits do not matter.
From the spec:
The mask operator is used to indicate a ternary match should be performed using the indicated mask value. The comparison between the select expression and the case’s value is limited to the bits set in the mask; that is, the select expression and value are each ANDed with the mask before the comparison is made.
@vgurevich I think the correct result is 0xfa00 and 0xfc00, is it right?
0x0400 mask 0xfa00 /* 1024..1535 */
0x0000 mask 0xfc00 /* 0..1023 */
@dingrui37 ,
Your solution would work, although I prefer the canonical way:
0x0400 mask 0xfe00 /* 1024..1535 */
0x0000 mask 0xfc00 /* 0..1023 */
The difference is that in the canonical solution we maintain that value & mask == value
. Also, the ranges are non-intersecting (in your solution, the first line also catches values 0..511 as does the second line as well) and masks do not have holes in them. These are often important considerations when it comes down to HW programming.
@vgurevich Thanks.
I think if the ethernet.etherType <= 0x05DC or 1500(decimal), it is a 802.3 format header. In the parse_ethernet (include/parse.p4 file) function, the select compares the values to find a matching one.
If the length is 512, and the ternart match is not 0, therefore, it cannot be handled by the parse_llc_header function, but it is a 802.3 format. I wonder if it is a problem or a mistake I make.