Skip to content
This repository has been archived by the owner on Jan 19, 2023. It is now read-only.

how to implement a forwoading function using XDP_TX based on xdp7.p4 #108

Open
kwjjyn opened this issue May 29, 2019 · 1 comment
Open
Labels

Comments

@kwjjyn
Copy link

kwjjyn commented May 29, 2019

Hi,
I want to implement a simple forwarding function based on xdp7.p4 by using XDP_TX.
What I thought is B send packets to A , then I load xdp program on A's driver, and then A modify the packet's mac address, ip address , tcp port .After all these , the modified packet is sent to C by using XDP_TX.
What the program does is set the packets' four tuple and mac address from B. And I write like this:

/*
    This program is based on xdp7.p4. The goal is to implement a simple forward behavior 
    by set the static ip dstAddr, tcp srcPort and dstPort.
*/

#include "xdp_model.p4"

header Ethernet {
    bit<48> destination;
    bit<48> source;
    bit<16> protocol;
}

header IPv4 {
    bit<4>  version;
    bit<4>  ihl;
    bit<8>  diffserv;
    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;
}

header icmp_t {
    bit<16> typeCode;
    bit<16> checksum;
}

header tcp_t {
    bit<16> srcPort;
    bit<16> dstPort;
    bit<32> seqNo;
    bit<32> ackNo;
    bit<4>  dataOffset;
    bit<4>  res;
    bit<8>  flags;
    bit<16> window;
    bit<16> checksum;
    bit<16> urgentPtr;
}

header udp_t {
    bit<16> srcPort;
    bit<16> dstPort;
    bit<16> length_;
    bit<16> checksum;
}


struct Headers {
    Ethernet ethernet;
    IPv4     ipv4;
    tcp_t   tcp;
    udp_t   udp;
    icmp_t icmp;
}

parser Parser(packet_in packet, out Headers hd) {
    state start {
        packet.extract(hd.ethernet);
        transition select(hd.ethernet.protocol) {
            16w0x800: parse_ipv4;
            default: accept;
        }
    }
    state parse_ipv4 {
        packet.extract(hd.ipv4);
        transition select(hd.ipv4.protocol) {
            8w6: parse_tcp;
            8w17: parse_udp;
            8w1: parse_icmp;
            default: accept;
        }
    }
    state parse_icmp {
        packet.extract(hd.icmp);
        transition accept;
    }
    state parse_tcp {
        packet.extract(hd.tcp);
        transition accept;
    }
    state parse_udp {
        packet.extract(hd.udp);
        transition accept;
    }
}

control Ingress(inout Headers hd, in xdp_input xin, out xdp_output xout) {

    bool xoutdrop = false;
    // from, to are host byte order
    bit<16> from;
    bit<16> to;
    bit<32> from_addr;
    bit<32> to_addr;
    bit<48> tmp;

    action Fallback_action()
    {

	// exchange ethernet's destination and source 
        tmp = hd.ethernet.source;
	hd.ethernet.source = hd.ethernet.destination;
        hd.ethernet.destination = tmp; 

        // TCP: set the packet's srcPort = 6666 , dstPort = 8888

        from = hd.tcp.srcPort;
        // srcPort: 6666
        to = 16w0x1a0a;    
        hd.tcp.srcPort = to;
        hd.tcp.checksum = csum_replace2(hd.tcp.checksum, from, to);
	    
        from = hd.tcp.dstPort;
        // dstPort: 8888
	to = 16w0x22b8;    
	hd.tcp.dstPort = to;
	hd.tcp.checksum = csum_replace2(hd.tcp.checksum, from, to);

        // IP: set the packet's srcAddr = dstAddr ,dstAddr = 172.16.100.1

        from_addr = hd.ipv4.srcAddr;
        // srcAddr = dstAddr
        to_addr = hd.ipv4.dstAddr;
        hd.ipv4.srcAddr = to_addr;
        hd.ipv4.checksum = csum_replace4(hd.ipv4.checksum, from_addr, to_addr);
        hd.tcp.checksum = csum_replace4(hd.tcp.checksum, from_addr, to_addr);
	    
        from_addr = hd.ipv4.dstAddr;
	// dstAddr = 172.16.100.1
        to_addr = 32w0xac106401;
	hd.ipv4.checksum = csum_replace4(hd.ipv4.checksum, from_addr, to_addr);
	hd.tcp.checksum = csum_replace4(hd.tcp.checksum, from_addr, to_addr);


        xoutdrop = false;
    }

    action Drop_action()
    {
        xoutdrop = true;
    }

    table dstmactable {
        key = { hd.ethernet.protocol : exact; }
        actions = {
            Fallback_action;
            Drop_action;
        }
        default_action = Fallback_action;
        implementation = hash_table(64);
    }

    apply {
        dstmactable.apply();
        xout.output_port = 0;
        // action set to XDP_TX
        xout.output_action = xoutdrop ? xdp_action.XDP_DROP : xdp_action.XDP_TX;
    }
}

control Deparser(in Headers hdrs, packet_out packet) {
    apply {
        packet.emit(hdrs.ethernet);
        packet.emit(hdrs.ipv4);

    // hit Verifier MAX_BPF_STACK issue
    //    packet.emit(hdrs.tcp);
    //    packet.emit(hdrs.udp);

        packet.emit(hdrs.icmp);
        packet.emit(hdrs.udp);
        packet.emit(hdrs.tcp);
    }
}

xdp(Parser(), Ingress(), Deparser()) main;

And I update the checksum . However this program could be compiled and loaded but seems not work as what I want.
Do I need to add ebpf_ipv4_checksum() to recalc the ipv4 checksum or anything else I forget to update ?
Could you give me some advices?
Thanks a lot!

@mihaibudiu
Copy link
Contributor

In which way does it not work as you want?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants