[fuzzing] Teach server_fuzzer about the chaotic good protocol (#35643)

No explicit testing yet, just some building blocks

Closes #35643

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35643 from ctiller:shush-chaotic-protocol 48dcaa0632
PiperOrigin-RevId: 600928555
pull/35647/head
Craig Tiller 10 months ago committed by Copybara-Service
parent 2fc9dd1546
commit 7507e3b644
  1. 1
      test/core/end2end/fuzzers/BUILD
  2. 56
      test/core/end2end/fuzzers/fuzzer_input.proto
  3. 88
      test/core/end2end/fuzzers/network_input.cc

@ -91,6 +91,7 @@ grpc_cc_library(
deps = [ deps = [
"fuzzer_input_proto", "fuzzer_input_proto",
"//:chttp2_frame", "//:chttp2_frame",
"//src/core:chaotic_good_frame_header",
"//test/core/event_engine/fuzzing_event_engine", "//test/core/event_engine/fuzzing_event_engine",
"//test/core/util:fuzzing_channel_args", "//test/core/util:fuzzing_channel_args",
"//test/core/util:grpc_test_util_base", "//test/core/util:grpc_test_util_base",

@ -21,6 +21,8 @@ import "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto";
import "test/core/util/fuzz_config_vars.proto"; import "test/core/util/fuzz_config_vars.proto";
import "test/core/util/fuzzing_channel_args.proto"; import "test/core/util/fuzzing_channel_args.proto";
message Empty{};
message H2DataFrame { message H2DataFrame {
uint32 stream_id = 1; uint32 stream_id = 1;
bool end_of_stream = 2; bool end_of_stream = 2;
@ -63,6 +65,10 @@ message SimpleHeaders {
optional string grpclb_client_stats = 24; optional string grpclb_client_stats = 24;
optional string lb_token = 25; optional string lb_token = 25;
optional string lb_cost_bin = 26; optional string lb_cost_bin = 26;
optional string chaotic_good_connection_type = 27;
optional string chaotic_good_connection_id = 28;
optional string chaotic_good_alignment = 29;
} }
message H2HeaderFrame { message H2HeaderFrame {
@ -117,6 +123,55 @@ message H2WindowUpdateFrame {
message H2ClientPrefix {} message H2ClientPrefix {}
message ChaoticGoodServerFragment {
uint32 stream_id = 1;
oneof headers {
Empty headers_none = 11;
bytes headers_raw_bytes = 12;
SimpleHeaders headers_simple_header = 13;
}
oneof data {
Empty none = 21;
uint32 length = 22;
}
oneof trailers {
Empty trailers_none = 31;
bytes trailers_raw_bytes = 32;
SimpleHeaders trailers_simple_header = 33;
}
}
message ChaoticGoodMessageData {
uint32 length = 1;
uint32 padding = 2;
}
message ChaoticGoodFrame {
enum FrameType {
SETTINGS = 0;
FRAGMENT = 1;
CANCEL = 2;
};
uint32 stream_id = 1;
FrameType type = 2;
oneof headers {
Empty headers_none = 11;
bytes headers_raw_bytes = 12;
SimpleHeaders headers_simple_header = 13;
}
oneof data {
Empty data_none = 21;
ChaoticGoodMessageData data_sized = 23;
}
oneof trailers {
Empty trailers_none = 31;
bytes trailers_raw_bytes = 32;
SimpleHeaders trailers_simple_header = 33;
}
}
message ChaoticGoodSettings {}
message InputSegment { message InputSegment {
int32 delay_ms = 1; int32 delay_ms = 1;
oneof payload { oneof payload {
@ -131,6 +186,7 @@ message InputSegment {
H2WindowUpdateFrame window_update = 10; H2WindowUpdateFrame window_update = 10;
H2ClientPrefix client_prefix = 11; H2ClientPrefix client_prefix = 11;
uint32 repeated_zeros = 12; uint32 repeated_zeros = 12;
ChaoticGoodFrame chaotic_good = 13;
} }
} }

@ -28,6 +28,7 @@
#include <grpc/slice.h> #include <grpc/slice.h>
#include "src/core/ext/transport/chaotic_good/frame_header.h"
#include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/ext/transport/chttp2/transport/frame.h"
#include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/ext/transport/chttp2/transport/varint.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
@ -165,6 +166,17 @@ SliceBuffer SliceBufferFromSimpleHeaders(
if (headers.has_lb_cost_bin()) { if (headers.has_lb_cost_bin()) {
add_header("lb-cost-bin", headers.lb_cost_bin()); add_header("lb-cost-bin", headers.lb_cost_bin());
} }
if (headers.has_chaotic_good_connection_type()) {
add_header("chaotic-good-connection-type",
headers.chaotic_good_connection_type());
}
if (headers.has_chaotic_good_connection_id()) {
add_header("chaotic-good-connection-id",
headers.chaotic_good_connection_id());
}
if (headers.has_chaotic_good_alignment()) {
add_header("chaotic-good-alignment", headers.chaotic_good_alignment());
}
SliceBuffer buffer; SliceBuffer buffer;
buffer.Append(Slice::FromCopiedBuffer(temp.data(), temp.size())); buffer.Append(Slice::FromCopiedBuffer(temp.data(), temp.size()));
return buffer; return buffer;
@ -183,6 +195,77 @@ SliceBuffer SliceBufferFromHeaderPayload(const T& payload) {
return SliceBuffer(); return SliceBuffer();
} }
SliceBuffer ChaoticGoodFrame(const fuzzer_input::ChaoticGoodFrame& frame) {
chaotic_good::FrameHeader h;
SliceBuffer suffix;
h.stream_id = frame.stream_id();
switch (frame.type()) {
case fuzzer_input::ChaoticGoodFrame::SETTINGS:
h.type = chaotic_good::FrameType::kSettings;
break;
case fuzzer_input::ChaoticGoodFrame::FRAGMENT:
h.type = chaotic_good::FrameType::kFragment;
break;
case fuzzer_input::ChaoticGoodFrame::CANCEL:
h.type = chaotic_good::FrameType::kCancel;
break;
default:
break;
}
switch (frame.headers_case()) {
case fuzzer_input::ChaoticGoodFrame::kHeadersNone:
case fuzzer_input::ChaoticGoodFrame::HEADERS_NOT_SET:
break;
case fuzzer_input::ChaoticGoodFrame::kHeadersRawBytes:
if (frame.headers_raw_bytes().empty()) break;
h.header_length = frame.headers_raw_bytes().size();
h.flags.Set(0, true);
suffix.Append(Slice::FromCopiedString(frame.headers_raw_bytes()));
break;
case fuzzer_input::ChaoticGoodFrame::kHeadersSimpleHeader: {
SliceBuffer append =
SliceBufferFromSimpleHeaders(frame.headers_simple_header());
if (append.Length() == 0) break;
h.header_length = append.Length();
h.flags.Set(0, true);
suffix.Append(append.JoinIntoSlice());
} break;
}
switch (frame.data_case()) {
case fuzzer_input::ChaoticGoodFrame::kDataNone:
case fuzzer_input::ChaoticGoodFrame::DATA_NOT_SET:
break;
case fuzzer_input::ChaoticGoodFrame::kDataSized:
h.flags.Set(1, true);
h.message_length = frame.data_sized().length();
h.message_padding = frame.data_sized().padding();
break;
}
switch (frame.trailers_case()) {
case fuzzer_input::ChaoticGoodFrame::kTrailersNone:
case fuzzer_input::ChaoticGoodFrame::TRAILERS_NOT_SET:
break;
case fuzzer_input::ChaoticGoodFrame::kTrailersRawBytes:
h.trailer_length = frame.trailers_raw_bytes().size();
h.flags.Set(2, true);
suffix.Append(Slice::FromCopiedString(frame.trailers_raw_bytes()));
break;
case fuzzer_input::ChaoticGoodFrame::kTrailersSimpleHeader: {
SliceBuffer append =
SliceBufferFromSimpleHeaders(frame.trailers_simple_header());
h.trailer_length = append.Length();
h.flags.Set(2, true);
suffix.Append(append.JoinIntoSlice());
} break;
}
uint8_t bytes[24];
h.Serialize(bytes);
SliceBuffer out;
out.Append(Slice::FromCopiedBuffer(bytes, 24));
out.Append(suffix);
return out;
}
grpc_slice SliceFromSegment(const fuzzer_input::InputSegment& segment) { grpc_slice SliceFromSegment(const fuzzer_input::InputSegment& segment) {
switch (segment.payload_case()) { switch (segment.payload_case()) {
case fuzzer_input::InputSegment::kRawBytes: case fuzzer_input::InputSegment::kRawBytes:
@ -244,6 +327,11 @@ grpc_slice SliceFromSegment(const fuzzer_input::InputSegment& segment) {
zeros.resize(std::min<size_t>(segment.repeated_zeros(), 128 * 1024), 0); zeros.resize(std::min<size_t>(segment.repeated_zeros(), 128 * 1024), 0);
return grpc_slice_from_copied_buffer(zeros.data(), zeros.size()); return grpc_slice_from_copied_buffer(zeros.data(), zeros.size());
} }
case fuzzer_input::InputSegment::kChaoticGood: {
return ChaoticGoodFrame(segment.chaotic_good())
.JoinIntoSlice()
.TakeCSlice();
} break;
case fuzzer_input::InputSegment::PAYLOAD_NOT_SET: case fuzzer_input::InputSegment::PAYLOAD_NOT_SET:
break; break;
} }

Loading…
Cancel
Save