IP reassembly must not accept data past an MF=0 fragment.  Track
last fragments, reject ranges beyond them on insert, and require the
sorted rightmost fragment to be MF=0 before completing a list.

An exact duplicate that carries the last-fragment (MF=0) flag records that
flag on the stored copy and re-runs the state transition, matching the
Linux kernel, so a datagram whose only MF=0 fragment arrives as a duplicate
can still complete.

The accompanying tests are added to tests/ofproto-dpif.at (using
netdev-dummy/receive with variable-built packets and precomputed IPv4
header checksums) rather than the system-traffic suite.

Assisted-by: composer-2.5-fast, Cursor
Fixes: 4ea96698f667 ("Userspace datapath: Add fragmentation handling.")
Signed-off-by: Eli Britstein <[email protected]>
---
 lib/dpctl.c                      |   4 +
 lib/dpif-provider.h              |   1 +
 lib/ipf.c                        |  71 ++++++++-
 lib/ipf.h                        |   1 +
 tests/ofproto-dpif.at            | 247 +++++++++++++++++++++++++++++++
 tests/system-userspace-macros.at |   8 +
 6 files changed, 327 insertions(+), 5 deletions(-)

diff --git a/lib/dpctl.c b/lib/dpctl.c
index dc3b68c01..d117e3d56 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -2633,6 +2633,8 @@ dpctl_ct_ipf_get_status(int argc, const char *argv[],
                         dpif_ipf_status.v4.nfrag_duplicate);
             dpctl_print(dpctl_p, "        v4 frags discarded: %"PRIu64"\n",
                         dpif_ipf_status.v4.nfrag_discarded);
+            dpctl_print(dpctl_p, "        v4 frags beyond last: %"PRIu64"\n",
+                        dpif_ipf_status.v4.nfrag_beyond_last);
             dpctl_print(dpctl_p, "        v4 frags purged: %"PRIu64"\n",
                         dpif_ipf_status.v4.nfrag_purged);
 
@@ -2654,6 +2656,8 @@ dpctl_ct_ipf_get_status(int argc, const char *argv[],
                         dpif_ipf_status.v6.nfrag_duplicate);
             dpctl_print(dpctl_p, "        v6 frags discarded: %"PRIu64"\n",
                         dpif_ipf_status.v6.nfrag_discarded);
+            dpctl_print(dpctl_p, "        v6 frags beyond last: %"PRIu64"\n",
+                        dpif_ipf_status.v6.nfrag_beyond_last);
             dpctl_print(dpctl_p, "        v6 frags purged: %"PRIu64"\n",
                         dpif_ipf_status.v6.nfrag_purged);
         } else {
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index f418327df..e1998151c 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -133,6 +133,7 @@ struct dpif_ipf_proto_status {
    uint64_t nfrag_overlap;
    uint64_t nfrag_duplicate;
    uint64_t nfrag_discarded;
+   uint64_t nfrag_beyond_last;
    uint64_t nfrag_purged;
    unsigned int min_frag_size;
    bool enabled;
diff --git a/lib/ipf.c b/lib/ipf.c
index 87ff5b4b9..2da6b9dc9 100644
--- a/lib/ipf.c
+++ b/lib/ipf.c
@@ -86,6 +86,7 @@ enum ipf_counter_type {
     IPF_NFRAGS_OVERLAP,
     IPF_NFRAGS_DUPLICATE,
     IPF_NFRAGS_DISCARDED,
+    IPF_NFRAGS_BEYOND_LAST,
     IPF_NFRAGS_PURGED,
     IPF_NFRAGS_NUM_CNTS,
 };
@@ -100,6 +101,7 @@ struct ipf_frag {
     struct dp_packet *pkt;
     uint16_t start_data_byte;
     uint16_t end_data_byte;
+    bool last_frag;                /* True if this was the MF=0 fragment. */
 };
 
 /* The key for a collection of fragments potentially making up an unfragmented
@@ -399,8 +401,14 @@ ipf_list_complete(const struct ipf_list *ipf_list)
             != ipf_list->frag_list[i].start_data_byte) {
             return false;
         }
+
+        /* Only the final fragment may have MF=0; data past it is invalid. */
+        if (ipf_list->frag_list[i - 1].last_frag) {
+            return false;
+        }
     }
-    return true;
+
+    return ipf_list->frag_list[ipf_list->last_inuse_idx].last_frag;
 }
 
 /* Runs O(n) for a sorted or almost sorted list. */
