Skip to content

Latest commit

 

History

History
184 lines (149 loc) · 5.47 KB

ansible.md

File metadata and controls

184 lines (149 loc) · 5.47 KB

Extend P4-16 as P4++

An overview of P4-16 extensions (P4++) is provided below. P4++ is used to write the customer P4 program. The customer P4 program is merged with a regular P4 program and a final merged P4 program is generated by the P4-Ansible tool. P4-Ansible uses a Python shell which provides commands to merge vendor and customer P4-16 programs.

Extensions

New keyword override

Examples for how the override keyword is used are provided below.

struct headers_t override { // tells compiler this is a "patch" to the previous type definition, not a new one.
    new_header_t new_header;
}

// tells compiler to patch previously
// defined parser with the same name ("base_parser")
parser base_parser(…) override {
    state ethernet override {  // override previously defined state definition
        ...
    }
    
    state new_state {  // if no override, then add the state as a new one
        ...
    }
}

control new_ingress(...) {  // no keyword used here, but the example shows how to merge two controls.
    old_ingress = base_ingress()
    apply {
        // new code is here
        //
        old_ingress.apply();
    }
}

control new_deparser(...) override {
    // extended deparser here
}

package V1Switch(base_parser, new_ingers, new_deparser) override;  // tells compiler to ignore (drop) previous package declaration and use this one
	

New Keywords: super.xxx.transition

xxx in syntax above is a parser state.

An example use of syntax in merging two P4 programs is shown below.

base.p4
---------
parser base_parser {
    state parse_ipv4_state {
        extract(hdr.ipv4);
        transition accept;
    }

    state parse_ethernet {
        extract(hdr.eth);
        transition (hdr.eth.ethertype) {
            IPV4: parse_ipv4_state;
            default: accept;
        }
    }
}
extended.p4
------------
parser base_parser override {
    state parse_ipv6_state {
        extract(hdr.ipv6);
        transition accept;
    }

    state parse_ethernet override {
        extract(hdr.eth);
        transition (hdr.eth.ethertype) {
            IPV6: parse_ipv6_state;
            // no need to extract, only switch based
            // on already extracted header
            default: super.parse_ethernet.transition;
        }
    }
}

We need to combine the two into one standard p4 program as follows.

parser base_parser { 
    state parse_ipv6_state {
        extract(hdr.ipv6);
        transition accept;
    }

    state _parse_ipv4_state {
        extract(hdr.ipv4);
        transition accept;
    }

    // original base state
    state parse_ethernet_transition {
        transition (hdr.eth.ethertype) {
            IPV4: parse_ipv4_state;
            default: accept;
        }
    }

    // extended state
    state parse_ethernet {
        extract(hdr.eth);
        transition (hdr.eth.ethertype) {
            IPV6: ipv6_state;
            // replace super reference with the name of the newly created transition part of the base state
            default: parse_ethernet_transition;
        }
    }
}

Override for Tables and Actions (not supported yet)

// Augmenting action parameter and action body is supported. Defaults to adding
// body to end.
action set_port_properties(...) override {  // tells compiler to patch previously
    // defined action.
}

// tells compiler to allow adding new action.
action New_action() {

}
table ipv4_acl override {
key override = {  // Patch new key element
// new key element.
}
actions override = {  // Patch to existing actions.
New_action;
}
default_action override = action_x;  // tells compiler to use this action as default_action.
}

Misc (Only control override is supported, rest is not supported yet)

control foo(…) override {
    action moo(…) override {
        // new code here
        super.moo(); // call base action.
    }
    apply {
        // new code
        super.apply(); // call apply method from the base code.
        // more new code
    }
}

P4 Constructs Supported for Override

Struct, Header, Header Union, Enum, Serialized Enum, Parser, Parser State, Control, and Package.

Writing P4++

  1. Deparser - the two new keywords cannot support merging deparsers which require a specific oder of headers to emit. So, if merging deparsers is required, write code to merge manually and override the base code deparser.

  2. Only add code if the code overrides base funtionality. For example, if no changes are made to base parser, do not add any parser code.

  3. The tool tackled the hardest problem first – it was to merge P4 parsers. The tool does not support fine-grained merging of P4 Control elements such as table key, table list of actions, and action. However, the design to merge such elements is complete and published in the this doc. Until fine grained P4 Control is supported, we support overriding of base control causing new control replacing base control. In summary P4 merging is supported for the whole P4 Program with some manual merge operations when writing new code in P4++.

Appendix

Use Cases

Usually, a Tofino with 12 stages, is using all stages in a production switch. However, the Tofino2 has 20 stages and then the tool can merge new P4 code with Tofino code and run the merged code on Tofino2. The paid version can remove/add specific functionality. Tofino merge examples are provided in the paid version of the tool.

Thereafter, a software implementation of P4, e.g., P4toVPP or P4toDPDK, is even better for use of the tool.