aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorBin Meng <bin.meng@windriver.com>2020-12-11 17:35:12 +0800
committerJason Wang <jasowang@redhat.com>2021-01-25 17:04:56 +0800
commitf574633529926697ced51b6865e5c50bbb78bf1b (patch)
tree98d77919083dfcbec0247c6980c479d08bc07d3b /net
parentd97f11590a0f60cd911ace8bb68180b5a09a068d (diff)
net: checksum: Introduce fine control over checksum type
At present net_checksum_calculate() blindly calculates all types of checksums (IP, TCP, UDP). Some NICs may have a per type setting in their BDs to control what checksum should be offloaded. To support such hardware behavior, introduce a 'csum_flag' parameter to the net_checksum_calculate() API to allow fine control over what type checksum is calculated. Existing users of this API are updated accordingly. Signed-off-by: Bin Meng <bin.meng@windriver.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
Diffstat (limited to 'net')
-rw-r--r--net/checksum.c18
-rw-r--r--net/filter-rewriter.c4
2 files changed, 16 insertions, 6 deletions
diff --git a/net/checksum.c b/net/checksum.c
index dabd290c64..70f4eaeb3a 100644
--- a/net/checksum.c
+++ b/net/checksum.c
@@ -57,7 +57,7 @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
return net_checksum_finish(sum);
}
-void net_checksum_calculate(uint8_t *data, int length)
+void net_checksum_calculate(uint8_t *data, int length, int csum_flag)
{
int mac_hdr_len, ip_len;
struct ip_header *ip;
@@ -108,9 +108,11 @@ void net_checksum_calculate(uint8_t *data, int length)
}
/* Calculate IP checksum */
- stw_he_p(&ip->ip_sum, 0);
- csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip));
- stw_be_p(&ip->ip_sum, csum);
+ if (csum_flag & CSUM_IP) {
+ stw_he_p(&ip->ip_sum, 0);
+ csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip));
+ stw_be_p(&ip->ip_sum, csum);
+ }
if (IP4_IS_FRAGMENT(ip)) {
return; /* a fragmented IP packet */
@@ -128,6 +130,10 @@ void net_checksum_calculate(uint8_t *data, int length)
switch (ip->ip_p) {
case IP_PROTO_TCP:
{
+ if (!(csum_flag & CSUM_TCP)) {
+ return;
+ }
+
tcp_header *tcp = (tcp_header *)(ip + 1);
if (ip_len < sizeof(tcp_header)) {
@@ -148,6 +154,10 @@ void net_checksum_calculate(uint8_t *data, int length)
}
case IP_PROTO_UDP:
{
+ if (!(csum_flag & CSUM_UDP)) {
+ return;
+ }
+
udp_header *udp = (udp_header *)(ip + 1);
if (ip_len < sizeof(udp_header)) {
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index fc0e64c45b..10fe3939b1 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -114,7 +114,7 @@ static int handle_primary_tcp_pkt(RewriterState *rf,
tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
- pkt->size - pkt->vnet_hdr_len);
+ pkt->size - pkt->vnet_hdr_len, CSUM_TCP);
}
/*
@@ -216,7 +216,7 @@ static int handle_secondary_tcp_pkt(RewriterState *rf,
tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
- pkt->size - pkt->vnet_hdr_len);
+ pkt->size - pkt->vnet_hdr_len, CSUM_TCP);
}
}