@@ -896,6 +904,30 @@ ipf_is_frag_overlap(const struct ipf_frag *frag_list, int 
last_inuse_idx,
     return false;
 }
 
+/* Returns true if accepting this fragment would place data past an MF=0
+ * (last) fragment.  The last fragment fixes the datagram's total length, so
+ * any octet at a higher offset is invalid per the IPv4 (RFC 791) and IPv6
+ * (RFC 8200, Section 4.5) reassembly procedures. */
+static bool
+ipf_is_beyond_last_frag(const struct ipf_frag *frag_list, int last_inuse_idx,
+                        uint16_t start_data_byte, uint16_t end_data_byte,
+                        bool lf)
+    /* OVS_REQUIRES(ipf_lock) */
+{
+    for (int i = 0; i <= last_inuse_idx; i++) {
+        if (frag_list[i].last_frag
+            && start_data_byte > frag_list[i].end_data_byte) {
+            return true;
+        }
+
+        if (lf && frag_list[i].end_data_byte > end_data_byte) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 /* Drops the entire fragment list: deletes every fragment packet held by the
  * list and removes the list from the tracking datastructures.  Per RFC 5722
  * and RFC 8200, when an overlapping fragment is detected the whole datagram
@@ -916,7 +948,9 @@ ipf_drop_frag_chain(struct ipf *ipf, struct ipf_list 
*ipf_list, bool v6)
 /* Adds a fragment to a list of fragments.  An exact duplicate fragment is
  * dropped on its own, keeping the rest of the list (RFC 8200).  An
  * overlapping (but not duplicate) fragment causes the whole fragment list to
- * be dropped (see ipf_drop_frag_chain(), RFC 5722 / RFC 8200). */
+ * be dropped (see ipf_drop_frag_chain(), RFC 5722 / RFC 8200).  A fragment
+ * with data beyond an already seen last (MF=0) fragment is dropped on its own
+ * (RFC 791 / RFC 8200). */
 static bool
 ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list,
                  struct dp_packet *pkt, uint16_t start_data_byte,
@@ -928,14 +962,17 @@ ipf_process_frag(struct ipf *ipf, struct ipf_list 
*ipf_list,
         ipf_list->last_inuse_idx, start_data_byte, end_data_byte);
     bool overlap_frag = ipf_is_frag_overlap(ipf_list->frag_list,
         ipf_list->last_inuse_idx, start_data_byte, end_data_byte);
+    bool beyond_last = ipf_is_beyond_last_frag(ipf_list->frag_list,
+        ipf_list->last_inuse_idx, start_data_byte, end_data_byte, lf);
     int last_inuse_idx = ipf_list->last_inuse_idx;
 
-    if (!duped_frag && !overlap_frag) {
+    if (!duped_frag && !overlap_frag && !beyond_last) {
         if (last_inuse_idx < ipf_list->size - 1) {
             struct ipf_frag *frag = &ipf_list->frag_list[last_inuse_idx + 1];
             frag->pkt = pkt;
             frag->start_data_byte = start_data_byte;
             frag->end_data_byte = end_data_byte;
+            frag->last_frag = lf;
             ipf_list->last_inuse_idx++;
             atomic_count_inc(&ipf->nfrag);
             ipf_count(ipf, v6, IPF_NFRAGS_ACCEPTED);
@@ -945,14 +982,34 @@ ipf_process_frag(struct ipf *ipf, struct ipf_list 
*ipf_list,
         }
     } else if (duped_frag) {
         /* RFC 8200: an exact duplicate may be dropped while keeping the rest
-         * of the fragment list for later reassembly. */
+         * of the fragment list for later reassembly.  If it is the last
+         * fragment and the stored copy was not marked last, record it so the
+         * datagram can complete. */
         ipf_count(ipf, v6, IPF_NFRAGS_DUPLICATE);
+        if (lf) {
+            struct ipf_frag *frag_list = ipf_list->frag_list;
+
+            for (int i = 0; i <= ipf_list->last_inuse_idx; i++) {
+                if (start_data_byte == frag_list[i].start_data_byte &&
+                    end_data_byte == frag_list[i].end_data_byte &&
+                    !frag_list[i].last_frag) {
+                    frag_list[i].last_frag = true;
+                    *rp = ipf_list_state_transition(ipf, ipf_list, ff, lf, v6);
+                    break;
+                }
+            }
+        }
+
         dp_packet_delete(pkt);
-    } else {
+    } else if (overlap_frag) {
         ipf_count(ipf, v6, IPF_NFRAGS_OVERLAP);
         dp_packet_delete(pkt);
         ipf_drop_frag_chain(ipf, ipf_list, v6);
+    } else {
+        ipf_count(ipf, v6, IPF_NFRAGS_BEYOND_LAST);
+        dp_packet_delete(pkt);
     }
+
     return true;
 }
 
@@ -1551,6 +1608,8 @@ ipf_get_status(struct ipf *ipf, struct ipf_status 
*ipf_status)
                         &ipf_status->v4.nfrag_duplicate);
     atomic_read_relaxed(&ipf->n4frag_cnt[IPF_NFRAGS_DISCARDED],
                         &ipf_status->v4.nfrag_discarded);
+    atomic_read_relaxed(&ipf->n4frag_cnt[IPF_NFRAGS_BEYOND_LAST],
+                        &ipf_status->v4.nfrag_beyond_last);
     atomic_read_relaxed(&ipf->n4frag_cnt[IPF_NFRAGS_PURGED],
                         &ipf_status->v4.nfrag_purged);
 
@@ -1573,6 +1632,8 @@ ipf_get_status(struct ipf *ipf, struct ipf_status 
*ipf_status)
                         &ipf_status->v6.nfrag_duplicate);
     atomic_read_relaxed(&ipf->n6frag_cnt[IPF_NFRAGS_DISCARDED],
                         &ipf_status->v6.nfrag_discarded);
+    atomic_read_relaxed(&ipf->n6frag_cnt[IPF_NFRAGS_BEYOND_LAST],
+                        &ipf_status->v6.nfrag_beyond_last);
     atomic_read_relaxed(&ipf->n6frag_cnt[IPF_NFRAGS_PURGED],
                         &ipf_status->v6.nfrag_purged);
     return 0;
diff --git a/lib/ipf.h b/lib/ipf.h
index c8aec5a5a..0093372de 100644
--- a/lib/ipf.h
+++ b/lib/ipf.h
@@ -31,6 +31,7 @@ struct ipf_proto_status {
    uint64_t nfrag_overlap;
    uint64_t nfrag_duplicate;
    uint64_t nfrag_discarded;
+   uint64_t nfrag_beyond_last;
    uint64_t nfrag_purged;
    unsigned int min_frag_size;
    bool enabled;
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 04ac3f446..ac009408a 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -5851,6 +5851,253 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status -m \
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto-dpif - fragment handling - reject fragment beyond last])
+OVS_VSWITCHD_START
+add_of_ports br0 1 90
+
+AT_DATA([flows.txt], [dnl
+table=0 in_port=90,ip actions=ct(commit),output:1
+])
+AT_CHECK([ovs-ofctl -O OpenFlow11 replace-flows br0 flows.txt])
+
+dnl The minimum fragment size is clamped to 400 bytes, so a non-last fragment
+dnl must be at least that large to be admitted for reassembly.
+AT_CHECK([ovs-appctl dpctl/ipf-set-min-frag v4 400], [], [dnl
+setting minimum fragment size successful
+])
+
+dnl First admit a last (MF=0) fragment carrying bytes 400..799, then reject a
+dnl new fragment carrying bytes 800..1199, whose data lies entirely beyond the
+dnl end of the last fragment and so must not be reassembled.
+dnl
+dnl Packet 1 (admitted).  Last fragment carrying bytes 400..799 (MF clear).
+dnl   Ethernet II, Src: 50:54:00:00:00:09, Dst: 50:54:00:00:00:0a
+dnl       Type: IPv4 (0x0800)
+dnl   Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
+dnl       0100 .... = Version: 4
+dnl       .... 0101 = Header Length: 20 bytes (5)
+dnl       Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
+dnl       Total Length: 420
+dnl       Identification: 0x0020 (32)
+dnl       000. .... = Flags: 0x0 (Last fragment)
+dnl       ...0 0000 0011 0010 = Fragment Offset: 400
+dnl       Time to Live: 64
+dnl       Protocol: UDP (17)
+dnl       Header Checksum: 0x62f3
+dnl   Data (400 bytes)
+eth="50 54 00 00 00 0a 50 54 00 00 00 09 08 00"
+ip1="45 00 01 a4 00 20 00 32 40 11 62 f3"
+addrs="0a 01 01 01 0a 01 01 02"
+data1=$(printf '%0*d' 800 0)
+packet1="${eth}${ip1}${addrs}${data1}"
+
+dnl Packet 2 (rejected as beyond last).  Fragment carrying bytes 800..1199
+dnl (MF set), starting past packet 1's last-fragment end.
+dnl   Ethernet II, Src: 50:54:00:00:00:09, Dst: 50:54:00:00:00:0a
+dnl       Type: IPv4 (0x0800)
+dnl   Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
+dnl       0100 .... = Version: 4
+dnl       .... 0101 = Header Length: 20 bytes (5)
+dnl       Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
+dnl       Total Length: 420
+dnl       Identification: 0x0020 (32)
+dnl       001. .... = Flags: 0x1 (More fragments)
+dnl       ...0 0000 0110 0100 = Fragment Offset: 800
+dnl       Time to Live: 64
+dnl       Protocol: UDP (17)
+dnl       Header Checksum: 0x42c1
+dnl   Data (400 bytes)
+ip2="45 00 01 a4 00 20 20 64 40 11 42 c1"
+data2=$(printf '%0*d' 800 0)
+packet2="${eth}${ip2}${addrs}${data2}"
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet1"])
+AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet2"])
+
+AT_CHECK([ovs-appctl dpctl/ipf-get-status -m \
+| grep -E 'num frag:|v4 frags accepted:|v4 frags completed:|v4 frags beyond 
last:'], [], [dnl
+        num frag: 1
+        v4 frags accepted: 1
+        v4 frags completed: 0
+        v4 frags beyond last: 1
+])
+
+dnl The rejected fragment left the last (MF=0) fragment queued.  Send the
+dnl missing first fragment, bytes 0..399 (MF set), and confirm the retained
+dnl list reassembles.
+dnl
+dnl Packet 3 (admitted).  First fragment carrying bytes 0..399 (MF set).
+dnl   Ethernet II, Src: 50:54:00:00:00:09, Dst: 50:54:00:00:00:0a
+dnl       Type: IPv4 (0x0800)
+dnl   Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
+dnl       0100 .... = Version: 4
+dnl       .... 0101 = Header Length: 20 bytes (5)
+dnl       Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
+dnl       Total Length: 420
+dnl       Identification: 0x0020 (32)
+dnl       001. .... = Flags: 0x1 (More fragments)
+dnl       ...0 0000 0000 0000 = Fragment Offset: 0
+dnl       Time to Live: 64
+dnl       Protocol: UDP (17)
+dnl       Header Checksum: 0x4325
+dnl   Data (400 bytes)
+ip3="45 00 01 a4 00 20 20 00 40 11 43 25"
+data3=$(printf '%0*d' 800 0)
+packet3="${eth}${ip3}${addrs}${data3}"
+AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet3"])
+
+AT_CHECK([ovs-appctl dpctl/ipf-get-status -m \
+| grep -E 'num frag:|v4 frags accepted:|v4 frags completed:|v4 frags beyond 
last:'], [], [dnl
+        num frag: 0
+        v4 frags accepted: 2
+        v4 frags completed: 2
+        v4 frags beyond last: 1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - fragment handling - reject fragment beyond last, last 
seen second])
+OVS_VSWITCHD_START
+add_of_ports br0 1 90
+
+AT_DATA([flows.txt], [dnl
+table=0 in_port=90,ip actions=ct(commit),output:1
+])
+AT_CHECK([ovs-ofctl -O OpenFlow11 replace-flows br0 flows.txt])
+
+AT_CHECK([ovs-appctl dpctl/ipf-set-min-frag v4 400], [], [dnl
+setting minimum fragment size successful
+])
+
+dnl First admit a non-last fragment carrying bytes 800..1199 (MF set), then
+dnl reject a last (MF=0) fragment carrying bytes 400..799, whose end lies
+dnl before the already queued fragment and so leaves data beyond the last.
+eth="50 54 00 00 00 0a 50 54 00 00 00 09 08 00"
+addrs="0a 01 01 01 0a 01 01 02"
+
+dnl Packet 1 (admitted).  Fragment carrying bytes 800..1199 (MF set).
+dnl   Ethernet II, Src: 50:54:00:00:00:09, Dst: 50:54:00:00:00:0a
+dnl       Type: IPv4 (0x0800)
+dnl   Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
+dnl       0100 .... = Version: 4
+dnl       .... 0101 = Header Length: 20 bytes (5)
+dnl       Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
+dnl       Total Length: 420
+dnl       Identification: 0x0020 (32)
+dnl       001. .... = Flags: 0x1 (More fragments)
+dnl       ...0 0000 0110 0100 = Fragment Offset: 800
+dnl       Time to Live: 64
+dnl       Protocol: UDP (17)
+dnl       Header Checksum: 0x42c1
+dnl   Data (400 bytes)
+ip1="45 00 01 a4 00 20 20 64 40 11 42 c1"
+data1=$(printf '%0*d' 800 0)
+packet1="${eth}${ip1}${addrs}${data1}"
+
+dnl Packet 2 (rejected as beyond last).  Last fragment carrying bytes
+dnl 400..799 (MF clear), ending before packet 1.
+dnl   Ethernet II, Src: 50:54:00:00:00:09, Dst: 50:54:00:00:00:0a
+dnl       Type: IPv4 (0x0800)
+dnl   Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
+dnl       0100 .... = Version: 4
+dnl       .... 0101 = Header Length: 20 bytes (5)
+dnl       Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
+dnl       Total Length: 420
+dnl       Identification: 0x0020 (32)
+dnl       000. .... = Flags: 0x0 (Last fragment)
+dnl       ...0 0000 0011 0010 = Fragment Offset: 400
+dnl       Time to Live: 64
+dnl       Protocol: UDP (17)
+dnl       Header Checksum: 0x62f3
+dnl   Data (400 bytes)
+ip2="45 00 01 a4 00 20 00 32 40 11 62 f3"
+data2=$(printf '%0*d' 800 0)
+packet2="${eth}${ip2}${addrs}${data2}"
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet1"])
+AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet2"])
+
+AT_CHECK([ovs-appctl dpctl/ipf-get-status -m \
+| grep -E 'num frag:|v4 frags accepted:|v4 frags completed:|v4 frags beyond 
last:'], [], [dnl
+        num frag: 1
+        v4 frags accepted: 1
+        v4 frags completed: 0
+        v4 frags beyond last: 1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - fragment handling - reject fragment beyond last - 
IPv6])
+OVS_VSWITCHD_START
+add_of_ports br0 1 90
+
+AT_DATA([flows.txt], [dnl
+table=0 in_port=90,ipv6 actions=ct(commit),output:1
+])
+AT_CHECK([ovs-ofctl -O OpenFlow11 replace-flows br0 flows.txt])
+
+AT_CHECK([ovs-appctl dpctl/ipf-set-min-frag v6 400], [], [dnl
+setting minimum fragment size successful
+])
+
+dnl First admit a last fragment carrying bytes 400..799 (M clear), then reject
+dnl a new fragment carrying bytes 800..1199 (M set), whose data lies beyond the
+dnl end of the last fragment.  The IPv6 fragment header holds the next header
+dnl (UDP), the fragment offset in 8-byte units with the M flag, and the
+dnl identification.
+dnl   Ethernet II, Src: 50:54:00:00:00:09, Dst: 50:54:00:00:00:0a
+dnl       Type: IPv6 (0x86dd)
+dnl   Internet Protocol Version 6, Src: 2001:db8::1, Dst: 2001:db8::2
+dnl       0110 .... = Version: 6
+dnl       Payload Length: 408
+dnl       Next Header: Fragment Header for IPv6 (44)
+dnl       Hop Limit: 64
+eth="50 54 00 00 00 0a 50 54 00 00 00 09 86 dd"
+ip6="60 00 00 00 01 98 2c 40 dnl
+20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 01 dnl
+20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 02"
+
+dnl Packet 1 (admitted).  Last fragment carrying bytes 400..799 (M clear).
+dnl   Fragment Header for IPv6
+dnl       Next Header: UDP (17)
+dnl       Reserved: 0x00
+dnl       0000 0001 1001 0... = Offset: 400 (0x190)
+dnl       .... .... .... .000 = Reserved bits / M flag: 0 (last fragment)
+dnl       Identification: 0x00000020
+dnl   Data (400 bytes)
+frag1="11 00 01 90 00 00 00 20"
+data1=$(printf '%0*d' 800 0)
+packet1="${eth}${ip6}${frag1}${data1}"
+
+dnl Packet 2 (rejected as beyond last).  Fragment carrying bytes 800..1199
+dnl (M set), starting past packet 1's last-fragment end.
+dnl   Fragment Header for IPv6
+dnl       Next Header: UDP (17)
+dnl       Reserved: 0x00
+dnl       0000 0011 0010 0... = Offset: 800 (0x320)
+dnl       .... .... .... .001 = More Fragments: 1
+dnl       Identification: 0x00000020
+dnl   Data (400 bytes)
+frag2="11 00 03 21 00 00 00 20"
+data2=$(printf '%0*d' 800 0)
+packet2="${eth}${ip6}${frag2}${data2}"
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet1"])
+AT_CHECK([ovs-appctl netdev-dummy/receive p90 "$packet2"])
+
+AT_CHECK([ovs-appctl dpctl/ipf-get-status -m \
+| grep -E 'num frag:|v6 frags accepted:|v6 frags completed:|v6 frags beyond 
last:'], [], [dnl
+        num frag: 1
+        v6 frags accepted: 1
+        v6 frags completed: 0
+        v6 frags beyond last: 1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto-dpif - handling of malformed TCP packets])
 OVS_VSWITCHD_START
 add_of_ports br0 1 90
diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at
index 1358d7156..20e9ce475 100644
--- a/tests/system-userspace-macros.at
+++ b/tests/system-userspace-macros.at
@@ -182,6 +182,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status], [], [dnl
         v4 frags overlapped: 0
         v4 frags duplicate: 0
         v4 frags discarded: 0
+        v4 frags beyond last: 0
         v4 frags purged: 0
         min v6 frag size: 1280
         v6 frags accepted: 0
@@ -192,6 +193,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status], [], [dnl
         v6 frags overlapped: 0
         v6 frags duplicate: 0
         v6 frags discarded: 0
+        v6 frags beyond last: 0
         v6 frags purged: 0
 ])
 ])
@@ -218,6 +220,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status --more], [], [dnl
         v4 frags overlapped: 0
         v4 frags duplicate: 0
         v4 frags discarded: 0
+        v4 frags beyond last: 0
         v4 frags purged: 0
         min v6 frag size: 1280
         v6 frags accepted: 0
@@ -228,6 +231,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status --more], [], [dnl
         v6 frags overlapped: 0
         v6 frags duplicate: 0
         v6 frags discarded: 0
+        v6 frags beyond last: 0
         v6 frags purged: 0
 
         Fragment Lists:
@@ -257,6 +261,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status --more], [], [dnl
         v4 frags overlapped: 0
         v4 frags duplicate: 0
         v4 frags discarded: 0
+        v4 frags beyond last: 0
         v4 frags purged: 0
         min v6 frag size: 1280
         v6 frags accepted: 30
@@ -267,6 +272,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status --more], [], [dnl
         v6 frags overlapped: 0
         v6 frags duplicate: 0
         v6 frags discarded: 0
+        v6 frags beyond last: 0
         v6 frags purged: 0
 
         Fragment Lists:
@@ -303,6 +309,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status -m | 
FORMAT_FRAG_LIST()], [], [dnl
         v4 frags overlapped: 0
         v4 frags duplicate: 0
         v4 frags discarded: 0
+        v4 frags beyond last: 0
         v4 frags purged: 0
         min v6 frag size: 1280
         v6 frags accepted: 0
@@ -313,6 +320,7 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status -m | 
FORMAT_FRAG_LIST()], [], [dnl
         v6 frags overlapped: 0
         v6 frags duplicate: 0
         v6 frags discarded: 0
+        v6 frags beyond last: 0
         v6 frags purged: 0
 
         Fragment Lists:
-- 
2.43.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to