On 15 Dec 2025, at 14:57, David Marchand via dev wrote:
> If we can predict that the segmented traffic will have the same headers,
> it is possible to rely on HW segmentation.
>
> TCP over IPv4 geneve (with checksum on tunnel) on a mlx5 nic:
> Before: 7.80 Gbits/sec, 100% cpu (SW segmentation)
> After: 10.8 Gbits/sec, 27% cpu (HW segmentation)
>
> For this optimisation, no touching of original tso_segsz should be
> allowed, so revert the commit
> 844a7cfa6edd ("netdev-dpdk: Use guest TSO segmentation size hint.").
>
> Yet, there might still be some non optimal cases where the L4 payload
> size would not be a multiple of tso_segsz.
> For this condition, "partially" segment: split the "last" segment and keep
> n-1 segments data in the original packet which will be segmented by HW.
>
Hi David,
Coverity reports an issue with this series. The abstract is below, and I think
a simple cast could fix the sign problemns, for example:
dp_packet_set_size(p, hdr_len +
(size_t)(n_segs - 1) * tso_segsz);
The memory access ones, I did not investigate. Could you check and send a patch
with fixes if needed?
Thanks,
Eelco
** CID 556379: (SIGN_EXTENSION)
/lib/dp-packet-gso.c: 251 in dp_packet_gso__()
/lib/dp-packet-gso.c: 238 in dp_packet_gso__()
/lib/dp-packet-gso.c: 225 in dp_packet_gso__()
/lib/dp-packet-gso.c: 239 in dp_packet_gso__()
_____________________________________________________________________________________________
*** CID 556379: (SIGN_EXTENSION)
/lib/dp-packet-gso.c: 251 in dp_packet_gso__()
245 }
246 dp_packet_batch_add(curr_batch, seg);
247
248 first_seg:
249 if (partial_seg) {
250 if (dp_packet_gso_partial_nr_segs(p) != 1) {
>>> CID 556379: (SIGN_EXTENSION)
>>> Suspicious implicit sign extension: "tso_segsz" with type "uint16_t"
>>> (16 bits, unsigned) is promoted in "(n_segs - 1) * tso_segsz" to type "int"
>>> (32 bits, signed), then sign-extended to type "unsigned long" (64 bits,
>>> unsigned). If "(n_segs - 1) * tso_segsz" is greater than 0x7FFFFFFF, the
>>> upper bits of the result will all be 1.
251 dp_packet_set_size(p, hdr_len + (n_segs - 1) * tso_segsz);
252 if (n_segs == 2) {
253 /* No need to ask HW segmentation, we already did the
job. */
254 dp_packet_set_tso_segsz(p, 0);
255 }
256 }
/lib/dp-packet-gso.c: 238 in dp_packet_gso__()
232 }
233 dp_packet_batch_add(curr_batch, seg);
234 }
235
236 last_seg:
237 /* Create the last segment. */
>>> CID 556379: (SIGN_EXTENSION)
>>> Suspicious implicit sign extension: "tso_segsz" with type "uint16_t"
>>> (16 bits, unsigned) is promoted in "(n_segs - 1) * tso_segsz" to type "int"
>>> (32 bits, signed), then sign-extended to type "unsigned long" (64 bits,
>>> unsigned). If "(n_segs - 1) * tso_segsz" is greater than 0x7FFFFFFF, the
>>> upper bits of the result will all be 1.
238 seg = dp_packet_gso_seg_new(p, hdr_len, hdr_len + (n_segs - 1) *
tso_segsz,
239 data_len - (n_segs - 1) * tso_segsz);
240 dp_packet_gso_update_segment(seg, n_segs - 1, n_segs, tso_segsz,
udp_tnl,
241 gre_tnl);
242
243 if (dp_packet_batch_is_full(curr_batch)) {
/lib/dp-packet-gso.c: 225 in dp_packet_gso__()
219 goto last_seg;
220 }
221 goto first_seg;
222 }
223
224 for (int i = 1; i < n_segs - 1; i++) {
>>> CID 556379: (SIGN_EXTENSION)
>>> Suspicious implicit sign extension: "tso_segsz" with type "uint16_t"
>>> (16 bits, unsigned) is promoted in "i * tso_segsz" to type "int" (32 bits,
>>> signed), then sign-extended to type "unsigned long" (64 bits, unsigned).
>>> If "i * tso_segsz" is greater than 0x7FFFFFFF, the upper bits of the result
>>> will all be 1.
225 seg = dp_packet_gso_seg_new(p, hdr_len, hdr_len + i * tso_segsz,
226 tso_segsz);
227 dp_packet_gso_update_segment(seg, i, n_segs, tso_segsz, udp_tnl,
228 gre_tnl);
229
230 if (dp_packet_batch_is_full(curr_batch)) {
/lib/dp-packet-gso.c: 239 in dp_packet_gso__()
233 dp_packet_batch_add(curr_batch, seg);
234 }
235
236 last_seg:
237 /* Create the last segment. */
238 seg = dp_packet_gso_seg_new(p, hdr_len, hdr_len + (n_segs - 1) *
tso_segsz,
>>> CID 556379: (SIGN_EXTENSION)
>>> Suspicious implicit sign extension: "tso_segsz" with type "uint16_t"
>>> (16 bits, unsigned) is promoted in "(n_segs - 1) * tso_segsz" to type "int"
>>> (32 bits, signed), then sign-extended to type "unsigned long" (64 bits,
>>> unsigned). If "(n_segs - 1) * tso_segsz" is greater than 0x7FFFFFFF, the
>>> upper bits of the result will all be 1.
239 data_len - (n_segs - 1) * tso_segsz);
240 dp_packet_gso_update_segment(seg, n_segs - 1, n_segs, tso_segsz,
udp_tnl,
241 gre_tnl);
242
243 if (dp_packet_batch_is_full(curr_batch)) {
244 curr_batch++;
** CID 556378: Memory - illegal accesses (OVERRUN)
_____________________________________________________________________________________________
*** CID 556378: Memory - illegal accesses (OVERRUN)
/lib/packets.c: 2154 in packet_udp_tunnel_csum()
2148
2149 inner_csum = packet_csum_pseudoheader6(inner_ip6);
2150 }
2151
2152 inner_csum = csum_continue(inner_csum, inner_l4,
2153 (char *) inner_l4_csum_p - (char *) inner_l4);
>>> CID 556378: Memory - illegal accesses (OVERRUN)
>>> Overrunning array of 2 bytes at byte offset 2 by dereferencing pointer
>>> "inner_l4_csum_p + 1".
2154 inner_l4_csum = csum_finish(csum_continue(inner_csum,
inner_l4_csum_p + 1,
2155 (char *) inner_l4_data - (char *)(inner_l4_csum_p + 1)));
2156 /* Important: for inner UDP, a null inner_l4_csum here should in
theory be
2157 * replaced with 0xffff. However, since the only use of
inner_l4_csum is
2158 * for the final outer checksum with a csum_add16() below, we can
skip this
2159 * entirely because adding 0xffff will have the same effect as
adding 0x0
** CID 556377: Memory - illegal accesses (USE_AFTER_FREE)
_____________________________________________________________________________________________
*** CID 556377: Memory - illegal accesses (USE_AFTER_FREE)
/lib/dp-packet-gso.c: 207 in dp_packet_gso__()
201 dp_packet_batch_add(curr_batch, p);
202
203 if (n_segs == 1) {
204 goto out;
205 }
206
>>> CID 556377: Memory - illegal accesses (USE_AFTER_FREE)
>>> Calling "dp_packet_tunnel" dereferences freed pointer "p".
207 if (dp_packet_tunnel(p)) {
208 hdr_len = (char *) dp_packet_get_inner_tcp_payload(p)
209 - (char *) dp_packet_eth(p);
210 data_len = dp_packet_get_inner_tcp_payload_length(p);
211 } else {
212 hdr_len = (char *) dp_packet_get_tcp_payload(p)
> Reported-at: https://issues.redhat.com/browse/FDP-1897
> Signed-off-by: David Marchand <[email protected]>
> ---
[...]
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev