05-ethernet.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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("send without content", "[ethernet]") {
  66. char buff[sizeof(example_raw)];
  67. auto buff_chunk = Chunk(buff, sizeof(example_raw));
  68. auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
  69. auto state = State();
  70. SECTION("no enough space") {
  71. SECTION("zero buff") {
  72. auto zero_chunk = Chunk(buff, 0);
  73. auto result = Packet::send<false>(state, ctx, zero_chunk, payload_chunk);
  74. REQUIRE(!result);
  75. CHECK(result.state() == &state);
  76. CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
  77. }
  78. SECTION("small buff") {
  79. auto zero_chunk = Chunk(buff, 63 - 4);
  80. auto result = Packet::send<false>(state, ctx, zero_chunk, payload_chunk);
  81. REQUIRE(!result);
  82. CHECK(result.state() == &state);
  83. CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
  84. }
  85. }
  86. SECTION("normal payload") {
  87. auto result = Packet::send<false>(state, ctx, buff_chunk, payload_chunk);
  88. REQUIRE(result);
  89. auto res_buff = result.consumed();
  90. CHECK((void *)res_buff.data() == (void *)buff);
  91. CHECK(res_buff.size() == 6 + 6 + 2);
  92. CHECK(res_buff == Chunk(example_raw, 6 + 6 + 2));
  93. }
  94. SECTION("small payload") {
  95. auto small_payload = Chunk(buff + payload_chunk.size() - 5, 5);
  96. auto result = Packet::send<false>(state, ctx, buff_chunk, small_payload);
  97. REQUIRE(result);
  98. auto res_buff = result.consumed();
  99. CHECK((void *)res_buff.data() == (void *)buff);
  100. CHECK(res_buff.size() == 6 + 6 + 2);
  101. }
  102. }
  103. TEST_CASE("recv/success", "[ethernet]") {
  104. auto state = State();
  105. auto result = state.recv(example_chunk, nullptr);
  106. CHECK(result);
  107. CHECK(result.consumed() == example_chunk);
  108. CHECK(result.state() == &state);
  109. auto &packet = state.get_parsed();
  110. CHECK(packet.source == src);
  111. CHECK(packet.destination == dst);
  112. CHECK(packet.type == (uint16_t)ethernet::EtherType::arp);
  113. CHECK(packet.crc == 0);
  114. CHECK(packet.payload == payload_chunk);
  115. }
  116. TEST_CASE("recv/incomplete", "[ethernet]") {
  117. auto state = State();
  118. auto chunk = Chunk(example_raw, 59);
  119. auto result = state.recv(chunk, nullptr);
  120. REQUIRE(!result);
  121. CHECK(result.state() == &state);
  122. CHECK(result.error_code() == (uint32_t)Errc::ethernet_malformed_frame);
  123. CHECK(result.consumed() == chunk);
  124. }
  125. TEST_CASE("crc32", "[ethernet]") {
  126. using O = ethernet::Opts;
  127. auto constexpr opts = ((int)O::calculate_crc) | ((int)O::validate_crc);
  128. using State = ethernet::State<void, opts>;
  129. using Context = typename State::Context;
  130. using Packet = typename State::Packet;
  131. char example_with_crc[sizeof(example_raw) + 4];
  132. memcpy(example_with_crc, example_raw, example_chunk.size());
  133. memcpy(example_with_crc + example_chunk.size(), crc_example, 4);
  134. auto example_crc = Chunk(example_with_crc, sizeof(example_with_crc));
  135. SECTION("send") {
  136. char buff[sizeof(example_raw) + 4];
  137. auto buff_chunk = Chunk(buff, sizeof(buff));
  138. auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
  139. auto state = State();
  140. auto result = Packet::send(state, ctx, buff_chunk, payload_chunk);
  141. REQUIRE(result);
  142. auto res_buff = result.consumed();
  143. CHECK((void *)res_buff.data() == (void *)buff);
  144. CHECK(res_buff.size() == example_crc.size());
  145. CHECK(res_buff == example_crc);
  146. };
  147. SECTION("send witout content") {
  148. char buff[sizeof(example_raw) + 4];
  149. auto buff_chunk = Chunk(buff, sizeof(buff));
  150. auto ctx = Context{src, dst, ethernet::EtherType::arp, nullptr};
  151. auto state = State();
  152. auto result = Packet::send<false>(state, ctx, buff_chunk, payload_chunk);
  153. REQUIRE(result);
  154. auto res_buff = result.consumed();
  155. CHECK((void *)res_buff.data() == (void *)buff);
  156. CHECK(res_buff.size() == 6 + 6 + 2 + 4);
  157. CHECK(Chunk(buff, 6 + 6 + 2) == Chunk(example_with_crc, 6 + 6 + 2));
  158. auto crc_chunk = Chunk(buff + 6 + 6 + 2, 4);
  159. auto crc_example = Chunk(example_with_crc + example_crc.size() - 4, 4);
  160. CHECK(crc_chunk == crc_example);
  161. };
  162. SECTION("recv") {
  163. auto state = State();
  164. auto result = state.recv(example_crc, nullptr);
  165. CHECK(result);
  166. CHECK(result.consumed() == example_crc);
  167. CHECK(result.state() == &state);
  168. auto &packet = state.get_parsed();
  169. CHECK(packet.source == src);
  170. CHECK(packet.destination == dst);
  171. CHECK(packet.type == (uint16_t)ethernet::EtherType::arp);
  172. CHECK(packet.crc == 0x2394a00);
  173. CHECK(packet.payload == payload_chunk);
  174. }
  175. SECTION("recv/crc mismatch") {
  176. auto state = State();
  177. memset(example_with_crc + example_crc.size() - 4, 0, 4);
  178. auto result = state.recv(example_crc, nullptr);
  179. CHECK(!result);
  180. CHECK(result.consumed() == example_crc);
  181. CHECK(result.state() == &state);
  182. CHECK(result.error_code() == (uint32_t)Errc::ethernet_crc_mismatch);
  183. }
  184. }