mip_test.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. #define MG_ENABLE_SOCKET 0
  2. #define MG_ENABLE_LINES 1
  3. #define MG_ENABLE_TCPIP 1
  4. #define MG_ENABLE_PACKED_FS 0
  5. #include "mongoose.c"
  6. #include "driver_mock.c"
  7. static int s_num_tests = 0;
  8. static bool s_sent_fragment = 0;
  9. static int s_seg_sent = 0;
  10. #define ASSERT(expr) \
  11. do { \
  12. s_num_tests++; \
  13. if (!(expr)) { \
  14. printf("FAILURE %s:%d: %s\n", __FILE__, __LINE__, #expr); \
  15. abort(); \
  16. } \
  17. } while (0)
  18. static void test_statechange(void) {
  19. char tx[1540];
  20. struct mg_tcpip_if iface;
  21. memset(&iface, 0, sizeof(iface));
  22. iface.ip = mg_htonl(0x01020304);
  23. iface.state = MG_TCPIP_STATE_READY;
  24. iface.tx.ptr = tx, iface.tx.len = sizeof(tx);
  25. iface.driver = &mg_tcpip_driver_mock;
  26. onstatechange(&iface);
  27. }
  28. static void ph(struct mg_connection *c, int ev, void *ev_data) {
  29. if (ev == MG_EV_POLL) ++(*(int *) c->fn_data);
  30. (void) c, (void) ev_data;
  31. }
  32. static void fn(struct mg_connection *c, int ev, void *ev_data) {
  33. (void) c, (void) ev, (void) ev_data;
  34. }
  35. static void frag_recv_fn(struct mg_connection *c, int ev, void *ev_data) {
  36. if (ev == MG_EV_ERROR) {
  37. if (s_sent_fragment) {
  38. ASSERT(strcmp((char*) ev_data, "Received fragmented packet") == 0);
  39. }
  40. }
  41. (void) c, (void) ev_data;
  42. }
  43. static void frag_send_fn(struct mg_connection *c, int ev, void *ev_data) {
  44. static bool s_sent;
  45. static int s_seg_sizes[] = {416, 416, 368};
  46. if (ev == MG_EV_POLL) {
  47. if (!s_sent) {
  48. c->send.len = 1200; // setting TCP payload size
  49. s_sent = true;
  50. }
  51. } else if (ev == MG_EV_WRITE) {
  52. // Checking TCP segment sizes (ev_data points to the TCP payload length)
  53. ASSERT(*(int *) ev_data == s_seg_sizes[s_seg_sent++]);
  54. }
  55. (void) c, (void) ev_data;
  56. }
  57. static void test_poll(void) {
  58. int count = 0, i;
  59. struct mg_mgr mgr;
  60. mg_mgr_init(&mgr);
  61. struct mg_tcpip_if mif;
  62. memset(&mif, 0, sizeof(mif));
  63. mif.driver = &mg_tcpip_driver_mock;
  64. mg_tcpip_init(&mgr, &mif);
  65. mg_http_listen(&mgr, "http://127.0.0.1:12346", ph, &count);
  66. for (i = 0; i < 10; i++) mg_mgr_poll(&mgr, 0);
  67. ASSERT(count == 10);
  68. mg_tcpip_free(&mif);
  69. mg_mgr_free(&mgr);
  70. }
  71. #define DRIVER_BUF_SIZE 1540
  72. struct driver_data {
  73. char buf[DRIVER_BUF_SIZE];
  74. size_t len;
  75. bool tx_ready; // data can be read from tx
  76. };
  77. static struct driver_data s_driver_data;
  78. static size_t if_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
  79. struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
  80. if (len > DRIVER_BUF_SIZE) len = DRIVER_BUF_SIZE;
  81. driver_data->len = len;
  82. memcpy(driver_data->buf, buf, len);
  83. driver_data->tx_ready = true;
  84. return len;
  85. }
  86. static bool if_up(struct mg_tcpip_if *ifp) {
  87. return ifp->driver_data ? true : false;
  88. }
  89. static size_t if_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
  90. struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
  91. if (!driver_data->len) return 0;
  92. if (len > driver_data->len) len = driver_data->len;
  93. memcpy(buf, driver_data->buf, len);
  94. driver_data->len = 0; // cleaning up the buffer
  95. return len;
  96. }
  97. static bool received_response(struct driver_data *driver) {
  98. bool was_ready = driver->tx_ready;
  99. driver->tx_ready = false;
  100. return was_ready;
  101. }
  102. static void create_tcp_pkt(struct eth *e, struct ip *ip, uint32_t seq,
  103. uint32_t ack, uint8_t flags, size_t payload_len) {
  104. struct tcp t;
  105. memset(&t, 0, sizeof(struct tcp));
  106. t.flags = flags;
  107. t.seq = mg_htonl(seq);
  108. t.ack = mg_htonl(ack);
  109. t.off = 5 << 4;
  110. memcpy(s_driver_data.buf, e, sizeof(*e));
  111. memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
  112. memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(struct tcp));
  113. s_driver_data.len = sizeof(*e) + sizeof(*ip)
  114. + sizeof(struct tcp) + payload_len;
  115. }
  116. static void init_tcp_handshake(struct eth *e, struct ip *ip, struct tcp *tcp,
  117. struct mg_mgr *mgr) {
  118. // SYN
  119. create_tcp_pkt(e, ip, 1000, 0, TH_SYN | TH_ACK, 0);
  120. mg_mgr_poll(mgr, 0);
  121. // SYN-ACK
  122. while(!received_response(&s_driver_data)) mg_mgr_poll(mgr, 0);
  123. tcp = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
  124. sizeof(struct ip));
  125. ASSERT((tcp->flags == (TH_SYN | TH_ACK)));
  126. ASSERT((tcp->ack == mg_htonl(1001)));
  127. // ACK
  128. create_tcp_pkt(e, ip, 1001, 1, TH_ACK, 0);
  129. mg_mgr_poll(mgr, 0);
  130. }
  131. static void test_retransmit(void) {
  132. struct mg_mgr mgr;
  133. struct eth e;
  134. struct ip ip;
  135. struct tcp *t = NULL;
  136. uint64_t start, now;
  137. bool response_recv = true;
  138. struct mg_tcpip_driver driver;
  139. struct mg_tcpip_if mif;
  140. mg_mgr_init(&mgr);
  141. memset(&mif, 0, sizeof(mif));
  142. memset(&s_driver_data, 0, sizeof(struct driver_data));
  143. driver.init = NULL, driver.tx = if_tx, driver.up = if_up, driver.rx = if_rx;
  144. mif.driver = &driver;
  145. mif.driver_data = &s_driver_data;
  146. mg_tcpip_init(&mgr, &mif);
  147. mg_http_listen(&mgr, "http://0.0.0.0:0", fn, NULL);
  148. mgr.conns->pfn = NULL; // HTTP handler not needed
  149. mg_mgr_poll(&mgr, 0);
  150. // setting the Ethernet header
  151. memset(&e, 0, sizeof(e));
  152. memcpy(e.dst, mif.mac, 6 * sizeof(uint8_t));
  153. e.type = mg_htons(0x800);
  154. // setting the IP header
  155. memset(&ip, 0, sizeof(ip));
  156. ip.ver = 4 << 4, ip.proto = 6;
  157. ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
  158. init_tcp_handshake(&e, &ip, t, &mgr);
  159. // packet with seq_no = 1001
  160. ip.len =
  161. mg_htons(sizeof(struct ip) + sizeof(struct tcp) + /* TCP Payload */ 1);
  162. create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1);
  163. mg_mgr_poll(&mgr, 0);
  164. while(!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
  165. t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
  166. sizeof(struct ip));
  167. ASSERT((t->flags == TH_ACK));
  168. ASSERT((t->ack == mg_htonl(1002))); // OK
  169. // resend packet with seq_no = 1001 (e.g.: MIP ACK lost)
  170. create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1);
  171. mg_mgr_poll(&mgr, 0);
  172. start = mg_millis();
  173. while(!received_response(&s_driver_data)) {
  174. mg_mgr_poll(&mgr, 0);
  175. now = mg_millis() - start;
  176. // we wait enough time for a reply
  177. if (now > 2 * MIP_TCP_ACK_MS) {
  178. response_recv = false;
  179. break;
  180. }
  181. }
  182. ASSERT((!response_recv)); // replies should not be sent for duplicate packets
  183. // packet with seq_no = 1002 got lost/delayed, send seq_no = 1003
  184. create_tcp_pkt(&e, &ip, 1003, 1, TH_PUSH | TH_ACK, 1);
  185. mg_mgr_poll(&mgr, 0);
  186. start = mg_millis();
  187. while(!received_response(&s_driver_data)) {
  188. mg_mgr_poll(&mgr, 0);
  189. now = mg_millis() - start;
  190. if (now > 2 * MIP_TCP_ACK_MS)
  191. ASSERT(0); // response should have been received by now
  192. }
  193. t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
  194. sizeof(struct ip));
  195. ASSERT((t->flags == TH_ACK));
  196. ASSERT((t->ack == mg_htonl(1002))); // dup ACK
  197. // retransmitting packet with seq_no = 1002
  198. create_tcp_pkt(&e, &ip, 1002, 1, TH_PUSH | TH_ACK, 1);
  199. mg_mgr_poll(&mgr, 0);
  200. while(!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
  201. t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
  202. sizeof(struct ip));
  203. ASSERT((t->flags == TH_ACK));
  204. ASSERT((t->ack == mg_htonl(1003))); // OK
  205. s_driver_data.len = 0;
  206. mg_mgr_free(&mgr);
  207. mg_tcpip_free(&mif);
  208. }
  209. static void test_frag_recv_path(void) {
  210. struct mg_mgr mgr;
  211. struct eth e;
  212. struct ip ip;
  213. struct tcp *t = NULL;
  214. struct mg_tcpip_driver driver;
  215. struct mg_tcpip_if mif;
  216. mg_mgr_init(&mgr);
  217. memset(&mif, 0, sizeof(mif));
  218. memset(&s_driver_data, 0, sizeof(struct driver_data));
  219. driver.init = NULL, driver.tx = if_tx, driver.up = if_up, driver.rx = if_rx;
  220. mif.driver = &driver;
  221. mif.driver_data = &s_driver_data;
  222. mg_tcpip_init(&mgr, &mif);
  223. mg_http_listen(&mgr, "http://0.0.0.0:0", frag_recv_fn, NULL);
  224. mgr.conns->pfn = NULL;
  225. mg_mgr_poll(&mgr, 0);
  226. // setting the Ethernet header
  227. memset(&e, 0, sizeof(e));
  228. memcpy(e.dst, mif.mac, 6 * sizeof(uint8_t));
  229. e.type = mg_htons(0x800);
  230. // setting the IP header
  231. memset(&ip, 0, sizeof(ip));
  232. ip.ver = 0x45, ip.proto = 6;
  233. ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
  234. init_tcp_handshake(&e, &ip, t, &mgr);
  235. // send fragmented TCP packet
  236. ip.len =
  237. mg_htons(sizeof(struct ip) + sizeof(struct tcp) + 1000);
  238. ip.frag |= IP_MORE_FRAGS_MSK; // setting More Fragments bit to 1
  239. create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1000);
  240. s_sent_fragment = true;
  241. mg_mgr_poll(&mgr, 0);
  242. s_driver_data.len = 0;
  243. mg_mgr_free(&mgr);
  244. mg_tcpip_free(&mif);
  245. }
  246. static void test_frag_send_path(void) {
  247. struct mg_mgr mgr;
  248. struct mg_tcpip_driver driver;
  249. struct mg_tcpip_if mif;
  250. mg_mgr_init(&mgr);
  251. memset(&mif, 0, sizeof(mif));
  252. memset(&s_driver_data, 0, sizeof(struct driver_data));
  253. driver.init = NULL, driver.tx = if_tx, driver.up = if_up, driver.rx = if_rx;
  254. mif.driver = &driver;
  255. mif.driver_data = &s_driver_data;
  256. mg_tcpip_init(&mgr, &mif);
  257. mif.mtu = 500;
  258. mg_http_listen(&mgr, "http://0.0.0.0:0", frag_send_fn, NULL);
  259. mgr.conns->pfn = NULL;
  260. for (int i = 0; i < 10; i++)
  261. mg_mgr_poll(&mgr, 0);
  262. ASSERT(s_seg_sent == 3);
  263. s_driver_data.len = 0;
  264. mg_mgr_free(&mgr);
  265. mg_tcpip_free(&mif);
  266. }
  267. static void test_fragmentation(void) {
  268. test_frag_recv_path();
  269. test_frag_send_path();
  270. }
  271. int main(void) {
  272. test_statechange();
  273. test_poll();
  274. test_retransmit();
  275. test_fragmentation();
  276. printf("SUCCESS. Total tests: %d\n", s_num_tests);
  277. return 0;
  278. }