hwsim_test.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * hwsim_test - Data connectivity test for mac80211_hwsim
  3. * Copyright (c) 2009, Atheros Communications
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include <sys/ioctl.h>
  19. #include <sys/socket.h>
  20. #include <sys/select.h>
  21. #include <netpacket/packet.h>
  22. #include <net/ethernet.h>
  23. #include <net/if.h>
  24. #include <arpa/inet.h>
  25. #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
  26. #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
  27. #define HWSIM_ETHERTYPE ETHERTYPE_IP
  28. #define HWSIM_PACKETLEN 1500
  29. static unsigned char addr1[ETH_ALEN], addr2[ETH_ALEN], bcast[ETH_ALEN];
  30. static void tx(int s, const char *ifname, int ifindex,
  31. const unsigned char *src, const unsigned char *dst)
  32. {
  33. char buf[HWSIM_PACKETLEN], *pos;
  34. struct ether_header *eth;
  35. int i;
  36. printf("TX: %s(ifindex=%d) " MACSTR " -> " MACSTR "\n",
  37. ifname, ifindex, MAC2STR(src), MAC2STR(dst));
  38. eth = (struct ether_header *) buf;
  39. memcpy(eth->ether_dhost, dst, ETH_ALEN);
  40. memcpy(eth->ether_shost, src, ETH_ALEN);
  41. eth->ether_type = htons(HWSIM_ETHERTYPE);
  42. pos = (char *) (eth + 1);
  43. for (i = 0; i < sizeof(buf) - sizeof(*eth); i++)
  44. *pos++ = i;
  45. if (send(s, buf, sizeof(buf), 0) < 0)
  46. perror("send");
  47. }
  48. struct rx_result {
  49. int rx_unicast1:1;
  50. int rx_broadcast1:1;
  51. int rx_unicast2:1;
  52. int rx_broadcast2:1;
  53. };
  54. static void rx(int s, int iface, const char *ifname, int ifindex,
  55. struct rx_result *res)
  56. {
  57. char buf[HWSIM_PACKETLEN + 1], *pos;
  58. struct ether_header *eth;
  59. int len, i;
  60. len = recv(s, buf, sizeof(buf), 0);
  61. if (len < 0) {
  62. perror("recv");
  63. return;
  64. }
  65. eth = (struct ether_header *) buf;
  66. printf("RX: %s(ifindex=%d) " MACSTR " -> " MACSTR " (len=%d)\n",
  67. ifname, ifindex,
  68. MAC2STR(eth->ether_shost), MAC2STR(eth->ether_dhost), len);
  69. if (len != HWSIM_PACKETLEN) {
  70. printf("Ignore frame with unexpected RX length\n");
  71. return;
  72. }
  73. pos = (char *) (eth + 1);
  74. for (i = 0; i < sizeof(buf) - 1 - sizeof(*eth); i++) {
  75. if ((unsigned char) *pos != (unsigned char) i) {
  76. printf("Ignore frame with unexpected contents\n");
  77. printf("i=%d received=0x%x expected=0x%x\n",
  78. i, (unsigned char) *pos, (unsigned char) i);
  79. return;
  80. }
  81. pos++;
  82. }
  83. if (iface == 1 &&
  84. memcmp(eth->ether_dhost, addr1, ETH_ALEN) == 0 &&
  85. memcmp(eth->ether_shost, addr2, ETH_ALEN) == 0)
  86. res->rx_unicast1 = 1;
  87. else if (iface == 1 &&
  88. memcmp(eth->ether_dhost, bcast, ETH_ALEN) == 0 &&
  89. memcmp(eth->ether_shost, addr2, ETH_ALEN) == 0)
  90. res->rx_broadcast1 = 1;
  91. else if (iface == 2 &&
  92. memcmp(eth->ether_dhost, addr2, ETH_ALEN) == 0 &&
  93. memcmp(eth->ether_shost, addr1, ETH_ALEN) == 0)
  94. res->rx_unicast2 = 1;
  95. else if (iface == 2 &&
  96. memcmp(eth->ether_dhost, bcast, ETH_ALEN) == 0 &&
  97. memcmp(eth->ether_shost, addr1, ETH_ALEN) == 0)
  98. res->rx_broadcast2 = 1;
  99. }
  100. int main(int argc, char *argv[])
  101. {
  102. int s1 = -1, s2 = -1, ret = -1;
  103. struct ifreq ifr;
  104. int ifindex1, ifindex2;
  105. struct sockaddr_ll ll;
  106. fd_set rfds;
  107. struct timeval tv;
  108. struct rx_result res;
  109. if (argc != 3) {
  110. fprintf(stderr, "usage: hwsim_test <ifname1> <ifname2>\n");
  111. return -1;
  112. }
  113. memset(bcast, 0xff, ETH_ALEN);
  114. s1 = socket(PF_PACKET, SOCK_RAW, htons(HWSIM_ETHERTYPE));
  115. if (s1 < 0) {
  116. perror("socket");
  117. goto fail;
  118. }
  119. s2 = socket(PF_PACKET, SOCK_RAW, htons(HWSIM_ETHERTYPE));
  120. if (s2 < 0) {
  121. perror("socket");
  122. goto fail;
  123. }
  124. memset(&ifr, 0, sizeof(ifr));
  125. strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name));
  126. if (ioctl(s1, SIOCGIFINDEX, &ifr) < 0) {
  127. perror("ioctl[SIOCGIFINDEX]");
  128. goto fail;
  129. }
  130. ifindex1 = ifr.ifr_ifindex;
  131. if (ioctl(s1, SIOCGIFHWADDR, &ifr) < 0) {
  132. perror("ioctl[SIOCGIFHWADDR]");
  133. goto fail;
  134. }
  135. memcpy(addr1, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
  136. memset(&ifr, 0, sizeof(ifr));
  137. strncpy(ifr.ifr_name, argv[2], sizeof(ifr.ifr_name));
  138. if (ioctl(s2, SIOCGIFINDEX, &ifr) < 0) {
  139. perror("ioctl[SIOCGIFINDEX]");
  140. goto fail;
  141. }
  142. ifindex2 = ifr.ifr_ifindex;
  143. if (ioctl(s2, SIOCGIFHWADDR, &ifr) < 0) {
  144. perror("ioctl[SIOCGIFHWADDR]");
  145. goto fail;
  146. }
  147. memcpy(addr2, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
  148. memset(&ll, 0, sizeof(ll));
  149. ll.sll_family = PF_PACKET;
  150. ll.sll_ifindex = ifindex1;
  151. ll.sll_protocol = htons(HWSIM_ETHERTYPE);
  152. if (bind(s1, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
  153. perror("bind");
  154. goto fail;
  155. }
  156. memset(&ll, 0, sizeof(ll));
  157. ll.sll_family = PF_PACKET;
  158. ll.sll_ifindex = ifindex2;
  159. ll.sll_protocol = htons(HWSIM_ETHERTYPE);
  160. if (bind(s2, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
  161. perror("bind");
  162. goto fail;
  163. }
  164. tx(s1, argv[1], ifindex1, addr1, addr2);
  165. tx(s1, argv[1], ifindex1, addr1, bcast);
  166. tx(s2, argv[2], ifindex2, addr2, addr1);
  167. tx(s2, argv[2], ifindex2, addr2, bcast);
  168. tv.tv_sec = 1;
  169. tv.tv_usec = 0;
  170. memset(&res, 0, sizeof(res));
  171. for (;;) {
  172. int r;
  173. FD_ZERO(&rfds);
  174. FD_SET(s1, &rfds);
  175. FD_SET(s2, &rfds);
  176. r = select(s2 + 1, &rfds, NULL, NULL, &tv);
  177. if (r < 0) {
  178. perror("select");
  179. goto fail;
  180. }
  181. if (r == 0)
  182. break; /* timeout */
  183. if (FD_SET(s1, &rfds))
  184. rx(s1, 1, argv[1], ifindex1, &res);
  185. if (FD_SET(s2, &rfds))
  186. rx(s2, 2, argv[2], ifindex2, &res);
  187. if (res.rx_unicast1 && res.rx_broadcast1 &&
  188. res.rx_unicast2 && res.rx_broadcast2) {
  189. ret = 0;
  190. break;
  191. }
  192. }
  193. if (ret) {
  194. printf("Did not receive all expected frames:\n"
  195. "rx_unicast1=%d rx_broadcast1=%d "
  196. "rx_unicast2=%d rx_broadcast2=%d\n",
  197. res.rx_unicast1, res.rx_broadcast1,
  198. res.rx_unicast2, res.rx_broadcast2);
  199. } else {
  200. printf("Both unicast and broadcast working in both "
  201. "directions\n");
  202. }
  203. fail:
  204. close(s1);
  205. close(s2);
  206. return ret;
  207. }