05-ethernet.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include "limbo/ethernet/state.hpp"
  2. #include "test-utils.h"
  3. using namespace limbo;
  4. uint8_t example_raw[]{
  5. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x48, 0xba, 0x4e, 0x51, 0x39,
  6. 0xbb, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01,
  7. 0x48, 0xba, 0x4e, 0x51, 0x39, 0xbb, 0xc0, 0xa8, 0x65, 0x01, 0x00,
  8. 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x65, 0x02, 0x00, 0x00,
  9. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  10. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  11. };
  12. auto example_chunk = Chunk(example_raw, sizeof(example_raw));
  13. uint8_t crc_example[] = {0x00, 0x4a, 0x39, 0x02};
  14. auto payload_raw = example_raw + 6 + 6 + 2;
  15. auto payload_chunk = Chunk(payload_raw, example_chunk.size() - (6 + 6 + 2 + 4));
  16. auto src = ethernet::MacAddress(example_raw + 6);
  17. auto dst = ethernet::MacAddress(example_raw);
  18. using State = ethernet::State<void>;
  19. using Context = typename State::Context;
  20. using Packet = typename State::Packet;
  21. TEST_CASE("send", "[ethernet]") {
  22. char buff[sizeof(example_raw)];
  23. auto buff_chunk = Chunk(buff, sizeof(example_raw));
  24. auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
  25. auto state = State();
  26. SECTION("no enough space") {
  27. SECTION("zero buff") {
  28. auto zero_chunk = Chunk(buff, 0);
  29. auto result = Packet::send(state, ctx, zero_chunk, payload_chunk);
  30. REQUIRE(!result);
  31. CHECK(result.state() == &state);
  32. CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
  33. }
  34. SECTION("small buff") {
  35. auto zero_chunk = Chunk(buff, 63);
  36. auto result = Packet::send(state, ctx, zero_chunk, payload_chunk);
  37. REQUIRE(!result);
  38. CHECK(result.state() == &state);
  39. CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
  40. }
  41. SECTION("small buff") {
  42. auto small_payload = Chunk(buff, 5);
  43. auto result = Packet::send(state, ctx, buff_chunk, small_payload);
  44. REQUIRE(!result);
  45. CHECK(result.state() == &state);
  46. CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
  47. }
  48. }
  49. auto result = Packet::send(state, ctx, buff_chunk, payload_chunk);
  50. REQUIRE(result);
  51. auto res_buff = result.consumed();
  52. CHECK((void *)res_buff.data() == (void *)buff);
  53. CHECK(res_buff.size() == example_chunk.size());
  54. CHECK(res_buff == example_chunk);
  55. }
  56. TEST_CASE("recv/success", "[ethernet]") {
  57. auto state = State();
  58. auto result = state.recv(example_chunk, nullptr);
  59. CHECK(result);
  60. CHECK(result.consumed() == example_chunk);
  61. CHECK(result.state() == &state);
  62. auto &packet = state.get_parsed();
  63. CHECK(packet.source == src);
  64. CHECK(packet.destination == dst);
  65. CHECK(packet.type == (uint16_t)ethernet::EtherType::arp);
  66. CHECK(packet.crc == 0);
  67. CHECK(packet.payload == payload_chunk);
  68. }
  69. TEST_CASE("recv/incomplete", "[ethernet]") {
  70. auto state = State();
  71. auto chunk = Chunk(example_raw, 63);
  72. auto result = state.recv(chunk, nullptr);
  73. REQUIRE(!result);
  74. CHECK(result.state() == &state);
  75. CHECK(result.error_code() == (uint32_t)Errc::ethernet_malformed_frame);
  76. CHECK(result.consumed() == chunk);
  77. }
  78. TEST_CASE("crc32", "[ethernet]") {
  79. using O = ethernet::Opts;
  80. auto constexpr opts = ((int)O::calculate_crc) | ((int)O::validate_crc);
  81. using State = ethernet::State<void, opts>;
  82. using Context = typename State::Context;
  83. using Packet = typename State::Packet;
  84. char example_with_crc[sizeof(example_raw)];
  85. memcpy(example_with_crc, example_raw, example_chunk.size());
  86. memcpy(example_with_crc + example_chunk.size() - 4, crc_example, 4);
  87. auto example_crc = Chunk(example_with_crc, example_chunk.size());
  88. SECTION("send") {
  89. char buff[sizeof(example_raw)];
  90. auto buff_chunk = Chunk(buff, sizeof(example_raw));
  91. auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
  92. auto state = State();
  93. auto result = Packet::send(state, ctx, buff_chunk, payload_chunk);
  94. REQUIRE(result);
  95. auto res_buff = result.consumed();
  96. CHECK((void *)res_buff.data() == (void *)buff);
  97. CHECK(res_buff.size() == example_crc.size());
  98. CHECK(res_buff == example_crc);
  99. };
  100. SECTION("recv") {
  101. auto state = State();
  102. auto result = state.recv(example_crc, nullptr);
  103. CHECK(result);
  104. CHECK(result.consumed() == example_crc);
  105. CHECK(result.state() == &state);
  106. auto &packet = state.get_parsed();
  107. CHECK(packet.source == src);
  108. CHECK(packet.destination == dst);
  109. CHECK(packet.type == (uint16_t)ethernet::EtherType::arp);
  110. CHECK(packet.crc == 0x2394a00);
  111. CHECK(packet.payload == payload_chunk);
  112. }
  113. SECTION("recv/crc mismatch") {
  114. auto state = State();
  115. auto result = state.recv(example_chunk, nullptr);
  116. CHECK(!result);
  117. CHECK(result.consumed() == example_chunk);
  118. CHECK(result.state() == &state);
  119. CHECK(result.error_code() == (uint32_t)Errc::ethernet_crc_mismatch);
  120. }
  121. }