P4ELTE / t4p4s

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

Bug when setting default rule while there is no key in table #20

Open Paxyk opened 4 years ago

Paxyk commented 4 years ago

Hi, we was using your code and found bug when setting default rule.

When you want to set default rule while there is no key = {... block in table. It seems that default rule will not be set.

git rev-parse HEAD showes this: a954d12b0f9db6f27a8fb05fa566b0dafc47ea0a

dpdk_controller.c :

// SPDX-License-Identifier: Apache-2.0
// Copyright 2016 Eotvos Lorand University, Budapest, Hungary

#include "controller.h"
#include "messages.h"
#include "handlers.h"
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>

controller c;
#define BUFFER_SIZE 2048

extern void notify_controller_initialized();

void dhf(void* b) {
    printf("some error\n");
}

void set_default_action_fill_influx() {
    char buffer[BUFFER_SIZE];
    struct p4_header *h;
    struct p4_set_default_action* def_act;
    struct p4_action* a;

    printf("SET DEF\n");

    h = create_p4_header(buffer, 0, BUFFER_SIZE);

    def_act = create_p4_set_default_action(buffer, 0, BUFFER_SIZE);
    strcpy(def_act->table_name, "bug_0");

    a = &(def_act->action);
    strcpy(a->description.name, "xxx");

    netconv_p4_header(h);
    netconv_p4_set_default_action(def_act);
    netconv_p4_action(a);

    send_p4_msg(c, buffer, BUFFER_SIZE);
}

void init() {

    printf("Set default actions\n");

    set_default_action_fill_influx();

    printf("Default action set\n");    

    notify_controller_initialized();

}

int main(int argc, char* argv[])
{
    printf("Create and configure controller...\n");
    c = create_controller_with_init(11111, 3, dhf, init);

    printf("Launching controller's main loop...\n");
    execute_controller(c);

    printf("Destroy controller\n");
    destroy_controller(c);

    return 0;
}

WORKING p4 program

#include <core.p4>
#include <v1model.p4>

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

header ip {
       bit<4> version;
       bit<4> ihl;
       bit<6>dscp;
       bit<2>  enc;
        bit <16>totalLen;
        bit<16>identification ;
        bit<3>flags;
        bit<13>fragOffset;
        bit<8>ttl;
        bit<8>protocol;
        bit<16>checksum;
        bit<32>srcAddr;
        bit<32>dstAddr;
    }

struct metadata {
}

struct headers {
    @name(".ethernet") 
    ethernet_t ethernet;
    ip ipv4;
}

parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    @name(".parse_ethernet") state parse_ethernet {
        packet.extract(hdr.ethernet);
        transition parse_ip;
    }

    state parse_ip {
        packet.extract(hdr.ipv4);
        transition accept;
    }
    @name(".start") state start {
        transition parse_ethernet;
    }

}

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

@name("mac_learn_digest") struct mac_learn_digest {
    bit<48> srcAddr;
    bit<9>  ingress_port;
}

control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    @name(".xxx") action xxx() {
    hdr.ipv4.totalLen = 3;    
    }
    @name(".bug") table bug {
        actions = {
            xxx;
        }
        key = {
            hdr.ethernet.dstAddr: exact;
        }
    }
    apply {
        bug.apply();
    }
}

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

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

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

V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main;

Buggy p4 program

#include <core.p4>
#include <v1model.p4>

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

header ip {
       bit<4> version;
       bit<4> ihl;
       bit<6>dscp;
       bit<2>  enc;
        bit <16>totalLen;
        bit<16>identification;
        bit<3>flags;
        bit<13>fragOffset;
        bit<8>ttl;
        bit<8>protocol;
        bit<16>checksum;
        bit<32>srcAddr;
        bit<32>dstAddr;
    }

struct metadata {
}

struct headers {
    @name(".ethernet") 
    ethernet_t ethernet;
    ip ipv4;
}

parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    @name(".parse_ethernet") state parse_ethernet {
        packet.extract(hdr.ethernet);
        transition parse_ip;
    }

    state parse_ip {
        packet.extract(hdr.ipv4);
        transition accept;
    }
    @name(".start") state start {
        transition parse_ethernet;
    }

}

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

@name("mac_learn_digest") struct mac_learn_digest {
    bit<48> srcAddr;
    bit<9>  ingress_port;
}

control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    @name(".xxx") action xxx() {
    hdr.ipv4.totalLen = 3;    
    }
    @name(".bug") table bug {
        actions = {
            xxx;
        }
    }
    apply {
        bug.apply();
    }
}

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

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

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

V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main;