summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/prox_cksum.c
diff options
context:
space:
mode:
Diffstat (limited to 'VNFs/DPPD-PROX/prox_cksum.c')
-rw-r--r--VNFs/DPPD-PROX/prox_cksum.c55
1 files changed, 38 insertions, 17 deletions
diff --git a/VNFs/DPPD-PROX/prox_cksum.c b/VNFs/DPPD-PROX/prox_cksum.c
index 9a05097e..401191f6 100644
--- a/VNFs/DPPD-PROX/prox_cksum.c
+++ b/VNFs/DPPD-PROX/prox_cksum.c
@@ -20,13 +20,23 @@
#include "log.h"
/* compute IP 16 bit checksum */
-void prox_ip_cksum_sw(struct ipv4_hdr *buf)
+/* The hdr_checksum field must be set to 0 by the caller. */
+inline void prox_ip_cksum_sw(prox_rte_ipv4_hdr *buf)
{
- const uint16_t size = sizeof(struct ipv4_hdr);
+ const uint16_t size = sizeof(prox_rte_ipv4_hdr);
uint32_t cksum = 0;
uint32_t nb_dwords;
uint32_t tail, mask;
- uint32_t *pdwd = (uint32_t *)buf;
+ /* Defining pdwd as (uint32_t *) causes some optimization issues (gcc -O2).
+ In prox_ip_cksum(), hdr_checksum is set to 0, as expected by the code below,
+ but when *pdwd is plain uint32_t, GCC does not see the pointer aliasing on
+ the IPv4 header, optimizes this hdr_checksum initialization away, and hence
+ breaks the expectations of the checksum computation loop below.
+ The following typedef tells GCC that the IPv4 header may be aliased by
+ pdwd, which prevents GCC from removing the hdr_checksum = 0 assignment.
+ */
+ typedef uint32_t __attribute__((__may_alias__)) uint32_may_alias;
+ uint32_may_alias *pdwd = (uint32_may_alias *)buf;
/* compute 16 bit checksum using hi and low parts of 32 bit integers */
for (nb_dwords = (size >> 2); nb_dwords > 0; --nb_dwords) {
@@ -52,7 +62,7 @@ void prox_ip_cksum_sw(struct ipv4_hdr *buf)
buf->hdr_checksum = ~((uint16_t)cksum);
}
-static uint16_t calc_pseudo_checksum(uint8_t ipproto, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+static inline uint16_t calc_pseudo_checksum(uint8_t ipproto, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
{
uint32_t csum = 0;
@@ -63,7 +73,7 @@ static uint16_t calc_pseudo_checksum(uint8_t ipproto, uint16_t len, uint32_t src
return csum;
}
-static void prox_write_udp_pseudo_hdr(struct udp_hdr *udp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+static inline void prox_write_udp_pseudo_hdr(prox_rte_udp_hdr *udp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
{
/* Note that the csum is not complemented, while the pseaudo
header checksum is calculated as "... the 16-bit one's
@@ -74,38 +84,42 @@ static void prox_write_udp_pseudo_hdr(struct udp_hdr *udp, uint16_t len, uint32_
udp->dgram_cksum = calc_pseudo_checksum(IPPROTO_UDP, len, src_ip_addr, dst_ip_addr);
}
-static void prox_write_tcp_pseudo_hdr(struct tcp_hdr *tcp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+static inline void prox_write_tcp_pseudo_hdr(prox_rte_tcp_hdr *tcp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
{
tcp->cksum = calc_pseudo_checksum(IPPROTO_TCP, len, src_ip_addr, dst_ip_addr);
}
-void prox_ip_udp_cksum(struct rte_mbuf *mbuf, struct ipv4_hdr *pip, uint16_t l2_len, uint16_t l3_len, int cksum_offload)
+inline void prox_ip_udp_cksum(struct rte_mbuf *mbuf, prox_rte_ipv4_hdr *pip, uint16_t l2_len, uint16_t l3_len, int cksum_offload)
{
- prox_ip_cksum(mbuf, pip, l2_len, l3_len, cksum_offload & IPV4_CKSUM);
+ prox_ip_cksum(mbuf, pip, l2_len, l3_len, cksum_offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM);
uint32_t l4_len = rte_bswap16(pip->total_length) - l3_len;
if (pip->next_proto_id == IPPROTO_UDP) {
- struct udp_hdr *udp = (struct udp_hdr *)(((uint8_t*)pip) + l3_len);
+ prox_rte_udp_hdr *udp = (prox_rte_udp_hdr *)(((uint8_t*)pip) + l3_len);
#ifndef SOFT_CRC
- if (cksum_offload & UDP_CKSUM) {
- mbuf->ol_flags |= PKT_TX_UDP_CKSUM;
+ if (cksum_offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) {
+ mbuf->ol_flags |= RTE_MBUF_F_TX_UDP_CKSUM;
prox_write_udp_pseudo_hdr(udp, l4_len, pip->src_addr, pip->dst_addr);
} else
#endif
prox_udp_cksum_sw(udp, l4_len, pip->src_addr, pip->dst_addr);
} else if (pip->next_proto_id == IPPROTO_TCP) {
- struct tcp_hdr *tcp = (struct tcp_hdr *)(((uint8_t*)pip) + l3_len);
+ prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(((uint8_t*)pip) + l3_len);
#ifndef SOFT_CRC
- if (cksum_offload & UDP_CKSUM) {
+ if (cksum_offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) {
prox_write_tcp_pseudo_hdr(tcp, l4_len, pip->src_addr, pip->dst_addr);
- mbuf->ol_flags |= PKT_TX_UDP_CKSUM;
+ mbuf->ol_flags |= RTE_MBUF_F_TX_UDP_CKSUM;
} else
#endif
prox_tcp_cksum_sw(tcp, l4_len, pip->src_addr, pip->dst_addr);
+ } else if (pip->next_proto_id == IPPROTO_IGMP) {
+ struct igmpv2_hdr *igmp = (struct igmpv2_hdr *)(((uint8_t*)pip) + l3_len);
+ // Not sure NIC can offload IGMP checkum => do it in software
+ prox_igmp_cksum_sw(igmp, l4_len);
}
}
-static uint16_t checksum_byte_seq(uint16_t *buf, uint16_t len)
+static inline uint16_t checksum_byte_seq(uint16_t *buf, uint16_t len)
{
uint32_t csum = 0;
@@ -129,17 +143,24 @@ static uint16_t checksum_byte_seq(uint16_t *buf, uint16_t len)
return ~csum;
}
-void prox_udp_cksum_sw(struct udp_hdr *udp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+inline void prox_udp_cksum_sw(prox_rte_udp_hdr *udp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
{
prox_write_udp_pseudo_hdr(udp, len, src_ip_addr, dst_ip_addr);
uint16_t csum = checksum_byte_seq((uint16_t *)udp, len);
udp->dgram_cksum = csum;
}
-void prox_tcp_cksum_sw(struct tcp_hdr *tcp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+inline void prox_tcp_cksum_sw(prox_rte_tcp_hdr *tcp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
{
prox_write_tcp_pseudo_hdr(tcp, len, src_ip_addr, dst_ip_addr);
uint16_t csum = checksum_byte_seq((uint16_t *)tcp, len);
tcp->cksum = csum;
}
+
+inline void prox_igmp_cksum_sw(struct igmpv2_hdr *igmp, uint16_t len)
+{
+ igmp->checksum = 0;
+ uint16_t csum = checksum_byte_seq((uint16_t *)igmp, len);
+ igmp->checksum = csum;
+}