# Icmp checksum invalid

**URL:** <https://forum.p4.org/t/icmp-checksum-invalid/1235>\
**Category:** Getting Started with P4\
**Created:** [December 25, 2024, 7:04am UTC](https://forum.p4.org/t/icmp-checksum-invalid/1235 "2024-12-25T07:04:32Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![hane0817](https://avatars.discourse-cdn.com/v4/letter/h/a88e4f/32.png) [@hane0817](https://forum.p4.org/u/hane0817)\
**Post date:** [December 25, 2024, 7:04am UTC](https://forum.p4.org/t/icmp-checksum-invalid/1235/1 "2024-12-25T07:04:32Z")

</div>

Hi.

I’m new here.  
I would like to add a timestamp to ipv4.options using p4-utils. But ICMP checksum was invalid.

Below is a program and wireshark image of what shows up when I run the program.

I use ping when I run the program.

What steps do I need to take to get the ICMP checksum value correct?

```auto
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>

const bit<16> TYPE_IPV4 = 0x800;

/ *************************************************************************
 ***********************H E A D E R S***********************************
 ************************************************************************* /

typedef bit<9> egressSpec_t;
typedef bit<48> macAddr_t;
typedef bit<32> ip4Addr_t;

header ethernet_t {
    macAddr_t dstAddr;
    macAddr_t srcAddr;
    bit<16> etherType;
}

header ipv4_t {
    bit<4> version;
    bit<4> ihl;
    bit<8> diffserv;
    bit<16> totalLen;
    bit<16> identification;
    bit<3> flags;
    bit<13> fragOffset;
    bit<8> ttl;
    bit<8> protocol;
    bit<16> hdrChecksum;
    ip4Addr_t srcAddr;
    ip4Addr_t dstAddr;
}

struct metadata {
    /* empty */
}

header timestamp_t {
   bit<48> value;
   bit<16> hdrChecksum;
}

struct headers {
    ethernet_t ethernet;
    ipv4_t ipv4;
    timestamp_t timestamp;
}

/ *************************************************************************
 ***********************P A R S E R***********************************
 ************************************************************************* /

parser MyParser(packet_in packet,
                out headers hdr,
                inout metadata meta,
                inout standard_metadata_t standard_metadata) {

    state start {

        packet.extract(hdr.ethernet);
        transition select(hdr.ethernet.etherType){

            TYPE_IPV4: ipv4;
            default: accept;

        }

    }

    state ipv4 {

        packet.extract(hdr.ipv4);
        transition accept;
    }

}

/ *************************************************************************
 ************C H E C K S U M V E R I F I C A T I O N*************
 ************************************************************************* /

control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
    apply { }
}

/ *************************************************************************
 **************I N G R E S S P R O C E S S I N G*******************
 ************************************************************************* /

control MyIngress(inout headers hdr,
                  inout metadata meta,
                  inout standard_metadata_t standard_metadata) {

    action drop() {
        mark_to_drop(standard_metadata);
    }

    action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {

        //set the src mac address as the previous dst, this is not correct right?
        hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;

       //set the destination mac address that we got from the match in the table
        hdr.ethernet.dstAddr = dstAddr;

        //set the output port that we also get from the table
        standard_metadata.egress_spec = port;

        //decrease ttl by 1
        hdr.ipv4.ttl = hdr.ipv4.ttl -1;

        hdr.ipv4.ihl=0x7;

        hdr.timestamp.setValid();
        hdr.timestamp.value=standard_metadata.ingress_global_timestamp;
    }

    table ipv4_lpm {
        key = {
            hdr.ipv4.dstAddr: lpm;
        }
        actions = {
            ipv4_forward;
            drop;
            NoAction;
        }
        size = 1024;
        default_action = NoAction();
    }

    apply {

        //only if IPV4 the rule is applied. Therefore other packets will not be forwarded.
        if (hdr.ipv4.isValid()){
            ipv4_lpm.apply();

        }
    }
}

/ *************************************************************************
 ****************E G R E S S P R O C E S S I N G*******************
 ************************************************************************* /

control MyEgress(inout headers hdr,
                 inout metadata meta,
                 inout standard_metadata_t standard_metadata) {
    apply { }
}

/ *************************************************************************
 *************C H E C K S U M C O M P U T A T I O N**************
 ************************************************************************* /

control MyComputeChecksum(inout headers hdr, inout metadata meta) {
     apply {
        update_checksum(
	    hdr.ipv4.isValid(),
            { hdr.ipv4.version,
	      hdr.ipv4.ihl,
              hdr.ipv4.diffserv,
              hdr.ipv4.totalLen,
              hdr.ipv4.identification,
              hdr.ipv4.flags,
              hdr.ipv4.fragOffset,
              hdr.ipv4.ttl,
              hdr.ipv4.protocol,
              hdr.ipv4.srcAddr,
              hdr.ipv4.dstAddr },
            hdr.ipv4.hdrChecksum,
            HashAlgorithm.csum16);

        update_checksum(
	    hdr.timestamp.isValid(),
            { hdr.timestamp.value },
            hdr.timestamp.hdrChecksum,
            HashAlgorithm.csum16);
    }
}

/ *************************************************************************
 ***********************D E P A R S E R*******************************
 ************************************************************************* /

control MyDeparser(packet_out packet, in headers hdr) {
    apply {

        //parsed headers have to be added again into the packet.
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
        packet.emit(hdr.timestamp);
    }
}

/ *************************************************************************
 ***********************S W I T C H*******************************
 ************************************************************************* /

//switch architecture
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;

```

 ![thumbnail_Screenshot from 2024-12-25 15-56-30](https://us1.discourse-cdn.com/flex019/uploads/p4/original/1X/852cbb2813f5239104d10e24a9a85c4d60401d39.png)

---

<div class="post-metadata">

**Author:** ![p4prof](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.p4.org/p4prof/32/251_2.png) [@p4prof](https://forum.p4.org/u/p4prof)\
**Post date:** [December 25, 2024, 6:49pm UTC](https://forum.p4.org/t/icmp-checksum-invalid/1235/2 "2024-12-25T18:49:53Z")

</div>

Dear @hane0817 ,

Welcome to the forum!

It is difficult to give you a conclusive answer without seeing the whole program and especially the definition of the header `hdr.timestamp`, but the general rule for ICMP checksum is to include all the bytes of the ICMP message and not just the header. See [RFC 972](https://datatracker.ietf.org/doc/html/rfc792#:~:text=source%20route%20failed.-,Checksum%0A%0A%20%20%20%20%20%20The%20checksum%20is%20the%2016%2Dbit%20ones%27s%20complement%20of%20the%20one%27s%0A%20%20%20%20%20%20complement%20sum%20of%20the%20ICMP%20message%20starting%20with%20the%20ICMP%20Type.%0A%20%20%20%20%20%20For%20computing%20the%20checksum%20%2C%20the%20checksum%20field%20should%20be%20zero.%0A%20%20%20%20%20%20This%20checksum%20may%20be%20replaced%20in%20the%20future.,-Internet%20Header%20%2B%2064).

Happy hacking,  
Vladimir
