From 08879ea7fbb9d17ec3d057d6fd3e0a6950edd0cf Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 12 Oct 2023 15:49:00 +0200 Subject: [PATCH] net: ip: Add option to force checksum calculation Modify internal L4 protocols APIs, to allow to enforce checksum calculation, regardless of the checksum HW offloading capability. Signed-off-by: Robert Lubos --- subsys/net/ip/icmpv4.c | 4 ++-- subsys/net/ip/icmpv4.h | 2 +- subsys/net/ip/icmpv6.c | 4 ++-- subsys/net/ip/icmpv6.h | 2 +- subsys/net/ip/ipv4.c | 6 +++--- subsys/net/ip/ipv6.c | 6 +++--- subsys/net/ip/tcp.c | 4 ++-- subsys/net/ip/tcp.h | 2 +- subsys/net/ip/tcp_internal.h | 5 +++-- subsys/net/ip/udp.c | 4 ++-- subsys/net/ip/udp_internal.h | 5 +++-- tests/net/ipv4_fragment/src/main.c | 6 +++--- tests/net/ipv6_fragment/src/main.c | 4 ++-- 13 files changed, 28 insertions(+), 26 deletions(-) diff --git a/subsys/net/ip/icmpv4.c b/subsys/net/ip/icmpv4.c index 205ca562754..8bab97d9cfc 100644 --- a/subsys/net/ip/icmpv4.c +++ b/subsys/net/ip/icmpv4.c @@ -47,7 +47,7 @@ int net_icmpv4_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code) return net_pkt_set_data(pkt, &icmpv4_access); } -int net_icmpv4_finalize(struct net_pkt *pkt) +int net_icmpv4_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access, struct net_icmp_hdr); @@ -65,7 +65,7 @@ int net_icmpv4_finalize(struct net_pkt *pkt) } icmp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { icmp_hdr->chksum = net_calc_chksum_icmpv4(pkt); net_pkt_set_chksum_done(pkt, true); } diff --git a/subsys/net/ip/icmpv4.h b/subsys/net/ip/icmpv4.h index b9680c44b34..ae848c9d964 100644 --- a/subsys/net/ip/icmpv4.h +++ b/subsys/net/ip/icmpv4.h @@ -48,7 +48,7 @@ enum net_verdict net_icmpv4_input(struct net_pkt *pkt, struct net_ipv4_hdr *ip_hdr); int net_icmpv4_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code); -int net_icmpv4_finalize(struct net_pkt *pkt); +int net_icmpv4_finalize(struct net_pkt *pkt, bool force_chksum); void net_icmpv4_init(void); #else diff --git a/subsys/net/ip/icmpv6.c b/subsys/net/ip/icmpv6.c index 6b436139d1a..c04e3dddf72 100644 --- a/subsys/net/ip/icmpv6.c +++ b/subsys/net/ip/icmpv6.c @@ -57,7 +57,7 @@ const char *net_icmpv6_type2str(int icmpv6_type) return "?"; } -int net_icmpv6_finalize(struct net_pkt *pkt) +int net_icmpv6_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, struct net_icmp_hdr); @@ -69,7 +69,7 @@ int net_icmpv6_finalize(struct net_pkt *pkt) } icmp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { icmp_hdr->chksum = net_calc_chksum_icmpv6(pkt); net_pkt_set_chksum_done(pkt, true); } diff --git a/subsys/net/ip/icmpv6.h b/subsys/net/ip/icmpv6.h index 967111955f3..64ee1dfaa7b 100644 --- a/subsys/net/ip/icmpv6.h +++ b/subsys/net/ip/icmpv6.h @@ -188,7 +188,7 @@ enum net_verdict net_icmpv6_input(struct net_pkt *pkt, struct net_ipv6_hdr *ip_hdr); int net_icmpv6_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code); -int net_icmpv6_finalize(struct net_pkt *pkt); +int net_icmpv6_finalize(struct net_pkt *pkt, bool force_chksum); void net_icmpv6_init(void); #else diff --git a/subsys/net/ip/ipv4.c b/subsys/net/ip/ipv4.c index 922068274f7..ce5c1e9986c 100644 --- a/subsys/net/ip/ipv4.c +++ b/subsys/net/ip/ipv4.c @@ -118,12 +118,12 @@ int net_ipv4_finalize(struct net_pkt *pkt, uint8_t next_header_proto) if (IS_ENABLED(CONFIG_NET_UDP) && next_header_proto == IPPROTO_UDP) { - return net_udp_finalize(pkt); + return net_udp_finalize(pkt, false); } else if (IS_ENABLED(CONFIG_NET_TCP) && next_header_proto == IPPROTO_TCP) { - return net_tcp_finalize(pkt); + return net_tcp_finalize(pkt, false); } else if (next_header_proto == IPPROTO_ICMP) { - return net_icmpv4_finalize(pkt); + return net_icmpv4_finalize(pkt, false); } return 0; diff --git a/subsys/net/ip/ipv6.c b/subsys/net/ip/ipv6.c index 7ef75831406..4957f1cb557 100644 --- a/subsys/net/ip/ipv6.c +++ b/subsys/net/ip/ipv6.c @@ -120,12 +120,12 @@ int net_ipv6_finalize(struct net_pkt *pkt, uint8_t next_header_proto) if (IS_ENABLED(CONFIG_NET_UDP) && next_header_proto == IPPROTO_UDP) { - return net_udp_finalize(pkt); + return net_udp_finalize(pkt, false); } else if (IS_ENABLED(CONFIG_NET_TCP) && next_header_proto == IPPROTO_TCP) { - return net_tcp_finalize(pkt); + return net_tcp_finalize(pkt, false); } else if (next_header_proto == IPPROTO_ICMPV6) { - return net_icmpv6_finalize(pkt); + return net_icmpv6_finalize(pkt, false); } return 0; diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 253004c4e1f..6ec7745c952 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -3583,7 +3583,7 @@ int net_tcp_recv(struct net_context *context, net_context_recv_cb_t cb, return 0; } -int net_tcp_finalize(struct net_pkt *pkt) +int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr); struct net_tcp_hdr *tcp_hdr; @@ -3595,7 +3595,7 @@ int net_tcp_finalize(struct net_pkt *pkt) tcp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { tcp_hdr->chksum = net_calc_chksum_tcp(pkt); net_pkt_set_chksum_done(pkt, true); } diff --git a/subsys/net/ip/tcp.h b/subsys/net/ip/tcp.h index f6f481d5443..77d5c5634a6 100644 --- a/subsys/net/ip/tcp.h +++ b/subsys/net/ip/tcp.h @@ -113,7 +113,7 @@ void net_tcp_init(void); #endif int net_tcp_update_recv_wnd(struct net_context *context, int32_t delta); int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt); -int net_tcp_finalize(struct net_pkt *pkt); +int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum); #if defined(CONFIG_NET_TEST_PROTOCOL) /** diff --git a/subsys/net/ip/tcp_internal.h b/subsys/net/ip/tcp_internal.h index 42752060092..49edae13f68 100644 --- a/subsys/net/ip/tcp_internal.h +++ b/subsys/net/ip/tcp_internal.h @@ -249,11 +249,12 @@ static inline int net_tcp_recv(struct net_context *context, * @return 0 on success, negative errno otherwise. */ #if defined(CONFIG_NET_NATIVE_TCP) -int net_tcp_finalize(struct net_pkt *pkt); +int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum); #else -static inline int net_tcp_finalize(struct net_pkt *pkt) +static inline int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum) { ARG_UNUSED(pkt); + ARG_UNUSED(force_chksum); return 0; } #endif diff --git a/subsys/net/ip/udp.c b/subsys/net/ip/udp.c index 858c046b907..5ecc595053b 100644 --- a/subsys/net/ip/udp.c +++ b/subsys/net/ip/udp.c @@ -35,7 +35,7 @@ int net_udp_create(struct net_pkt *pkt, uint16_t src_port, uint16_t dst_port) return net_pkt_set_data(pkt, &udp_access); } -int net_udp_finalize(struct net_pkt *pkt) +int net_udp_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr); struct net_udp_hdr *udp_hdr; @@ -51,7 +51,7 @@ int net_udp_finalize(struct net_pkt *pkt) udp_hdr->len = htons(length); - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { udp_hdr->chksum = net_calc_chksum_udp(pkt); net_pkt_set_chksum_done(pkt, true); } diff --git a/subsys/net/ip/udp_internal.h b/subsys/net/ip/udp_internal.h index 94106d60010..00009177d0b 100644 --- a/subsys/net/ip/udp_internal.h +++ b/subsys/net/ip/udp_internal.h @@ -63,11 +63,12 @@ static inline int net_udp_create(struct net_pkt *pkt, * @return 0 on success, negative errno otherwise. */ #if defined(CONFIG_NET_NATIVE_UDP) -int net_udp_finalize(struct net_pkt *pkt); +int net_udp_finalize(struct net_pkt *pkt, bool force_chksum); #else -static inline int net_udp_finalize(struct net_pkt *pkt) +static inline int net_udp_finalize(struct net_pkt *pkt, bool force_chksum) { ARG_UNUSED(pkt); + ARG_UNUSED(force_chksum); return 0; } diff --git a/tests/net/ipv4_fragment/src/main.c b/tests/net/ipv4_fragment/src/main.c index 4db5b877d4f..7375aab17aa 100644 --- a/tests/net/ipv4_fragment/src/main.c +++ b/tests/net/ipv4_fragment/src/main.c @@ -636,7 +636,7 @@ ZTEST(net_ipv4_fragment, test_udp) net_pkt_cursor_init(pkt); net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt)); - net_udp_finalize(pkt); + net_udp_finalize(pkt, false); pkt_recv_expected_size = net_pkt_get_len(pkt); @@ -706,7 +706,7 @@ ZTEST(net_ipv4_fragment, test_tcp) net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt)); - net_tcp_finalize(pkt); + net_tcp_finalize(pkt, false); pkt_recv_expected_size = net_pkt_get_len(pkt); @@ -849,7 +849,7 @@ ZTEST(net_ipv4_fragment, test_do_not_fragment) net_pkt_cursor_init(pkt); net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt)); - net_udp_finalize(pkt); + net_udp_finalize(pkt, false); pkt_recv_expected_size = net_pkt_get_len(pkt); diff --git a/tests/net/ipv6_fragment/src/main.c b/tests/net/ipv6_fragment/src/main.c index 890ddc32b57..adb8652bdc1 100644 --- a/tests/net/ipv6_fragment/src/main.c +++ b/tests/net/ipv6_fragment/src/main.c @@ -2015,7 +2015,7 @@ ZTEST(net_ipv6_fragment, test_send_ipv6_fragment) net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt)); - net_udp_finalize(pkt); + net_udp_finalize(pkt, false); test_failed = false; test_complete = false; @@ -2175,7 +2175,7 @@ ZTEST(net_ipv6_fragment, test_send_ipv6_fragment_udp_loopback) net_pkt_set_overwrite(pkt, true); net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt)); - net_udp_finalize(pkt); + net_udp_finalize(pkt, false); test_failed = false; test_complete = false;