Issue in p4-learning/examples/recirculate

Hello everyone,

I’m doing the recirculate example in the p4-learning repo. When I run the program, I got this error:

I’ve checked the directory /usr/local/share/p4c/p4include/v1model.p4 and I see that the recirculate extern exists

Here is the .p4 program:

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

const bit<16> TYPE_IPV4 = 0x800;
#define RECIRCULATE_TIMES 5

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

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

/* TCP/IP Headers */

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

header ipv4_t {
    bit<4>    version;
    bit<4>    ihl;
    bit<8>    tos;
    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 {
    bit<8> counter;
}

struct headers {
    ethernet_t   ethernet;
    ipv4_t       ipv4;
}


/*************************************************************************
*********************** 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;
    }
}

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

control MyDeparser(packet_out packet, in headers hdr) {
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
    }
}

/*************************************************************************
************   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);
    }

    apply {
        standard_metadata.egress_spec = 2;
    }
}

/*************************************************************************
****************  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) {


    //To debug
    table debug {
        key = {
            meta.counter: exact;
        }
        actions = {
            NoAction;
        }
        size=1;
        default_action=NoAction();
    }

    apply {
       debug.apply();
       if (meta.counter < RECIRCULATE_TIMES){
           meta.counter = meta.counter + 1;
           recirculate({meta.counter});
       }
    }
}

/*************************************************************************
*************   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.tos,
              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);
    }
}


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

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

Does anyone know this problem? I’m using April, 2023 Development VM.

Hi @tuananh01

  • did you take a look of the command that is runned in the the python script?

  • did you try to compile by “your hand” the p4 program instead of use a script?

Here you can find the “official” and latest update version of the P4 tutorial GitHub - p4lang/tutorials at e855fa7dfd7c05d8c8f4ec0cd25930dfa304389a

1 Like

It is true that recirculate is still defined in the v1model.p4 include file, but note that it is also deprecated, with a suggestion to use the new recirculate_preserving_field_list extern function instead.

I am not sure, but perhaps when recirculate was deprecated, its implementation may have also been removed, leading to the compiler error you are seeing?

If you make these two changes to your program, it compiles without errors or warnings with recent versions of p4c (the deprecation of recirculate was done over 1 year ago):

(1)In the definition of your user-defined metadata struct, add a @field_list annotation to any fields that you want to preserve, and pick a field list numeric id for each “set” of fields that. you might want to preserve in different situations. If you always want to preserve all of it, then it is simplest to put the annotation on every field with the same numeric id.

struct metadata {
    @field_list(1)
    bit<8> counter;
}

(2) Replace your call to recirculate with recirculate_preserving_field_list(1);

Thank you, @andyfingerhut. It worked.