123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- #include "limbo/ethernet/state.hpp"
- #include "test-utils.h"
- using namespace limbo;
- uint8_t example_raw[]{
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x48, 0xba, 0x4e, 0x51, 0x39, 0xbb,
- 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x48, 0xba,
- 0x4e, 0x51, 0x39, 0xbb, 0xc0, 0xa8, 0x65, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xa8, 0x65, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
- auto example_chunk = Chunk(example_raw, sizeof(example_raw));
- uint8_t crc_example[] = {0x00, 0x4a, 0x39, 0x02};
- auto payload_raw = example_raw + 6 + 6 + 2;
- auto payload_chunk = Chunk(payload_raw, example_chunk.size() - (6 + 6 + 2));
- auto src = ethernet::MacAddress(example_raw + 6);
- auto dst = ethernet::MacAddress(example_raw);
- using State = ethernet::State<void>;
- using Context = typename State::Context;
- using Packet = typename State::Packet;
- TEST_CASE("send", "[ethernet]") {
- char buff[sizeof(example_raw)];
- auto buff_chunk = Chunk(buff, sizeof(example_raw));
- auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
- auto state = State();
- SECTION("no enough space") {
- SECTION("zero buff") {
- auto zero_chunk = Chunk(buff, 0);
- auto result = Packet::send(state, ctx, zero_chunk, payload_chunk);
- REQUIRE(!result);
- CHECK(result.state() == &state);
- CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
- }
- SECTION("small buff") {
- auto zero_chunk = Chunk(buff, 63 - 4);
- auto result = Packet::send(state, ctx, zero_chunk, payload_chunk);
- REQUIRE(!result);
- CHECK(result.state() == &state);
- CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
- }
- }
- SECTION("normal payload") {
- auto result = Packet::send(state, ctx, buff_chunk, payload_chunk);
- REQUIRE(result);
- auto res_buff = result.consumed();
- CHECK((void *)res_buff.data() == (void *)buff);
- CHECK(res_buff.size() == example_chunk.size());
- CHECK(res_buff == example_chunk);
- }
- SECTION("small payload") {
- auto small_payload = Chunk(buff + payload_chunk.size() - 5, 5);
- auto result = Packet::send(state, ctx, buff_chunk, small_payload);
- REQUIRE(result);
- auto res_buff = result.consumed();
- CHECK((void *)res_buff.data() == (void *)buff);
- CHECK(res_buff.size() == 60);
- }
- SECTION("unknown dest") {
- ctx.destination = ethernet::MacAddress::unknown;
- auto result = Packet::send(state, ctx, buff_chunk, payload_chunk);
- REQUIRE(!result);
- CHECK(result.state() == &state);
- CHECK(result.error_code() == (uint32_t)Errc::ethernet_unknown_mac);
- }
- }
- TEST_CASE("send without content", "[ethernet]") {
- char buff[sizeof(example_raw)];
- auto buff_chunk = Chunk(buff, sizeof(example_raw));
- auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
- auto state = State();
- SECTION("no enough space") {
- SECTION("zero buff") {
- auto zero_chunk = Chunk(buff, 0);
- auto result = Packet::send<false>(state, ctx, zero_chunk, payload_chunk);
- REQUIRE(!result);
- CHECK(result.state() == &state);
- CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
- }
- SECTION("small buff") {
- auto zero_chunk = Chunk(buff, 63 - 4);
- auto result = Packet::send<false>(state, ctx, zero_chunk, payload_chunk);
- REQUIRE(!result);
- CHECK(result.state() == &state);
- CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
- }
- }
- SECTION("normal payload") {
- auto result = Packet::send<false>(state, ctx, buff_chunk, payload_chunk);
- REQUIRE(result);
- auto res_buff = result.consumed();
- CHECK((void *)res_buff.data() == (void *)buff);
- CHECK(res_buff.size() == 6 + 6 + 2);
- CHECK(res_buff == Chunk(example_raw, 6 + 6 + 2));
- }
- SECTION("small payload") {
- auto small_payload = Chunk(buff + payload_chunk.size() - 5, 5);
- auto result = Packet::send<false>(state, ctx, buff_chunk, small_payload);
- REQUIRE(result);
- auto res_buff = result.consumed();
- CHECK((void *)res_buff.data() == (void *)buff);
- CHECK(res_buff.size() == 6 + 6 + 2);
- }
- }
- TEST_CASE("recv/success", "[ethernet]") {
- auto state = State();
- auto result = state.recv(example_chunk, nullptr);
- CHECK(result);
- CHECK(result.consumed() == example_chunk);
- CHECK(result.state() == &state);
- auto &packet = state.get_parsed();
- CHECK(packet.source == src);
- CHECK(packet.destination == dst);
- CHECK(packet.type == (uint16_t)ethernet::EtherType::arp);
- CHECK(packet.crc == 0);
- CHECK(packet.payload == payload_chunk);
- }
- TEST_CASE("recv/incomplete", "[ethernet]") {
- auto state = State();
- auto chunk = Chunk(example_raw, 59);
- auto result = state.recv(chunk, nullptr);
- REQUIRE(!result);
- CHECK(result.state() == &state);
- CHECK(result.error_code() == (uint32_t)Errc::ethernet_malformed_frame);
- CHECK(result.consumed() == chunk);
- }
- TEST_CASE("crc32", "[ethernet]") {
- using O = ethernet::Opts;
- auto constexpr opts = ((int)O::calculate_crc) | ((int)O::validate_crc);
- using State = ethernet::State<void, opts>;
- using Context = typename State::Context;
- using Packet = typename State::Packet;
- char example_with_crc[sizeof(example_raw) + 4];
- memcpy(example_with_crc, example_raw, example_chunk.size());
- memcpy(example_with_crc + example_chunk.size(), crc_example, 4);
- auto example_crc = Chunk(example_with_crc, sizeof(example_with_crc));
- SECTION("send") {
- char buff[sizeof(example_raw) + 4];
- auto buff_chunk = Chunk(buff, sizeof(buff));
- auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
- auto state = State();
- auto result = Packet::send(state, ctx, buff_chunk, payload_chunk);
- REQUIRE(result);
- auto res_buff = result.consumed();
- CHECK((void *)res_buff.data() == (void *)buff);
- CHECK(res_buff.size() == example_crc.size());
- CHECK(res_buff == example_crc);
- };
- SECTION("send witout content") {
- char buff[sizeof(example_raw) + 4];
- auto buff_chunk = Chunk(buff, sizeof(buff));
- auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
- auto state = State();
- auto result = Packet::send<false>(state, ctx, buff_chunk, payload_chunk);
- REQUIRE(result);
- auto res_buff = result.consumed();
- CHECK((void *)res_buff.data() == (void *)buff);
- CHECK(res_buff.size() == 6 + 6 + 2 + 4);
- CHECK(Chunk(buff, 6 + 6 + 2) == Chunk(example_with_crc, 6 + 6 + 2));
- auto crc_chunk = Chunk(buff + 6 + 6 + 2, 4);
- auto crc_example = Chunk(example_with_crc + example_crc.size() - 4, 4);
- CHECK(crc_chunk == crc_example);
- };
- SECTION("recv") {
- auto state = State();
- auto result = state.recv(example_crc, nullptr);
- CHECK(result);
- CHECK(result.consumed() == example_crc);
- CHECK(result.state() == &state);
- auto &packet = state.get_parsed();
- CHECK(packet.source == src);
- CHECK(packet.destination == dst);
- CHECK(packet.type == (uint16_t)ethernet::EtherType::arp);
- CHECK(packet.crc == 0x2394a00);
- CHECK(packet.payload == payload_chunk);
- }
- SECTION("recv/crc mismatch") {
- auto state = State();
- memset(example_with_crc + example_crc.size() - 4, 0, 4);
- auto result = state.recv(example_crc, nullptr);
- CHECK(!result);
- CHECK(result.consumed() == example_crc);
- CHECK(result.state() == &state);
- CHECK(result.error_code() == (uint32_t)Errc::ethernet_crc_mismatch);
- }
- }
|