18b52a31eSHanoh Haim#include "CPktCmn.h"
28b52a31eSHanoh Haim/*
38b52a31eSHanoh HaimCopyright (c) 2015-2015 Cisco Systems, Inc.
48b52a31eSHanoh Haim
58b52a31eSHanoh HaimLicensed under the Apache License, Version 2.0 (the "License");
68b52a31eSHanoh Haimyou may not use this file except in compliance with the License.
78b52a31eSHanoh HaimYou may obtain a copy of the License at
88b52a31eSHanoh Haim
98b52a31eSHanoh Haim    http://www.apache.org/licenses/LICENSE-2.0
108b52a31eSHanoh Haim
118b52a31eSHanoh HaimUnless required by applicable law or agreed to in writing, software
128b52a31eSHanoh Haimdistributed under the License is distributed on an "AS IS" BASIS,
138b52a31eSHanoh HaimWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148b52a31eSHanoh HaimSee the License for the specific language governing permissions and
158b52a31eSHanoh Haimlimitations under the License.
168b52a31eSHanoh Haim*/
178b52a31eSHanoh Haim
188b52a31eSHanoh Haim
198b52a31eSHanoh Haim
208b52a31eSHanoh Haim#define TouchCacheLine(a)
218b52a31eSHanoh Haim
228b52a31eSHanoh Haimuint16_t pkt_InetChecksum(uint8_t* data ,
238b52a31eSHanoh Haim                        uint16_t len, uint8_t* data2 , uint16_t len2){
248b52a31eSHanoh Haim
258b52a31eSHanoh Haim    TouchCacheLine(data2);
268b52a31eSHanoh Haim    TouchCacheLine(data2+32);
278b52a31eSHanoh Haim    TouchCacheLine(data2+64);
288b52a31eSHanoh Haim
298b52a31eSHanoh Haim    int sum = 0;
308b52a31eSHanoh Haim    while(len>1){
318b52a31eSHanoh Haim        TouchCacheLine(data+96); //three lines ahead !
328b52a31eSHanoh Haim        sum += PKT_NTOHS(*((uint16_t*)data));
338b52a31eSHanoh Haim        data += 2;
348b52a31eSHanoh Haim        len -= 2;
358b52a31eSHanoh Haim    }
368b52a31eSHanoh Haim
378b52a31eSHanoh Haim    while(len2>1){
388b52a31eSHanoh Haim        TouchCacheLine(data2+96); //three lines ahead !
398b52a31eSHanoh Haim        sum += PKT_NTOHS(*((uint16_t*)data2));
408b52a31eSHanoh Haim        data2 += 2;
418b52a31eSHanoh Haim        len2 -= 2;
428b52a31eSHanoh Haim    }
438b52a31eSHanoh Haim
448b52a31eSHanoh Haim    if(len2){
458b52a31eSHanoh Haim        sum += (PKT_NTOHS(*((uint16_t*)data2)) & 0xff00);
468b52a31eSHanoh Haim    }
478b52a31eSHanoh Haim
488b52a31eSHanoh Haim    while(sum >> 16){
498b52a31eSHanoh Haim        sum = (sum & 0xffff) + (sum >> 16);
508b52a31eSHanoh Haim    }
518b52a31eSHanoh Haim
528b52a31eSHanoh Haim    return PKT_NTOHS((uint16_t)(~sum));
538b52a31eSHanoh Haim}
548b52a31eSHanoh Haim
558b52a31eSHanoh Haimuint16_t pkt_InetChecksum(uint8_t* data , uint16_t len){
568b52a31eSHanoh Haim
578b52a31eSHanoh Haim    int sum = 0;
588b52a31eSHanoh Haim    while(len>1){
598b52a31eSHanoh Haim        TouchCacheLine(data+96); //three line ahead !
608b52a31eSHanoh Haim        sum += PKT_NTOHS(*((uint16_t*)data));
618b52a31eSHanoh Haim        data += 2;
628b52a31eSHanoh Haim        len -= 2;
638b52a31eSHanoh Haim    }
648b52a31eSHanoh Haim
658b52a31eSHanoh Haim    if(len){
668b52a31eSHanoh Haim        sum += (PKT_NTOHS(*((uint16_t*)data)) & 0xff00);
678b52a31eSHanoh Haim    }
688b52a31eSHanoh Haim
698b52a31eSHanoh Haim    while(sum >> 16){
708b52a31eSHanoh Haim        sum = (sum & 0xffff) + (sum >> 16);
718b52a31eSHanoh Haim    }
728b52a31eSHanoh Haim
738b52a31eSHanoh Haim    return PKT_NTOHS((uint16_t)(~sum));
748b52a31eSHanoh Haim}
758b52a31eSHanoh Haim
768b52a31eSHanoh Haimuint16_t pkt_UpdateInetChecksum(uint16_t csFieldFromPacket, uint16_t oldVal, uint16_t newVal){
778b52a31eSHanoh Haim    uint32_t newCS;
788b52a31eSHanoh Haim    newCS = (uint16_t)(~PKT_NTOHS(csFieldFromPacket));
798b52a31eSHanoh Haim    newCS += (uint16_t)(~PKT_NTOHS(oldVal));
808b52a31eSHanoh Haim    newCS += (uint16_t)PKT_NTOHS(newVal);
818b52a31eSHanoh Haim    while(newCS >> 16){
828b52a31eSHanoh Haim        newCS = (newCS & 0xffff) + (newCS >> 16);
838b52a31eSHanoh Haim    }
848b52a31eSHanoh Haim    return PKT_NTOHS((uint16_t)(~newCS));
858b52a31eSHanoh Haim}
868b52a31eSHanoh Haim
878b52a31eSHanoh Haimuint16_t pkt_SubtractInetChecksum(uint16_t checksum, uint16_t csToSubtract){
888b52a31eSHanoh Haim    uint32_t newCS;
898b52a31eSHanoh Haim    newCS = (uint16_t)(~PKT_NTOHS(checksum));
908b52a31eSHanoh Haim
918b52a31eSHanoh Haim    // since the cs is already in ~ format in the packet, there is no need
928b52a31eSHanoh Haim    // to negate it for subtraction in 1's complement.
938b52a31eSHanoh Haim    newCS += (uint16_t)PKT_NTOHS(csToSubtract);
948b52a31eSHanoh Haim
958b52a31eSHanoh Haim    while(newCS >> 16){
968b52a31eSHanoh Haim        newCS = (newCS & 0xffff) + (newCS >> 16);
978b52a31eSHanoh Haim    }
988b52a31eSHanoh Haim    return PKT_NTOHS((uint16_t)(~newCS));
998b52a31eSHanoh Haim}
1008b52a31eSHanoh Haim
1018b52a31eSHanoh Haimuint16_t pkt_AddInetChecksum(uint16_t checksum, uint16_t csToAdd){
1028b52a31eSHanoh Haim    uint32_t newCS;
1038b52a31eSHanoh Haim    newCS = (uint16_t)(~PKT_NTOHS(checksum));
1048b52a31eSHanoh Haim
1058b52a31eSHanoh Haim    // since the cs is already in ~ format in the packet, there is a need
1068b52a31eSHanoh Haim    // to negate it for addition in 1's complement.
1078b52a31eSHanoh Haim    newCS += (uint16_t)PKT_NTOHS(~csToAdd);
1088b52a31eSHanoh Haim
1098b52a31eSHanoh Haim    while(newCS >> 16){
1108b52a31eSHanoh Haim        newCS = (newCS & 0xffff) + (newCS >> 16);
1118b52a31eSHanoh Haim    }
1128b52a31eSHanoh Haim    return PKT_NTOHS((uint16_t)(~newCS));
1138b52a31eSHanoh Haim}
1148b52a31eSHanoh Haim
1158b52a31eSHanoh Haim
1168b52a31eSHanoh Haimextern "C" void pkt_ChecksumTest(){
1178b52a31eSHanoh Haim
1188b52a31eSHanoh Haim    uint16_t cs;
1198b52a31eSHanoh Haim    uint8_t data[5] = {0xcd,0x7a,0x55,0x55,0xa1};
1208b52a31eSHanoh Haim
1218b52a31eSHanoh Haim    cs = pkt_InetChecksum((uint8_t*)data,5);
1228b52a31eSHanoh Haim    printf("CS = 0x%04x: ",cs);
1238b52a31eSHanoh Haim    if(cs == 0x2F3C){
1248b52a31eSHanoh Haim        printf("CS func with odd len OK.\n");
1258b52a31eSHanoh Haim    }else{
1268b52a31eSHanoh Haim        printf("ERROR: CS func produced wrong value with odd number of bytes.\n");
1278b52a31eSHanoh Haim    }
1288b52a31eSHanoh Haim
1298b52a31eSHanoh Haim    cs = pkt_InetChecksum((uint8_t*)data,4);
1308b52a31eSHanoh Haim    printf("CS = 0x%04x: ",cs);
1318b52a31eSHanoh Haim    if(cs == 0x2FDD){
1328b52a31eSHanoh Haim        printf("CS func with even len OK.\n");
1338b52a31eSHanoh Haim    }else{
1348b52a31eSHanoh Haim        printf("ERROR: CS func produced wrong value with even number of bytes.\n");
1358b52a31eSHanoh Haim    }
1368b52a31eSHanoh Haim
1378b52a31eSHanoh Haim    cs = pkt_UpdateInetChecksum(cs,0x5555,0x8532);
1388b52a31eSHanoh Haim    printf("CS = 0x%04x: ",cs);
1398b52a31eSHanoh Haim    if(cs == 0x0000){
1408b52a31eSHanoh Haim        printf("Update CS func OK.\n");
1418b52a31eSHanoh Haim    }else{
1428b52a31eSHanoh Haim        printf("ERROR: Update CS func produced wrong value.\n");
1438b52a31eSHanoh Haim    }
1448b52a31eSHanoh Haim
1458b52a31eSHanoh Haim}