diff mbox series

[ovs-dev,v2,1/2] ipf: Only add fragments to batch of same dl_type.

Message ID 20240516153832.153496-1-mkp@redhat.com
State Accepted, archived
Commit 3a6b8c83619d3b0e11ff2fcea5b9a04edc2f3e4a
Delegated to: Simon Horman
Headers show
Series [ovs-dev,v2,1/2] ipf: Only add fragments to batch of same dl_type. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/intel-ovs-compilation success test: success

Commit Message

Mike Pattrick May 16, 2024, 3:38 p.m. UTC
When conntrack is reassembling packet fragments, the same reassembly
context can be shared across multiple threads handling different packets
simultaneously. Once a full packet is assembled, it is added to a packet
batch for processing, this is most likely the batch that added it in the
first place, but that isn't a guarantee.

The packets in these batches should be segregated by network protocol
version (ipv4 vs ipv6) for conntrack defragmentation to function
appropriately. However, there are conditions where we would add a
reassembled packet of one type to a batch of another.

This change introduces checks to make sure that reassembled or expired
fragments are only added to packet batches of the same type.

Fixes: 4ea96698f667 ("Userspace datapath: Add fragmentation handling.")
Reported-at: https://issues.redhat.com/browse/FDP-560
Signed-off-by: Mike Pattrick <mkp@redhat.com>
---
 lib/ipf.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

Comments

Paolo Valerio June 2, 2024, 7:52 p.m. UTC | #1
Mike Pattrick <mkp@redhat.com> writes:

> When conntrack is reassembling packet fragments, the same reassembly
> context can be shared across multiple threads handling different packets
> simultaneously. Once a full packet is assembled, it is added to a packet
> batch for processing, this is most likely the batch that added it in the
> first place, but that isn't a guarantee.
>
> The packets in these batches should be segregated by network protocol
> version (ipv4 vs ipv6) for conntrack defragmentation to function
> appropriately. However, there are conditions where we would add a
> reassembled packet of one type to a batch of another.
>
> This change introduces checks to make sure that reassembled or expired
> fragments are only added to packet batches of the same type.
>
> Fixes: 4ea96698f667 ("Userspace datapath: Add fragmentation handling.")
> Reported-at: https://issues.redhat.com/browse/FDP-560
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
> ---

Acked-by: Paolo Valerio <pvalerio@redhat.com>

