Signal with different u_ctx if current_uthread set
[akaros.git] / tools / packetizer / packetizer.cpp
1 #include <net/if.h>
2 #include <net/ethernet.h>
3 #include <netinet/in.h>
4 #include <unistd.h>
5 #include <stdint.h>
6 #include <netdb.h>
7 #include <sys/ioctl.h>
8 #include <sys/time.h>
9 #include <stdio.h>
10 #include <assert.h>
11 #include <packetizer.h>
12 #include <stdexcept>
13 #include <fstream>
14
15 #ifdef DEBUG_MODE
16 # define debug(...) (__VA_ARGS__)
17 #else
18 # define debug(...) do { } while(0)
19 #endif
20
21 static __inline uint64_t
22 read_tsc(void)
23 {
24     uint64_t tsc;
25     __asm __volatile("rdtsc" : "=A" (tsc));
26     return tsc;
27 }
28
29 packetizer::packetizer(const char *target_mac, const char *eth_device, 
30                              const char *filename)
31 {
32         seqno = 0;
33         memcpy(this->target_mac, target_mac, 6);
34         strcpy(this->eth_device, eth_device);
35         strcpy(this->filename, filename);
36         memset(&myaddr, 0, sizeof(myaddr));
37
38         // setuid root to open a raw socket.  if we fail, too bad
39         seteuid(0);
40         sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
41         seteuid(getuid());
42         if(sock < 0)
43           throw std::runtime_error("socket() failed! Maybe try running as root...");
44
45         myaddr.sll_ifindex = if_nametoindex(eth_device);
46         myaddr.sll_family = AF_PACKET;
47
48         int ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
49         if (ret < 0)
50           throw std::runtime_error("bind() failed!");
51
52         struct timeval tv;
53         tv.tv_sec = 1;
54         tv.tv_usec = 0;
55         if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(struct timeval)) < 0)
56           throw std::runtime_error("setsockopt() failed!");
57
58         // get MAC address of local ethernet device
59         struct ifreq ifr;
60         strcpy(ifr.ifr_name, eth_device);
61         ret = ioctl(sock, SIOCGIFHWADDR, (char *)&ifr);
62         if (ret < 0)
63           throw std::runtime_error("ioctl() failed!");
64         memcpy(&host_mac, &ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
65 }
66
67 int packetizer::start()
68 {
69         std::ifstream file(filename, std::ios::in | std::ios::binary);
70         packet p(target_mac, host_mac, seqno, MAX_PAYLOAD_SIZE, NULL);
71
72         int ret;
73         printf("Starting to packetize the file: %s\n", filename);
74         file.read(p.payload, MAX_PAYLOAD_SIZE);
75         while(file) {
76                 //printf("Sending chunk %d\n", seqno);
77                 ret = ::sendto(sock, (char*)&p, p.size(), 0,
78                                (sockaddr*)&myaddr,sizeof(myaddr));
79                 
80                 volatile uint64_t tsc = read_tsc();
81                 while((read_tsc() - tsc) < 34800);
82                 if (ret < 0)
83                   throw std::runtime_error("sending packet failed!");
84                 p.header.seqno = htons(next_seqno());
85                 file.read(p.payload, MAX_PAYLOAD_SIZE);
86         }
87         if(file.gcount()) {
88                 p.header.payload_size = ntohl(file.gcount());
89                 p.packet_size = sizeof(p.header)+file.gcount();
90                 
91                 ret = ::sendto(sock, (char*)&p, p.size(), 0,
92                                (sockaddr*)&myaddr,sizeof(myaddr));
93                 if (ret < 0)
94                   throw std::runtime_error("sending packet failed!");
95                 //printf("Sending chunk %d\n", seqno);
96         }
97         printf("Last chunk had %u bytes...\n", file.gcount());
98 }
99
100 int main(int argc, char** argv)
101 {
102         char target_mac[6];
103         char eth_device[256];
104         char filename[256];
105         if(argc == 1) {
106                 target_mac[0] = 0x00;
107                 target_mac[1] = 0x24;
108                 target_mac[2] = 0x1d;
109                 target_mac[3] = 0x10;
110                 target_mac[4] = 0xa2;
111                 target_mac[5] = 0xb5;
112                 strcpy(eth_device, "eth0");
113                 strcpy(filename, "../../fs/i686/tests/e.y4m");
114         }
115         if(argc > 1) {
116                 assert(argc == 4);
117                 assert(strlen(argv[1]) == 17);
118                 sscanf(argv[1], "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&target_mac[0],
119                                                            (unsigned int *)&target_mac[1],
120                                                            (unsigned int *)&target_mac[2],
121                                                            (unsigned int *)&target_mac[3],
122                                                            (unsigned int *)&target_mac[4],
123                                                            (unsigned int *)&target_mac[5]);
124                 strcpy(eth_device, argv[2]);
125                 strcpy(filename, argv[3]);
126                 
127         }
128         packetizer p(target_mac, eth_device, filename);
129         p.start();
130         return 0;
131 }
132