ip_forward: fix IPv4 forwarding with multiple netifs/offloading

When we have multiple netifs where at least one has checksum offloading
capabilities, IP forwarding needs to set various checksum fields to 0
to prevent HW algorithms on calculating an invalid checksum.

-> set checksum fields of IP/UDP/TCP/ICMP to 0 in ip4_forward().

See bug #56288

Signed-off-by: Simon Goldschmidt <goldsimon@gmx.de>
This commit is contained in:
Simon Goldschmidt 2020-01-30 23:02:16 +01:00
parent 695c323164
commit 61c67fc229
2 changed files with 34 additions and 1 deletions

View File

@ -336,6 +336,37 @@ ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
IPH_CHKSUM_SET(iphdr, (u16_t)(IPH_CHKSUM(iphdr) + PP_HTONS(0x100)));
}
/* Take care of setting checksums to 0 for checksum offload netifs */
if (CHECKSUM_GEN_IP || NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP)) {
IPH_CHKSUM_SET(iphdr, 0);
}
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP
#if LWIP_UDPLITE
case IP_PROTO_UDPLITE:
#endif
case IP_PROTO_UDP:
if (CHECKSUM_GEN_UDP || NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_UDP)) {
((struct udp_hdr *)((const u8_t *)iphdr + IPH_HL_BYTES(iphdr)))->chksum = 0;
}
break;
#endif
#if LWIP_TCP
case IP_PROTO_TCP:
if (CHECKSUM_GEN_TCP || NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_TCP)) {
((struct tcp_hdr *)((const u8_t *)iphdr + IPH_HL_BYTES(iphdr)))->chksum = 0;
}
break;
#endif
#if LWIP_ICMP
case IP_PROTO_ICMP:
if (CHECKSUM_GEN_ICMP || NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP)) {
((struct icmp_hdr *)((const u8_t *)iphdr + IPH_HL_BYTES(iphdr)))->chksum = 0;
}
break;
#endif
}
LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()),
ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr())));

View File

@ -404,8 +404,10 @@ struct netif {
#if LWIP_CHECKSUM_CTRL_PER_NETIF
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \
(netif)->chksum_flags = chksumflags; } while(0)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0))
#define NETIF_CHECKSUM_ENABLED(netif, chksumflag) (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0))
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if NETIF_CHECKSUM_ENABLED(netif, chksumflag)
#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */
#define NETIF_CHECKSUM_ENABLED(netif, chksumflag) 0
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */