P4ELTE / t4p4s

Retargetable compiler for the P4 language
http://p4.elte.hu/
Apache License 2.0
119 stars 42 forks source link

Modified packet not emitted #54

Closed VogelIBR closed 1 year ago

VogelIBR commented 1 year ago

When changing values in a custom header I don't receive the packet back on the other host. E.g., I broadcast a packet from node1, with the following code running on node0:

#include "common-boilerplate-pre.p4"

const bit<16> TYPE_IPV4 = 0x800;

struct metadata {
    /* In our case it is empty */
}

header test_t {
    bit<64> offset;
    bit<8> a;
    bit<8> b;
    bit<8> c;
    bit<8> d;
}

struct headers {
    ethernet_t   ethernet;
    ipv4_t       ipv4;
    test_t       four_bytes;
}

PARSER {
    state start {
        packet.extract(hdr.ethernet);
        transition select(hdr.ethernet.etherType) {
            TYPE_IPV4: parse_ipv4;
            default: accept;
        }
    }

    state parse_ipv4 {
        packet.extract(hdr.ipv4);
        transition parse_four_bytes;
    }

    state parse_four_bytes {
        packet.extract(hdr.four_bytes);
        transition accept;
    }

}

CTL_MAIN {
    apply {
        if (hdr.ipv4.isValid()) {
            # Since we don't go through the kernel this is actually not needed. 
            hdr.ethernet.srcAddr = 0x001122334455;
            hdr.four_bytes.a = 0x12;
            SET_EGRESS_PORT(GET_INGRESS_PORT());
        }
    }
}

CTL_EMIT {
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
        packet.emit(hdr.four_bytes);
    }
}

#include "common-boilerplate-post.p4"

I don't receive the changed packet back on node1.

Output on node0 which shows the packet it correctly parsed and line hdr.four_bytes.a = 0x12; is applied to the packet:

dataplane.c@  98 [CORE 0] Handling packet #-01 (port 0, 64B): ffff ffff ffff 0c42 a1dd 57d4 0800 4500 0020 0000 0000 0011 bace 0000 0000 0000 0000 0538 0539 000c f15f 0102 0304 0000 0000 0000 0000 0000 0000 0000 0000 0000
   parser.c@ 169 [CORE 0]  %%%% Parser state start
ulti_parser@  13 [CORE 0]    :: Parsed header#1 ethernet/14B: .dstAddr/6B=ffff_ffff_ffff .srcAddr/6B=0c42_a1dd_57d4 .etherType/2B=2048=0x0800
   parser.c@ 185 [CORE 0]  %%%% Parser state parse_ipv4 <== ethernet.etherType/16b=2048=0x0800 
ulti_parser@  39 [CORE 0]    :: Parsed header#2 ipv4/20B: .version/4b=4 .ihl/4b=5 .diffserv/1B=0 .totalLen/2B=32=0x0020 .identification/2B=0 .flags/3b=0 .fragOffset/13b=0 .ttl/1B=0 .protocol/1B=17=0x11 .hdrChecksum/2B=47822=0xbace .srcAddr/4B=0 .dstAddr/4B=0
ulti_parser@  26 [CORE 0]    :: Parsed header#3 four_bytes/12B: .offset/8B=0538_0539_000c_f15f .a/1B=1 .b/1B=2 .c/1B=3 .d/1B=4
   parser.c@ 152 [CORE 0]  %%%% Packet is accepted, 46B in 3 headers, 18B of payload: 0000 0000 0000 0000 0000 0000 0000 0000 0000
aplane_show@  31 [CORE 0]  ~~~~ Action [ingress.ifT]
_primitives@ 151 [CORE 0]     = Set ethernet.srcAddr/6B = 0011 2233 4455
_primitives@ 136 [CORE 0]     = Set four_bytes.a/1B = 18 = 0x12
_primitives@ 136 [CORE 0]     = Set all_metadatas.egress_port/9b = 0 = 0x0000
     main.c@  79 [CORE 0]  <<<< Emitting packet #-01 with unchanged structure on port 0: 46B of headers, 18B of payload

If I uncomment the line hdr.four_bytes.a = 0x12; I get the following output on node0:

dataplane.c@  98 [CORE 0] Handling packet #-01 (port 0, 64B): ffff ffff ffff 0c42 a1dd 57d4 0800 4500 0020 0000 0000 0011 bace 0000 0000 0000 0000 0538 0539 000c f15f 0102 0304 0000 0000 0000 0000 0000 0000 0000 0000 0000
   parser.c@ 169 [CORE 0]  %%%% Parser state start
ulti_parser@  13 [CORE 0]    :: Parsed header#1 ethernet/14B: .dstAddr/6B=ffff_ffff_ffff .srcAddr/6B=0c42_a1dd_57d4 .etherType/2B=2048=0x0800
   parser.c@ 185 [CORE 0]  %%%% Parser state parse_ipv4 <== ethernet.etherType/16b=2048=0x0800 
ulti_parser@  39 [CORE 0]    :: Parsed header#2 ipv4/20B: .version/4b=4 .ihl/4b=5 .diffserv/1B=0 .totalLen/2B=32=0x0020 .identification/2B=0 .flags/3b=0 .fragOffset/13b=0 .ttl/1B=0 .protocol/1B=17=0x11 .hdrChecksum/2B=47822=0xbace .srcAddr/4B=0 .dstAddr/4B=0
ulti_parser@  26 [CORE 0]    :: Parsed header#3 four_bytes/12B: .offset/8B=0538_0539_000c_f15f .a/1B=1 .b/1B=2 .c/1B=3 .d/1B=4
   parser.c@ 152 [CORE 0]  %%%% Packet is accepted, 46B in 3 headers, 18B of payload: 0000 0000 0000 0000 0000 0000 0000 0000 0000
aplane_show@  31 [CORE 0]  ~~~~ Action [ingress.ifT]
_primitives@ 151 [CORE 0]     = Set ethernet.srcAddr/6B = 0011 2233 4455
_primitives@ 136 [CORE 0]     = Set all_metadatas.egress_port/9b = 0 = 0x0000
     main.c@  79 [CORE 0]  <<<< Emitting packet #-01 with unchanged structure on port 0: 46B of headers, 18B of payload

And I receive the packet back on node1: (with correctly mirrored payload 0x01020304)

Frame 193: 64 bytes on wire (512 bits), 64 bytes captured (512 bits) on interface enp65s0f0np0, id 0
Ethernet II, Src: CIMSYS_33:44:55 (00:11:22:33:44:55), Dst: Broadcast (ff:ff:ff:ff:ff:ff)
Internet Protocol Version 4, Src: 0.0.0.0, Dst: 0.0.0.0
User Datagram Protocol, Src Port: 1336, Dst Port: 1337
Data (4 bytes)

I don't see any errors and the log even claims the packet is emitted back, I am unsure why I don't receive the packet back on node1. Especially since when I only modify the mac address I still get the packet back.

VogelIBR commented 1 year ago

Ok nvm. I figured it out. Since I modified the UDP data which is included in the UDP checksum without fixing the checksum it was discarded somewhere on the path.