05-ethernet.cpp 5.1 KB

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