[ovs-dev] [PATCH v3 3/3] upcall: considering dataofs when parsing tcp pkt

lic121 lic121 at chinatelecom.cn
Mon Nov 22 03:10:59 UTC 2021



>On 11/1/21 12:03, lic121 wrote:



>> dataofs field of tcp header indicates the tcp header len. The len



>> should be >= 20 bytes/4. This patch is to test dataofs, and don't



>> parse layer 4 fields when meet ba dataofs. This behave is the consistent



>> with openvswitch kenrel module.



>> 



>> Signed-off-by: lic121 <lic121 at chinatelecom.cn>



>> ---



>>  lib/flow.c            | 18 ++++++++++--------



>>  tests/ofproto-dpif.at | 31 +++++++++++++++++++++++++++++++



>>  2 files changed, 41 insertions(+), 8 deletions(-)



>



>Hi.  Thanks for the patch!  And sorry for the late response.



>See some comments inline.



>

Hi Ilya, it's OK and thanks for your review.


>Bets regards, Ilya Maximets.



>



>> 



>> diff --git a/lib/flow.c b/lib/flow.c



>> index 89837de..f117490 100644



>> --- a/lib/flow.c



>> +++ b/lib/flow.c



>> @@ -1006,14 +1006,16 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)



>>          if (OVS_LIKELY(nw_proto == IPPROTO_TCP)) {



>>              if (OVS_LIKELY(size >= TCP_HEADER_LEN)) {



>>                  const struct tcp_header *tcp = data;



>> -



>> -                miniflow_push_be32(mf, arp_tha.ea[2], 0);



>> -                miniflow_push_be32(mf, tcp_flags,



>> -                                   TCP_FLAGS_BE32(tcp->tcp_ctl));



>> -                miniflow_push_be16(mf, tp_src, tcp->tcp_src);



>> -                miniflow_push_be16(mf, tp_dst, tcp->tcp_dst);



>> -                miniflow_push_be16(mf, ct_tp_src, ct_tp_src);



>> -                miniflow_push_be16(mf, ct_tp_dst, ct_tp_dst);



>> +                size_t tcp_hdr_len = TCP_OFFSET(tcp->tcp_ctl) * 4;



>



>Please, add an empty line between the declarations and the code below.

Will address this in v4


>



>> +                if (tcp_hdr_len >= TCP_HEADER_LEN) {



>



>This check seems fine, but, IIUC, it doesn't check the case where



>the TCP header length declared larger than the remaining space in



>a packet.  Looking at the kernel implementation of tcphdr_ok(),



>there are, basically, 3 checks that make it fail:



>



>1. pskb_may_pull(skb, th_ofs + sizeof(struct tcphdr))) == false



>   



>   This one is similar to (size >= TCP_HEADER_LEN) check here.



>



>2. tcp_len < sizeof(struct tcphdr)



>



>   This check you added as (tcp_hdr_len >= TCP_HEADER_LEN)



>



>3. skb->len < th_ofs + tcp_len



>



>   But this one is not covered by the patch.  IIUC, it should



>   look like:



>       if (tcp_hdr_len >= TCP_HEADER_LEN && size >= tcp_hdr_len) {



>



>Without the third check, if TCP header length is larger than



>the remaining packet size, kernel will not parse it, but



>userspace will, leading to the similar issue.



>



>Could you add this check to the patch and a test case for this



>condition?

Agree, will address this in v4


>



>> +                    miniflow_push_be32(mf, arp_tha.ea[2], 0);



>> +                    miniflow_push_be32(mf, tcp_flags,



>> +                                    TCP_FLAGS_BE32(tcp->tcp_ctl));



>



>Please, shift this line 3 spaces to the right.

good catch. Will do


>



>> +                    miniflow_push_be16(mf, tp_src, tcp->tcp_src);



>> +                    miniflow_push_be16(mf, tp_dst, tcp->tcp_dst);



>> +                    miniflow_push_be16(mf, ct_tp_src, ct_tp_src);



>> +                    miniflow_push_be16(mf, ct_tp_dst, ct_tp_dst);



>> +                }



>>              }



>>          } else if (OVS_LIKELY(nw_proto == IPPROTO_UDP)) {



>>              if (OVS_LIKELY(size >= UDP_HEADER_LEN)) {



>> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at



>> index 31fb163..0f372ae 100644



>> --- a/tests/ofproto-dpif.at



>> +++ b/tests/ofproto-dpif.at



>> @@ -4862,6 +4862,37 @@ recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,fr



>>  OVS_VSWITCHD_STOP



>>  AT_CLEANUP



>>  



>> +AT_SETUP([ofproto-dpif - malformed packets handling - upcall])



>> +OVS_VSWITCHD_START



>> +add_of_ports br0 1 90



>> +dnl drop packet has tcp port 0-f but allow other tcp packets



>> +AT_DATA([flows.txt], [dnl



>> +priority=75 tcp tp_dst=0/0xfff0     actions=drop



>> +priority=50 tcp                     actions=output:1



>> +])



>> +AT_CHECK([ovs-ofctl replace-flows br0 flows.txt])



>> +dnl good tcp pkt, tcp(sport=100,dpor=16)



>> +pkt1="be95df40fb57fa163e5ee3570800450000280001000040063e940a0a0a0a141414140064001000000000000000005002200053330000"



>> +dnl malformed tcp pkt, tcp(sport=100,dport=16,dataofs=1)



>> +pkt2="be95df40fb57fa163e5ee3570800450000280001000040063e940a0a0a0a141414140064001000000000000000001002200093330000"



>> +AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])



>> +mode=normal



>> +AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$pkt1"], [0], [stdout])



>> +dnl for good tcp pkt, ovs can extract the tp_dst=16



>> +AT_CHECK([ovs-appctl dpctl/dump-flows filter=in_port\(90\),tcp], [0], [dnl



>> +flow-dump from the main thread:



>> +recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=16/0xfff0), packets:0, bytes:0, used:never, actions:1



>> +])



>> +AT_CHECK([ovs-appctl dpctl/del-flows], [0], [stdout])



>> +AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$pkt2"], [0], [stdout])



>> +dnl for malformed tcp pkt, ovs can use default value tp_dst=0



>> +AT_CHECK([ovs-appctl dpctl/dump-flows filter=in_port\(90\),tcp], [0], [dnl



>> +flow-dump from the main thread:



>> +recirc_id(0),in_port(90),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(proto=6,frag=no),tcp(dst=0/0xfff0), packets:0, bytes:0, used:never, actions:drop



>> +])



>> +OVS_VSWITCHD_STOP



>> +AT_CLEANUP



>> +



>>  AT_SETUP([ofproto-dpif - exit])



>>  OVS_VSWITCHD_START



>>  add_of_ports br0 1 2 3 10 11 12 13 14



>> 



>



>




More information about the dev mailing list