Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

If the PSA frame NTK path set to true,the ARP packet will be sent as ipv4 . #4882

Open
mayo11 opened this issue Aug 23, 2024 · 3 comments
Open
Labels
ebpf-psa Topics related to the eBPF PSA back end question This is a topic requesting clarification.

Comments

@mayo11
Copy link

mayo11 commented Aug 23, 2024

Hello,As a newcomer to the P4 language,I have some question...
I found that ebpf backends does not have tc's ingress and egress framework model to offer,only xdp_model.
I try to use the PSA framework to make a demo, remove the vlan header in the ingress of tc, and add the vlan header on the egress, so that the NIC port can communicate directly with the vlan interface.

I found that when I set NTK to true, the current packet will pass through return "bpf_redirect(skb->ifindex, BPF_F_INGRESS);" and enter the xdp_helper again, and the arp packet will be xdp_helper modified eth_type to ipv4 type, and it will be directly uploaded when entering the ingress by "return TC_ACT_OK;", and the packet eth_type is still 0x0800, and it is not modified to the original ARP (0x0806),ARP packets cannot be delivered to the port correctly!!

I don't know if it's my P4 code that is problematic, please take a look, thank a lot!!!

the necessary part of generate C code:

    SEC("classifier/tc-ingress")
    int tc_ingress_func(struct __sk_buff *skb) {
        struct psa_global_metadata *compiler_meta__ = (struct psa_global_metadata *) skb->cb;
        if (compiler_meta__->pass_to_kernel == true) {
            bpf_printk("at NTK");
            return TC_ACT_OK;
        }
        
        if (compiler_meta__->packet_path == NORMAL) {
            compiler_meta__->mark = 153;
            struct internal_metadata *md = (struct internal_metadata *)(unsigned long)skb->data_meta;
            if ((void *) ((struct internal_metadata *) md + 1) <= (void *)(long)skb->data) {
                __u16 *ether_type = (__u16 *) ((void *) (long)skb->data + 12);
                if ((void *) ((__u16 *) ether_type + 1) > (void *) (long) skb->data_end) {
                    return TC_ACT_SHOT;
                }
                *ether_type = md->pkt_ether_type;
                bpf_printk("in ingress ,eth proto %d", *ether_type);
            }
        }

        if (!ostd.drop && ostd.egress_port == 0) {
            compiler_meta__->pass_to_kernel = true;
            bpf_printk("at NTK judge ,eth proto");
            // return TC_ACT_OK;
            return bpf_redirect(skb->ifindex, BPF_F_INGRESS);
        }
        return bpf_redirect(ostd.egress_port, 0);
    }

The P4 code:

    #include <core.p4>
    #include <psa.p4>
    #define ETH_P_8021Q 0x8100

    typedef bit<48> ethernet_addr_t;

    header ethernet_h {
        ethernet_addr_t dstAddr;
        ethernet_addr_t srcAddr;
        bit<16>         etherType;
    }

    header vlan_h {
        bit<3>  pcp;
        bit<1>  dei;
        bit<12> vid;
        bit<16> tpid;
    }

    struct headers_t {
        ethernet_h ethernet;
        vlan_h     vlan;
    }

    struct local_metadata_t {

    }

    struct empty_metadata_t {
    }

    parser packet_parser(packet_in packet, out headers_t hdr, inout local_metadata_t local_metadata, 
                        in psa_ingress_parser_input_metadata_t standard_metadata, in empty_metadata_t resub_meta, 
                        in empty_metadata_t recirc_meta) {
        state start {
            packet.extract(hdr.ethernet);
            transition select(hdr.ethernet.etherType) {
                16w0x8100: vlan;
                default: accept;
            }
        }

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

    control ingress(inout headers_t hdr, inout local_metadata_t local_metadata, in psa_ingress_input_metadata_t standard_metadata,
                    inout psa_ingress_output_metadata_t ostd) {
        apply {
            if (hdr.vlan.isValid()) {
                hdr.ethernet.etherType = hdr.vlan.tpid;
                hdr.vlan.setInvalid();
            }
            // ostd.egress_port = (PortId_t)0;
            ostd.drop = false;
        }
    }

    control packet_deparser(packet_out packet, out empty_metadata_t clone_i2e_meta, out empty_metadata_t resubmit_meta,
                            out empty_metadata_t normal_meta, inout headers_t hdr, in local_metadata_t local_metadata,
                            in psa_ingress_output_metadata_t istd) {

        apply {
            packet.emit(hdr.ethernet);
            packet.emit(hdr.vlan);
        }

    }

    parser egress_parser(packet_in packet, out headers_t hdr, inout local_metadata_t local_metadata,
                        in psa_egress_parser_input_metadata_t istd, in empty_metadata_t normal_meta, 
                        in empty_metadata_t clone_i2e_meta, in empty_metadata_t clone_e2e_meta) {
        state start {
            packet.extract(hdr.ethernet);
            transition select(hdr.ethernet.etherType) {
                16w0x8100: vlan;
                default: accept;
            }
        }

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

    control egress(inout headers_t hdr, inout local_metadata_t local_metadata, in psa_egress_input_metadata_t istd, 
                inout psa_egress_output_metadata_t ostd) {
        apply {
            if (!hdr.vlan.isValid()){
                hdr.vlan.setValid();
                hdr.vlan.tpid = hdr.ethernet.etherType;
                hdr.ethernet.etherType = ETH_P_8021Q;
                hdr.vlan.pcp = 0;
                hdr.vlan.dei = 0;
                hdr.vlan.vid = 2;
            }
        }
    }

    control egress_deparser(packet_out packet, out empty_metadata_t clone_e2e_meta, out empty_metadata_t recirculate_meta, 
                            inout headers_t hdr, in local_metadata_t local_metadata, in psa_egress_output_metadata_t istd,
                            in psa_egress_deparser_input_metadata_t edstd) {
        apply {
            packet.emit(hdr.ethernet);
            packet.emit(hdr.vlan);
        }
    }


    IngressPipeline(packet_parser(), ingress(), packet_deparser()) ip;

    EgressPipeline(egress_parser(), egress(), egress_deparser()) ep;

    PSA_Switch(ip, PacketReplicationEngine(), ep, BufferingQueueingEngine()) main;
@jafingerhut
Copy link
Contributor

I am not sure, but you might get a wider audience for your question by posting it on the general channel of the P4 Zulip instance here https://p4lang.zulipchat.com

Github issues on this repository are better focused on bugs in, or desired enhancements to, the P4 compiler.

If you do ask your question there, I would suggest making it clear which P4 back end you are trying to use, e.g. are you using the p4tc back end? One of the ebpf/ubpf back ends? That wasn't clear to me from your question. I would also recommend publishing your P4 program in a public repository, perhaps on github.com, and linking to it from your question.

@fruffy fruffy added question This is a topic requesting clarification. ebpf-psa Topics related to the eBPF PSA back end labels Aug 24, 2024
@fruffy
Copy link
Collaborator

fruffy commented Aug 24, 2024

@tatry @osinstom

@mayo11
Copy link
Author

mayo11 commented Aug 25, 2024

I am not sure, but you might get a wider audience for your question by posting it on the general channel of the P4 Zulip instance here https://p4lang.zulipchat.com

Github issues on this repository are better focused on bugs in, or desired enhancements to, the P4 compiler.

If you do ask your question there, I would suggest making it clear which P4 back end you are trying to use, e.g. are you using the p4tc back end? One of the ebpf/ubpf back ends? That wasn't clear to me from your question. I would also recommend publishing your P4 program in a public repository, perhaps on github.com, and linking to it from your question.

Thank you for your reply,The back ends I use are ebpf psa, and my P4 example code is the P4 code I posted. Thank you for your suggestion. I will consider raising my questions on P4 Zulip. Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ebpf-psa Topics related to the eBPF PSA back end question This is a topic requesting clarification.
Projects
None yet
Development

No branches or pull requests

3 participants