diff options
| author | Andrey Konovalov <andreyknvl@google.com> | 2017-04-27 20:31:00 +0200 |
|---|---|---|
| committer | Andrey Konovalov <andreyknvl@google.com> | 2017-05-12 15:47:59 +0200 |
| commit | ac0c70f74a5badbebec721c2be0602ea98c0437b (patch) | |
| tree | 69278d03cdaae547c1c87a84deb44969081837bd /executor/executor.cc | |
| parent | b2dbb4f4d10f436088ba8a1d2d18437911a83887 (diff) | |
prog, executor: move checksum computation to executor
This commit moves checksum computation to executor. This will allow to embed
dynamically generated values (like TCP sequence numbers) into packets.
Diffstat (limited to 'executor/executor.cc')
| -rw-r--r-- | executor/executor.cc | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/executor/executor.cc b/executor/executor.cc index 63d66d435..52da3a16b 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -57,6 +57,7 @@ const uint64_t instr_copyout = -3; const uint64_t arg_const = 0; const uint64_t arg_result = 1; const uint64_t arg_data = 2; +const uint64_t arg_csum = 3; // We use the default value instead of results of failed syscalls. // -1 is an invalid fd and an invalid address and deterministic, @@ -115,6 +116,13 @@ struct thread_t { thread_t threads[kMaxThreads]; +// Checksum kinds. +const uint64_t arg_csum_inet = 0; + +// Checksum chunk kinds. +const uint64_t arg_csum_chunk_data = 0; +const uint64_t arg_csum_chunk_const = 1; + void execute_one(); uint64_t read_input(uint64_t** input_posp, bool peek = false); uint64_t read_arg(uint64_t** input_posp); @@ -354,6 +362,52 @@ retry: read_input(&input_pos); break; } + case arg_csum: { + debug("checksum found at %llx\n", addr); + char* csum_addr = addr; + uint64_t csum_size = size; + uint64_t csum_kind = read_input(&input_pos); + switch (csum_kind) { + case arg_csum_inet: { + if (csum_size != 2) { + fail("inet checksum must be 2 bytes, not %lu", size); + } + debug("calculating checksum for %llx\n", csum_addr); + struct csum_inet csum; + csum_inet_init(&csum); + uint64_t chunks_num = read_input(&input_pos); + uint64_t chunk; + for (chunk = 0; chunk < chunks_num; chunk++) { + uint64_t chunk_kind = read_input(&input_pos); + uint64_t chunk_value = read_input(&input_pos); + uint64_t chunk_size = read_input(&input_pos); + switch (chunk_kind) { + case arg_csum_chunk_data: + debug("#%d: data chunk, addr: %llx, size: %llu\n", chunk, chunk_value, chunk_size); + NONFAILING(csum_inet_update(&csum, (const uint8_t*)chunk_value, chunk_size)); + break; + case arg_csum_chunk_const: + if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) { + fail("bad checksum const chunk size %lld\n", chunk_size); + } + // Here we assume that const values come to us big endian. + debug("#%d: const chunk, value: %llx, size: %llu\n", chunk, chunk_value, chunk_size); + csum_inet_update(&csum, (const uint8_t*)&chunk_value, chunk_size); + break; + default: + fail("bad checksum chunk kind %lu", chunk_kind); + } + } + int16_t csum_value = csum_inet_digest(&csum); + debug("writing inet checksum %hx to %llx\n", csum_value, csum_addr); + NONFAILING(copyin(csum_addr, csum_value, 2, 0, 0)); + break; + } + default: + fail("bad checksum kind %lu", csum_kind); + } + break; + } default: fail("bad argument type %lu", typ); } |
