summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorroot <[email protected]>2024-02-28 08:28:03 +0000
committerroot <[email protected]>2024-02-28 08:28:03 +0000
commite01a9248bd9d0d79f74e6590cd19f36e7e4d09df (patch)
tree4a499cd92885deb4043c3517da35ff4338338652 /common
parent5cdde1b9d74d053ddf5e505dc3a39f2154fb3d1e (diff)
fix ip header checksum wrong after modify DSCP value for a packet
fix table_info.json shaping profile table valid column add some debug info
Diffstat (limited to 'common')
-rw-r--r--common/src/raw_packet.cpp51
-rw-r--r--common/test/gtest_raw_packet.cpp3
2 files changed, 29 insertions, 25 deletions
diff --git a/common/src/raw_packet.cpp b/common/src/raw_packet.cpp
index 83dd0f0..3b6dad3 100644
--- a/common/src/raw_packet.cpp
+++ b/common/src/raw_packet.cpp
@@ -1,6 +1,7 @@
#include <assert.h>
#include <errno.h>
#include <linux/if_ether.h>
+#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
@@ -1059,30 +1060,29 @@ static const void *parse_mpls(struct raw_pkt_parser *handler, const void *data,
}
}
-static unsigned short ip_checksum(struct iphdr *iph) {
- // 初始化检验和为0
- unsigned short checksum = 0;
- // 将IP头的指针转换为无符号短整型的指针
- unsigned short *p = (unsigned short *)iph;
- // 计算IP头的长度,单位为字节
- int len = iph->ihl * 4;
- // 逐个累加IP头的每个16位字段
- while (len > 1) {
- checksum += *p++;
- len -= 2;
- }
- // 如果IP头的长度为奇数,将最后一个字节视为高8位,低8位补0,再累加
- if (len == 1) {
- checksum += *(unsigned char *)p << 8;
- }
- // 将检验和的高16位和低16位相加,直到没有进位
- while (checksum >> 16) {
- checksum = (checksum & 0xFFFF) + (checksum >> 16);
- }
- // 将检验和取反
- checksum = ~checksum;
- // 返回检验和
- return checksum;
+static unsigned short ip_header_checksum_calculate(struct iphdr *iph)
+{
+ unsigned short *buffer = (unsigned short *)iph;
+ unsigned int length = iph->ihl * 4;
+ unsigned int sum = 0;
+
+ while (length > 1)
+ {
+ sum += *buffer++;
+ length -= 2;
+ }
+
+ if (length > 0)
+ {
+ sum += ((*buffer) & htons(0xFF00));
+ }
+
+ while (sum >> 16)
+ {
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ }
+
+ return ~sum;
}
void raw_packet_set_dscp(struct ethhdr *eth_hdr, uint8_t dscp)
@@ -1092,7 +1092,8 @@ void raw_packet_set_dscp(struct ethhdr *eth_hdr, uint8_t dscp)
struct iphdr *ip_hdr = (struct iphdr *)(eth_hdr + 1);
ip_hdr->tos = (ip_hdr->tos & 0x03) | (dscp << 2);
//recalculate checksum
- ip_hdr->check = ip_checksum(ip_hdr);
+ ip_hdr->check = 0;
+ ip_hdr->check = ip_header_checksum_calculate(ip_hdr);
}
else if (eth_hdr->h_proto == htons(ETH_P_IPV6))
{
diff --git a/common/test/gtest_raw_packet.cpp b/common/test/gtest_raw_packet.cpp
index 02422da..69d752f 100644
--- a/common/test/gtest_raw_packet.cpp
+++ b/common/test/gtest_raw_packet.cpp
@@ -1391,6 +1391,9 @@ TEST(RAW_PACKET, SET_IPV4_DSCP_VALUE)
raw_packet_set_dscp(eth, 40);//40 is CS5
dscp_value = ip->tos >> 2;
EXPECT_EQ(dscp_value, 40);
+
+ EXPECT_EQ(htons(ip->check), 0x7fb3);
+
pcap_close(handle);
}