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

Commit

Permalink
csum: add csum_replace4 for 4-byte value
Browse files Browse the repository at this point in the history
Test using tcp/udp, modify both 16-bit port and 32-bit address,
see xdp7.p4 for example.
  • Loading branch information
williamtu committed Mar 1, 2017
1 parent a43b08c commit 2b9833a
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 3 deletions.
4 changes: 4 additions & 0 deletions p4include/xdp_model.p4
Expand Up @@ -59,6 +59,10 @@ extern bit<16> csum_replace2(in bit<16> csum, // current csum
in bit<16> old, // old value of the field
in bit<16> new);

extern bit<16> csum_replace4(in bit<16> csum,
in bit<32> old,
in bit<32> new);

extern bit<32> BPF_PERF_EVENT_OUTPUT();
// FIXME: use 64 bit
extern bit<32> BPF_KTIME_GET_NS();
Expand Down
23 changes: 20 additions & 3 deletions tests/xdp7.p4
Expand Up @@ -16,14 +16,14 @@ header IPv4 {
bit<13> fragOffset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdrChecksum;
bit<16> checksum;
bit<32> srcAddr;
bit<32> dstAddr;
}

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

header tcp_t {
Expand Down Expand Up @@ -92,21 +92,38 @@ control Ingress(inout Headers hd, in xdp_input xin, out xdp_output xout) {
// from, to are host byte order
bit<16> from;
bit<16> to;
bit<32> from_addr;
bit<32> to_addr;

action Fallback_action()
{
// UDP
#if 0
// UDP port
from = hd.udp.dstPort;
to = 16w0x400;
hd.udp.dstPort = to;
hd.udp.checksum = csum_replace2(hd.udp.checksum, from, to);

// UDP IP addr
from_addr = hd.ipv4.dstAddr;
to_addr = 32w0x01020304;
hd.ipv4.dstAddr = to_addr;
hd.ipv4.checksum = csum_replace4(hd.ipv4.checksum, from_addr, to_addr);
hd.udp.checksum = csum_replace4(hd.udp.checksum, from_addr, to_addr);
#endif
// TCP
from = hd.tcp.srcPort;
to = 16w0x841;
hd.tcp.srcPort = to;
hd.tcp.checksum = csum_replace2(hd.tcp.checksum, from, to);

// TCP IP addr
from_addr = hd.ipv4.srcAddr;
to_addr = 32w0x05060708;
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);

xoutdrop = false;
}

Expand Down
2 changes: 2 additions & 0 deletions xdpModel.h
Expand Up @@ -65,6 +65,7 @@ class XDPModel : public EBPF::EBPFModel {
XDPModel() : EBPF::EBPFModel(), xdp(), inputMetadataModel(), outputMetadataModel(),
ipv4_checksum("ebpf_ipv4_checksum"), bpf_event_output("bpf_event_output"),
bpf_ktime_get_ns("bpf_ktime_get_ns"), csum_replace2("csum_replace2"),
csum_replace4("csum_replace4"),
action_enum()
{}

Expand All @@ -75,6 +76,7 @@ class XDPModel : public EBPF::EBPFModel {
OutputMetadataModel outputMetadataModel;
::Model::Extern_Model ipv4_checksum;
::Model::Extern_Model csum_replace2;
::Model::Extern_Model csum_replace4;
::Model::Extern_Model bpf_event_output;
::Model::Extern_Model bpf_ktime_get_ns;
XDP_Action_Model action_enum;
Expand Down
23 changes: 23 additions & 0 deletions xdpProgram.cpp
Expand Up @@ -150,6 +150,29 @@ void XDPProgram::emitC(EBPF::CodeBuilder* builder, cstring headerFile) {
" return (~csum16_add(csum16_sub(~csum, old), new));\n"
"}\n");

builder->appendLine(
"inline u16 csum_fold(u32 csum) {\n"
" u32 r = csum << 16 | csum >> 16;\n"
" csum = ~csum;\n"
" csum -= r;\n"
" return (u16)(csum >> 16);\n"
"}\n"
"inline u32 csum_unfold(u16 csum) {\n"
" return (u32)csum;\n"
"}\n"
"inline u32 csum32_add(u32 csum, u32 addend) {\n"
" u32 res = csum;\n"
" res += addend;\n"
" return (res + (res < addend));\n"
"}\n"
"inline u32 csum32_sub(u32 csum, u32 addend) {\n"
" return csum32_add(csum, ~addend);\n"
"}\n"
"inline u16 csum_replace4(u16 csum, u32 from, u32 to) {\n"
" u32 tmp = csum32_sub(~csum_unfold(csum), from);\n"
" return csum_fold(csum32_add(tmp, to));\n"
"}\n");

builder->appendLine(
"struct bpf_map_def SEC(\"maps\") perf_event = {\n"
" .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,\n"
Expand Down

0 comments on commit 2b9833a

Please sign in to comment.