This repository was archived by the owner on Jan 19, 2023. It is now read-only.
  
  
  - 
                Notifications
    You must be signed in to change notification settings 
- Fork 26
    This repository was 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
Copy link
Copy link
Open
Labels
Description
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!