Calculating checksum with example
So, I had worked earlier on a message passing ping application and we wanted to incorporate the checksum into the payload.
We used the following structure:
struct tst_msg_hdr {
uint_t tmh_magic; /* 4 */
uchar_t tmh_flags; /* 5 */
llt_nid_t tmh_src; /* 6 */
llt_nid_t tmh_dst; /* 7 */
llt_port_t tmh_port; /* 8 */
ushort_t tmh_pktnum; /* 10 */
uint_t tmh_len; /* Linux 14 */
ushort_t tmh_hdrcksum; /* Linux 16, 14 otherwise */
ushort_t tmh_cksum; /* Linux 18, 16 otherwise */
};
We used the following structure:
struct tst_msg_hdr {
uint_t tmh_magic; /* 4 */
uchar_t tmh_flags; /* 5 */
llt_nid_t tmh_src; /* 6 */
llt_nid_t tmh_dst; /* 7 */
llt_port_t tmh_port; /* 8 */
ushort_t tmh_pktnum; /* 10 */
uint_t tmh_len; /* Linux 14 */
ushort_t tmh_hdrcksum; /* Linux 16, 14 otherwise */
ushort_t tmh_cksum; /* Linux 18, 16 otherwise */
};
So we wanted to calculate the tmh_hdrcksum which is the checksum of only the header portion of tst_msg_hdr.
mp->tmh_magic = HDR_MAGIC;
mp->tmh_flags = 0;
mp->tmh_src = mynode;
mp->tmh_dst = node;
mp->tmh_port = port;
mp->tmh_pktnum = long_to_ushort(mp - start_mpool);
mp->tmh_len = size_to_uint(size);
/* calculate checksum only if verification is requested */
if (veriflg) {
mp->tmh_hdrcksum = tmh_cksum((uchar_t *) mp,
(uchar_t *) &mp->tmh_hdrcksum);
}
mp->tmh_cksum = 0;
mp++;
So I pass the start and end address of the portion of memory we want to calculate the checksum on.
ushort_t tmh_cksum(unsigned char *ckstart, unsigned char *ckend)
{
uchar_t sum = 0, rot = 0, *curp;
for (curp = ckstart; curp < ckend; curp++) {
sum ^= *curp;
rot = (rot << 1) ^ *curp;
}
return (rot << 8) | sum;
}
This is a simple checksum calculation function: XOR each byte (from start byte to end byte) with previous sum.
Then calculate the rot = ( rot << 1) ^ *curp;
The finally return last 8 bits of rot XORed with sum.