2 #include <l4/re/namespace>
3 #include <l4/re/util/cap_alloc>
4 #include <l4/cxx/ipc_stream>
5 #include <l4/ankh/protocol>
7 #include <l4/ankh/session>
8 #include <l4/util/util.h>
9 #include <l4/shmc/shmc.h>
10 #include <boost/format.hpp>
13 #include <l4/sys/debugger.h>
14 #include <pthread-l4.h>
17 Ankh::Shm_receiver *recv;
18 Ankh::Shm_sender *send;
19 Ankh::Shm_chunk *info;
22 int cfg_shmsize = 2048;
23 l4shmc_area_t ankh_shmarea;
25 #define mac_fmt "%02X:%02X:%02X:%02X:%02X:%02X"
26 #define mac_str(mac) (unsigned char)((mac)[0]), (unsigned char)((mac)[1]), \
27 (unsigned char)((mac)[2]), (unsigned char)((mac)[3]), \
28 (unsigned char)((mac)[4]), (unsigned char)((mac)[5])
30 static const int print_rate = 30000;
31 unsigned char const bcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
34 * Print a MAC formatted
36 static void print_mac(unsigned char *macptr)
38 char macbuf_size = 32;
39 char mac_buf[macbuf_size];
40 snprintf(mac_buf, macbuf_size, mac_fmt, mac_str(macptr));
41 boost::format f("%1$-18s");
47 static char *human_readable_size(unsigned size) {
51 snprintf(sizebuf, sizeof(sizebuf), "%d B", size);
52 else if (size < 1000000)
53 snprintf(sizebuf, sizeof(sizebuf), "%.02f kiB", size/1000.0);
54 else if (size < 1000000000)
55 snprintf(sizebuf, sizeof(sizebuf), "%.02f MiB", size/1000000.0);
57 snprintf(sizebuf, sizeof(sizebuf), "%.02f GiB", size/1000000000.0);
59 return strdup(sizebuf);
64 * Print my device's stats
66 static void print_stats()
68 struct AnkhSessionDescriptor *sd = reinterpret_cast<struct AnkhSessionDescriptor*>(info->addr());
70 std::cout << "info @ " << (void*)sd << "\n";
71 print_mac(&sd->mac[0]); std::cout << "MTU " << sd->mtu << "\n";
72 std::cout << "RX packets: " << sd->num_rx << " dropped: " << sd->rx_dropped << "\n";
73 std::cout << "TX packets: " << sd->num_tx << " dropped: " << sd->tx_dropped << "\n";
74 char *s1 = human_readable_size(sd->rx_bytes);
75 char *s2 = human_readable_size(sd->tx_bytes);
76 std::cout << "RX bytes: " << s1
77 << " TX bytes: " << s2 << "\n";
81 static void ankh_activate()
83 L4::Cap<void> ankh_server;
85 if (!(ankh_server = L4Re::Env::env()->get_cap<void>("ankh"))) {
86 printf("Could not find Ankh server.\n");
90 L4::Ipc::Iostream s(l4_utcb());
92 s << l4_umword_t(Ankh::Opcode::Activate);
94 l4_msgtag_t res = s.call(ankh_server.cap(), Ankh::Protocol::Ankh);
95 ASSERT_EQUAL(l4_ipc_error(res, l4_utcb()), 0);
97 printf("activated Ankh connection.\n");
101 static void get_shm_area(L4::Cap<void> /*session*/)
103 int err = l4shmc_attach(shm_name, &ankh_shmarea);
105 std::cout << "Attached shm area '" << shm_name << "': " << err << "\n";
107 Ankh::Shm_ringbuffer *send_rb = Ankh::Shm_ringbuffer::create(
108 &ankh_shmarea, "tx_ring",
109 "tx_signal", cfg_shmsize);
110 Ankh::Shm_ringbuffer *recv_rb = Ankh::Shm_ringbuffer::create(
111 &ankh_shmarea, "rx_ring",
112 "rx_signal", cfg_shmsize);
113 Ankh::Shm_chunk *info_chunk = Ankh::Shm_chunk::create(&ankh_shmarea,
114 "info", sizeof(AnkhSessionDescriptor));
116 std::cout << "SEND RB @ " << (void*)send_rb
117 << " RECV RB @ " << (void*)recv_rb
118 << " INFO @ " << (void *)info_chunk << "\n";
122 send = new Ankh::Shm_sender(&ankh_shmarea, "tx_ring",
124 std::cout << "sender: " << (void*)send << "\n";
125 recv = new Ankh::Shm_receiver(&ankh_shmarea, "rx_ring",
127 std::cout << "receiver: " << (void*)recv << "\n";
129 info = Ankh::Shm_chunk::get(&ankh_shmarea, "info",
130 sizeof(struct AnkhSessionDescriptor));
132 struct AnkhSessionDescriptor *sd = reinterpret_cast<struct AnkhSessionDescriptor*>(info->addr());
134 std::cout << "Got assigned MAC: ";
150 unsigned char txbuf[1024];
152 unsigned char rxbuf[1024];
154 const unsigned char packet_const;
158 rx_struct recv_buffer = {
159 {0xAA, 0xAA, 0xAA, 0xAA},
161 {0xBB, 0xBB, 0xBB, 0xBB},
163 {0xCC, 0xCC, 0xCC, 0xCC},
165 {0xDD, 0xDD, 0xDD, 0xDD}
170 generate_packet(unsigned char *buf,
171 unsigned char dest[6],
172 unsigned char src[6],
173 unsigned char payload,
176 memcpy(buf, dest, 6);
177 memcpy(buf+6, src, 6);
178 memset(buf+12, payload, size);
181 static void send_packet(Ankh::Shm_sender *snd,
182 unsigned char *packet,
185 DEBUG("sending()\n");
186 int err = snd->next_copy_in((char*)packet, size);
189 snd->commit_packet();
192 static void recv_packet(Ankh::Shm_receiver *rcv,
197 recv->wait_for_data();
198 DEBUG("got data.\n");
199 int err = rcv->next_copy_out((char*)buf, size);
201 DEBUG("copied out\n");
205 static void sanity_check_packet(unsigned char *buf,
206 unsigned char src[6],
207 unsigned char dest[6],
208 unsigned char payload,
211 if (memcmp(buf, dest, 6)) {
212 std::cout << "Dest mismatch in buf @ " << (void*)buf << " ";
214 std::cout << " <-> ";
216 std::cout << std::endl;
217 assert(memcmp(buf, dest, 6) == 0);
219 if (memcmp(buf + 6, src, 6)) {
220 std::cout << "Src mismatch in buf @ " << (void*)buf << " ";
222 std::cout << " <-> ";
224 std::cout << std::endl;
225 assert(memcmp(buf+6, src, 6) == 0);
228 unsigned char *c = buf + 12;
229 for ( ; c < buf + size; ++c)
230 assert(*c == payload);
233 static void morping()
235 unsigned char mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
236 unsigned char mymac[6] = {0x00};
237 unsigned bufsize = sizeof(recv_buffer.txbuf);
238 // minimum size for sending test packets
240 // maximum random element in size: bufsize - header len - minimum size
241 int data_size = bufsize - 12 - min_size;
244 memcpy(mymac, reinterpret_cast<struct AnkhSessionDescriptor*>(info->addr())->mac, 6);
247 printf("MY MAC: "); print_mac(mymac); printf("\n");
248 for (int cnt = 0; ; cnt++)
252 * minimum_size <= rand <= data_size
254 int rand = random() % data_size + min_size;
256 generate_packet(recv_buffer.txbuf, mac, mymac, recv_buffer.packet_const, rand);
258 size = rand + 12; // data + sizeof(header)
259 send_packet(send, &recv_buffer.txbuf[0], size);
262 recv_packet(recv, &recv_buffer.rxbuf[0], &size);
265 * This task will always receive second. This means,
266 * the packet will contain valid MACs, but our own
267 * representation of the partner's MAC will be bcast.
268 * Therefore, we extract the partner's MAC from the
269 * packet's sender field.
271 if (memcmp(mac, bcast_mac, 6) == 0)
272 memcpy(mac, recv_buffer.rxbuf + 6, 6);
274 sanity_check_packet(recv_buffer.rxbuf, mac, mymac, recv_buffer.packet_const, rand);
276 if (cnt > print_rate) {
283 static void morpong()
285 unsigned char mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
286 unsigned char mymac[6] = {0x00};
287 unsigned bufsize = sizeof(recv_buffer.txbuf);
290 memcpy(mymac, reinterpret_cast<struct AnkhSessionDescriptor*>(info->addr())->mac, 6);
292 printf("MY MAC: "); print_mac(mymac); printf("\n");
293 for (int cnt = 0; ; cnt++)
296 recv_packet(recv, &recv_buffer.rxbuf[0], &size);
299 * This task will always recv() first, so the recipient
300 * MAC of the first packet will be a bcast one. If we
301 * find this, we extract the partner's MAC from the sender
304 if (memcmp(recv_buffer.rxbuf, bcast_mac, 6) == 0)
305 memcpy(mac, recv_buffer.rxbuf + 6, 6);
307 sanity_check_packet(recv_buffer.rxbuf, mac, mymac, recv_buffer.packet_const, size);
309 generate_packet(recv_buffer.txbuf, mac, mymac, recv_buffer.packet_const, size-12);
311 send_packet(send, &recv_buffer.txbuf[0], size);
313 if (cnt > print_rate+1) {
321 static void setup_debug_names(std::string const &name)
323 std::cout << "I am " << name << "\n";
325 std::cout << "My TID = 0x" << std::hex << l4_debugger_global_id(pthread_getl4cap(pthread_self()))
327 //std::cout << "Ready to contact Ankh.\n";
328 char const *c = name.c_str();
329 for ( ; *c++ != '/'; ) ;
331 std::cout << c << "\n";
332 l4_debugger_set_object_name(pthread_getl4cap(pthread_self()), c);
337 int main(int argc, char **argv)
340 std::cout << "Using shm area: '" << argv[1] << "'\n";
341 shm_name = strdup(argv[1]);
344 L4::Cap<void> ankh_session;
345 if (!(ankh_session = L4Re::Env::env()->get_cap<void>("ankh")))
347 std::cout << "Ankh not found.\n";
351 get_shm_area(ankh_session);
353 std::string name(argv[0]);
354 std::cout << name << "\n";
355 setup_debug_names(name);
356 std::cout << "txbuf @ " << (void*)recv_buffer.txbuf << ", rxbuf @ " << (void*)recv_buffer.rxbuf << std::endl;
358 if (name == "rom/morping")