p4c
p4c copied to clipboard
Testing hash tuple data with ebpf psa
This is the P4 program used to test ebpf psa. I am chasing testing of StructExpression
by using a hash in P4 code.
./p4c-ebpf --arch psa --target kernel -o out.c ../backends/ebpf/psa/examples/upf.p4
$ git diff examples/upf.p4
diff --git a/backends/ebpf/psa/examples/upf.p4 b/backends/ebpf/psa/examples/upf.p4
index 806831476..814eceea0 100644
--- a/backends/ebpf/psa/examples/upf.p4
+++ b/backends/ebpf/psa/examples/upf.p4
@@ -146,6 +146,7 @@ struct upf_meta_t {
struct metadata {
upf_meta_t upf;
+ bit<16> hash;
}
struct headers {
@@ -338,6 +339,7 @@ control upf_ingress(
in psa_ingress_input_metadata_t istd,
inout psa_ingress_output_metadata_t ostd) {
+ Hash<bit<16>>(PSA_HashAlgorithm_t.CRC16) h;
action drop() {
ingress_drop(ostd);
@@ -481,6 +483,8 @@ control upf_ingress(
apply {
+ bit<16> hash_value = h.get_hash({meta.upf.gtpu_local_ip});
+
source_interface_lookup_by_port.apply();
if (gtpu.isValid()) {
if (session_lookup_by_teid.apply().hit) {
The out.c
file has this code which I don't understand - why is there no struct for hash data in generated code?
/* upf_ingress_h.get_hash({meta->upf.gtpu_local_ip}) */
crc16_finalize(ingress_upf_ingress_h_reg);
I see this commit added code to process StructExpression
by a backend but no P4 program exists in the commit to test this new processing.
https://github.com/p4lang/p4c/commit/c794fb4aa8968f976bb0842b45543fdc5fe9fab1
The
out.c
file has this code which I don't understand - why is there no struct for hash data in generated code?/* upf_ingress_h.get_hash({meta->upf.gtpu_local_ip}) */ crc16_finalize(ingress_upf_ingress_h_reg);
Implemented algorithm calculate hash based on definition, so it require register variable and input data. Struct for hash data should be generated (as far I remember), but it is not used at all. Each field of data is passed to the crc16_update
function (it can be called multiple times) to update the register value based on input data. Some CRC algorithms after data process transform register value (e.g. by xor with some value), that's why crc16_finalize
function exists, because implementation for CRC16 and CRC32 is the same. See https://github.com/p4lang/p4c/commit/77ddb3e82d6bd4f0e9f9206c7c2b7e9a456eccdc
There are at least two reasons why there is no struct used for hash data in generated code:
- Save stack space. Stack size for eBPF is 512B size, so it is desired to not have multiple copies of the same data. Another case is header fields larger than 512 bytes which can't be placed on stack, but they are supported by compiler, because bpf array map is used for headers.
- It is not easy to calculate hash over structure as a block of data. For hash calculation bits (in byte) and byte order is important and structure defined by compiler is not usable for this task. First, fields must have changed byte order, which require some preparation. Also, when bit fields are used, they must be defined in right way (different from defined by P4 program). Second, there must be no padding, even for fields smaller than 8 bit.
I see this commit added code to process
StructExpression
by a backend but no P4 program exists in the commit to test this new processing.
For example see hash-crc16.p4 test P4 program, added by later commit.