>  lib/ipf.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/lib/ipf.c b/lib/ipf.c
> index 7d74e2c13..3c8960be3 100644
> --- a/lib/ipf.c
> +++ b/lib/ipf.c
> @@ -1063,6 +1063,9 @@ ipf_send_completed_frags(struct ipf *ipf, struct dp_packet_batch *pb,
>      struct ipf_list *ipf_list;
>  
>      LIST_FOR_EACH_SAFE (ipf_list, list_node, &ipf->frag_complete_list) {
> +        if ((ipf_list->key.dl_type == htons(ETH_TYPE_IPV6)) != v6) {
> +            continue;
> +        }
>          if (ipf_send_frags_in_list(ipf, ipf_list, pb, IPF_FRAG_COMPLETED_LIST,
>                                     v6, now)) {
>              ipf_completed_list_clean(&ipf->frag_lists, ipf_list);
> @@ -1096,6 +1099,9 @@ ipf_send_expired_frags(struct ipf *ipf, struct dp_packet_batch *pb,
>      size_t lists_removed = 0;
>  
>      LIST_FOR_EACH_SAFE (ipf_list, list_node, &ipf->frag_exp_list) {
> +        if ((ipf_list->key.dl_type == htons(ETH_TYPE_IPV6)) != v6) {
> +            continue;
> +        }
>          if (now <= ipf_list->expiration ||
>              lists_removed >= IPF_FRAG_LIST_MAX_EXPIRED) {
>              break;
> @@ -1116,7 +1122,8 @@ ipf_send_expired_frags(struct ipf *ipf, struct dp_packet_batch *pb,
>  /* Adds a reassmebled packet to a packet batch to be processed by the caller.
>   */
>  static void
> -ipf_execute_reass_pkts(struct ipf *ipf, struct dp_packet_batch *pb)
> +ipf_execute_reass_pkts(struct ipf *ipf, struct dp_packet_batch *pb,
> +                       ovs_be16 dl_type)
>  {
>      if (ovs_list_is_empty(&ipf->reassembled_pkt_list)) {
>          return;
> @@ -1127,6 +1134,7 @@ ipf_execute_reass_pkts(struct ipf *ipf, struct dp_packet_batch *pb)
>  
>      LIST_FOR_EACH_SAFE (rp, rp_list_node, &ipf->reassembled_pkt_list) {
>          if (!rp->list->reass_execute_ctx &&
> +            rp->list->key.dl_type == dl_type &&
>              ipf_dp_packet_batch_add(pb, rp->pkt, false)) {
>              rp->list->reass_execute_ctx = rp->pkt;
>          }
> @@ -1237,7 +1245,7 @@ ipf_preprocess_conntrack(struct ipf *ipf, struct dp_packet_batch *pb,
>      }
>  
>      if (ipf_get_enabled(ipf) || atomic_count_get(&ipf->nfrag)) {
> -        ipf_execute_reass_pkts(ipf, pb);
> +        ipf_execute_reass_pkts(ipf, pb, dl_type);
>      }
>  }
>  
> -- 
> 2.39.3
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Simon Horman June 3, 2024, 2:12 p.m. UTC | #2
On Thu, May 16, 2024 at 11:38:31AM -0400, Mike Pattrick wrote:
> When conntrack is reassembling packet fragments, the same reassembly
> context can be shared across multiple threads handling different packets
> simultaneously. Once a full packet is assembled, it is added to a packet
> batch for processing, this is most likely the batch that added it in the
> first place, but that isn't a guarantee.
> 
> The packets in these batches should be segregated by network protocol
> version (ipv4 vs ipv6) for conntrack defragmentation to function
> appropriately. However, there are conditions where we would add a
> reassembled packet of one type to a batch of another.
> 
> This change introduces checks to make sure that reassembled or expired
> fragments are only added to packet batches of the same type.
> 
> Fixes: 4ea96698f667 ("Userspace datapath: Add fragmentation handling.")
> Reported-at: https://issues.redhat.com/browse/FDP-560
> Signed-off-by: Mike Pattrick <mkp@redhat.com>

Acked-by: Simon Horman <horms@ovn.org>
Aaron Conole June 5, 2024, 5:59 p.m. UTC | #3
Mike Pattrick <mkp@redhat.com> writes:

> When conntrack is reassembling packet fragments, the same reassembly
> context can be shared across multiple threads handling different packets
> simultaneously. Once a full packet is assembled, it is added to a packet
> batch for processing, this is most likely the batch that added it in the
> first place, but that isn't a guarantee.
>
> The packets in these batches should be segregated by network protocol
> version (ipv4 vs ipv6) for conntrack defragmentation to function
> appropriately. However, there are conditions where we would add a
> reassembled packet of one type to a batch of another.
>
> This change introduces checks to make sure that reassembled or expired
> fragments are only added to packet batches of the same type.
>
> Fixes: 4ea96698f667 ("Userspace datapath: Add fragmentation handling.")
> Reported-at: https://issues.redhat.com/browse/FDP-560
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
> ---

Applied, and backported to branches down to 2.17
diff mbox series

Patch

diff --git a/lib/ipf.c b/lib/ipf.c
index 7d74e2c13..3c8960be3 100644
--- a/lib/ipf.c
+++ b/lib/ipf.c
@@ -1063,6 +1063,9 @@  ipf_send_completed_frags(struct ipf *ipf, struct dp_packet_batch *pb,
     struct ipf_list *ipf_list;
 
     LIST_FOR_EACH_SAFE (ipf_list, list_node, &ipf->frag_complete_list) {
+        if ((ipf_list->key.dl_type == htons(ETH_TYPE_IPV6)) != v6) {
+            continue;
+        }
         if (ipf_send_frags_in_list(ipf, ipf_list, pb, IPF_FRAG_COMPLETED_LIST,
                                    v6, now)) {
             ipf_completed_list_clean(&ipf->frag_lists, ipf_list);
@@ -1096,6 +1099,9 @@  ipf_send_expired_frags(struct ipf *ipf, struct dp_packet_batch *pb,
     size_t lists_removed = 0;
 
     LIST_FOR_EACH_SAFE (ipf_list, list_node, &ipf->frag_exp_list) {
+        if ((ipf_list->key.dl_type == htons(ETH_TYPE_IPV6)) != v6) {
+            continue;
+        }
         if (now <= ipf_list->expiration ||
             lists_removed >= IPF_FRAG_LIST_MAX_EXPIRED) {
             break;
@@ -1116,7 +1122,8 @@  ipf_send_expired_frags(struct ipf *ipf, struct dp_packet_batch *pb,
 /* Adds a reassmebled packet to a packet batch to be processed by the caller.
  */
 static void
-ipf_execute_reass_pkts(struct ipf *ipf, struct dp_packet_batch *pb)
+ipf_execute_reass_pkts(struct ipf *ipf, struct dp_packet_batch *pb,
+                       ovs_be16 dl_type)
 {
     if (ovs_list_is_empty(&ipf->reassembled_pkt_list)) {
         return;
@@ -1127,6 +1134,7 @@  ipf_execute_reass_pkts(struct ipf *ipf, struct dp_packet_batch *pb)
 
     LIST_FOR_EACH_SAFE (rp, rp_list_node, &ipf->reassembled_pkt_list) {
         if (!rp->list->reass_execute_ctx &&
+            rp->list->key.dl_type == dl_type &&
             ipf_dp_packet_batch_add(pb, rp->pkt, false)) {
             rp->list->reass_execute_ctx = rp->pkt;
         }
@@ -1237,7 +1245,7 @@  ipf_preprocess_conntrack(struct ipf *ipf, struct dp_packet_batch *pb,
     }
 
     if (ipf_get_enabled(ipf) || atomic_count_get(&ipf->nfrag)) {
-        ipf_execute_reass_pkts(ipf, pb);
+        ipf_execute_reass_pkts(ipf, pb, dl_type);
     }
 }