2 * hwsim_test - Data connectivity test for mac80211_hwsim
3 * Copyright (c) 2009, Atheros Communications
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include <sys/ioctl.h>
20 #include <sys/socket.h>
21 #include <sys/select.h>
22 #include <netpacket/packet.h>
23 #include <net/ethernet.h>
25 #include <arpa/inet.h>
27 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
28 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
30 #define HWSIM_ETHERTYPE ETHERTYPE_IP
31 #define HWSIM_PACKETLEN 1500
33 static unsigned char addr1[ETH_ALEN], addr2[ETH_ALEN], bcast[ETH_ALEN];
35 static void tx(int s, const char *ifname, int ifindex,
36 const unsigned char *src, const unsigned char *dst)
38 char buf[HWSIM_PACKETLEN], *pos;
39 struct ether_header *eth;
42 printf("TX: %s(ifindex=%d) " MACSTR " -> " MACSTR "\n",
43 ifname, ifindex, MAC2STR(src), MAC2STR(dst));
45 eth = (struct ether_header *) buf;
46 memcpy(eth->ether_dhost, dst, ETH_ALEN);
47 memcpy(eth->ether_shost, src, ETH_ALEN);
48 eth->ether_type = htons(HWSIM_ETHERTYPE);
49 pos = (char *) (eth + 1);
50 for (i = 0; i < sizeof(buf) - sizeof(*eth); i++)
53 if (send(s, buf, sizeof(buf), 0) < 0)
66 static void rx(int s, int iface, const char *ifname, int ifindex,
67 struct rx_result *res)
69 char buf[HWSIM_PACKETLEN + 1], *pos;
70 struct ether_header *eth;
73 len = recv(s, buf, sizeof(buf), 0);
78 eth = (struct ether_header *) buf;
80 printf("RX: %s(ifindex=%d) " MACSTR " -> " MACSTR " (len=%d)\n",
82 MAC2STR(eth->ether_shost), MAC2STR(eth->ether_dhost), len);
84 if (len != HWSIM_PACKETLEN) {
85 printf("Ignore frame with unexpected RX length\n");
89 pos = (char *) (eth + 1);
90 for (i = 0; i < sizeof(buf) - 1 - sizeof(*eth); i++) {
91 if ((unsigned char) *pos != (unsigned char) i) {
92 printf("Ignore frame with unexpected contents\n");
93 printf("i=%d received=0x%x expected=0x%x\n",
94 i, (unsigned char) *pos, (unsigned char) i);
101 memcmp(eth->ether_dhost, addr1, ETH_ALEN) == 0 &&
102 memcmp(eth->ether_shost, addr2, ETH_ALEN) == 0)
103 res->rx_unicast1 = 1;
104 else if (iface == 1 &&
105 memcmp(eth->ether_dhost, bcast, ETH_ALEN) == 0 &&
106 memcmp(eth->ether_shost, addr2, ETH_ALEN) == 0)
107 res->rx_broadcast1 = 1;
108 else if (iface == 2 &&
109 memcmp(eth->ether_dhost, addr2, ETH_ALEN) == 0 &&
110 memcmp(eth->ether_shost, addr1, ETH_ALEN) == 0)
111 res->rx_unicast2 = 1;
112 else if (iface == 2 &&
113 memcmp(eth->ether_dhost, bcast, ETH_ALEN) == 0 &&
114 memcmp(eth->ether_shost, addr1, ETH_ALEN) == 0)
115 res->rx_broadcast2 = 1;
119 int main(int argc, char *argv[])
121 int s1 = -1, s2 = -1, ret = -1;
123 int ifindex1, ifindex2;
124 struct sockaddr_ll ll;
127 struct rx_result res;
130 fprintf(stderr, "usage: hwsim_test <ifname1> <ifname2>\n");
134 memset(bcast, 0xff, ETH_ALEN);
136 s1 = socket(PF_PACKET, SOCK_RAW, htons(HWSIM_ETHERTYPE));
142 s2 = socket(PF_PACKET, SOCK_RAW, htons(HWSIM_ETHERTYPE));
148 memset(&ifr, 0, sizeof(ifr));
149 strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name));
150 if (ioctl(s1, SIOCGIFINDEX, &ifr) < 0) {
151 perror("ioctl[SIOCGIFINDEX]");
154 ifindex1 = ifr.ifr_ifindex;
155 if (ioctl(s1, SIOCGIFHWADDR, &ifr) < 0) {
156 perror("ioctl[SIOCGIFHWADDR]");
159 memcpy(addr1, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
161 memset(&ifr, 0, sizeof(ifr));
162 strncpy(ifr.ifr_name, argv[2], sizeof(ifr.ifr_name));
163 if (ioctl(s2, SIOCGIFINDEX, &ifr) < 0) {
164 perror("ioctl[SIOCGIFINDEX]");
167 ifindex2 = ifr.ifr_ifindex;
168 if (ioctl(s2, SIOCGIFHWADDR, &ifr) < 0) {
169 perror("ioctl[SIOCGIFHWADDR]");
172 memcpy(addr2, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
174 memset(&ll, 0, sizeof(ll));
175 ll.sll_family = PF_PACKET;
176 ll.sll_ifindex = ifindex1;
177 ll.sll_protocol = htons(HWSIM_ETHERTYPE);
178 if (bind(s1, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
183 memset(&ll, 0, sizeof(ll));
184 ll.sll_family = PF_PACKET;
185 ll.sll_ifindex = ifindex2;
186 ll.sll_protocol = htons(HWSIM_ETHERTYPE);
187 if (bind(s2, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
192 tx(s1, argv[1], ifindex1, addr1, addr2);
193 tx(s1, argv[1], ifindex1, addr1, bcast);
194 tx(s2, argv[2], ifindex2, addr2, addr1);
195 tx(s2, argv[2], ifindex2, addr2, bcast);
200 memset(&res, 0, sizeof(res));
207 r = select(s2 + 1, &rfds, NULL, NULL, &tv);
216 if (FD_SET(s1, &rfds))
217 rx(s1, 1, argv[1], ifindex1, &res);
218 if (FD_SET(s2, &rfds))
219 rx(s2, 2, argv[2], ifindex2, &res);
221 if (res.rx_unicast1 && res.rx_broadcast1 &&
222 res.rx_unicast2 && res.rx_broadcast2) {
229 printf("Did not receive all expected frames:\n"
230 "rx_unicast1=%d rx_broadcast1=%d "
231 "rx_unicast2=%d rx_broadcast2=%d\n",
232 res.rx_unicast1, res.rx_broadcast1,
233 res.rx_unicast2, res.rx_broadcast2);
235 printf("Both unicast and broadcast working in both "