Added a fillmeup syscall
[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 <netdb.h>
6 #include <sys/ioctl.h>
7 #include <sys/time.h>
8 #include <stdio.h>
9 #include <packetizer.h>
10 #include <stdexcept>
11 #include <fstream>
12
13 #ifdef DEBUG_MODE
14 # define debug(...) (__VA_ARGS__)
15 #else
16 # define debug(...) do { } while(0)
17 #endif
18
19 packetizer::packetizer(const char *target_mac, const char *eth_device, 
20                              const char *filename)
21 {
22         seqno = 0;
23         memcpy(this->target_mac, target_mac, 6);
24         strcpy(this->eth_device, eth_device);
25         strcpy(this->filename, filename);
26         memset(&myaddr, 0, sizeof(myaddr));
27
28         // setuid root to open a raw socket.  if we fail, too bad
29         seteuid(0);
30         sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
31         seteuid(getuid());
32         if(sock < 0)
33           throw std::runtime_error("socket() failed! Maybe try running as root...");
34
35         myaddr.sll_ifindex = if_nametoindex(eth_device);
36         myaddr.sll_family = AF_PACKET;
37
38         int ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
39         if (ret < 0)
40           throw std::runtime_error("bind() failed!");
41
42         struct timeval tv;
43         tv.tv_sec = 1;
44         tv.tv_usec = 0;
45         if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(struct timeval)) < 0)
46           throw std::runtime_error("setsockopt() failed!");
47
48         // get MAC address of local ethernet device
49         struct ifreq ifr;
50         strcpy(ifr.ifr_name, eth_device);
51         ret = ioctl(sock, SIOCGIFHWADDR, (char *)&ifr);
52         if (ret < 0)
53           throw std::runtime_error("ioctl() failed!");
54         memcpy(&host_mac, &ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
55 }
56
57 int packetizer::start()
58 {
59         std::ifstream file(filename, std::ios::in | std::ios::binary);
60         packet p(target_mac, host_mac, seqno, MAX_PAYLOAD_SIZE, NULL);
61
62         int ret;
63         printf("Starting to packetize the file: %s\n", filename);
64         file.read(p.payload, MAX_PAYLOAD_SIZE);
65         while(file) {
66                 printf("Sending chunk %d\n", seqno);
67                 ret = ::sendto(sock, (char*)&p, p.size(), 0,
68                                (sockaddr*)&myaddr,sizeof(myaddr));
69                 if (ret < 0)
70                   throw std::runtime_error("sending packet failed!");
71                 p.header.seqno = htons(next_seqno());
72                 file.read(p.payload, MAX_PAYLOAD_SIZE);
73         }
74         if(file.gcount()) {
75                 p.header.payload_size = ntohl(file.gcount());
76                 p.packet_size = sizeof(p.header)+file.gcount();
77                 
78                 ret = ::sendto(sock, (char*)&p, p.size(), 0,
79                                (sockaddr*)&myaddr,sizeof(myaddr));
80                 if (ret < 0)
81                   throw std::runtime_error("sending packet failed!");
82                 printf("Sending chunk %d\n", seqno);
83         }
84         printf("Last chunk had %u bytes...\n", file.gcount());
85 }
86
87 int main(int argc, char** argv)
88 {
89         char target_mac[] = {0x00, 0x24, 0x1d, 0x10, 0xa2, 0xb5};
90         char eth_device[] = "ros-tap1";
91         char filename[] = "test_file";
92         packetizer p(target_mac, eth_device, filename);
93         p.start();
94         return 0;
95 }
96
97 /*
98 memif_t::error memif_x86_dma_t::read_chunk(uint32_t addr, uint32_t len, uint8_t* bytes, uint8_t asi, uint16_t pid)
99 {
100         if(!htif->running)
101           return memif_t::Invalid;
102
103         x86_packet p(ros_mac,appsvr_mac,X86_CMD_LOAD,next_seqno(),0,addr,0);
104         p.header.payload_size = htonl(len);
105         for(int i=0; i<p.size(); i++) {
106           debug("%02x ", (unsigned char)*((char *)&p + i));
107         }
108         debug("\n\n");
109         send_packet(&p);
110         if(p.size() - sizeof(x86_packet_header) != len)
111           throw std::runtime_error("bad packet size");
112
113         memcpy(bytes,p.payload,len);
114
115         return memif_t::OK;
116 }
117
118 memif_t::error memif_x86_dma_t::write_chunk(uint32_t addr, uint32_t len, const uint8_t* bytes, uint8_t asi, uint16_t pid)
119 {
120         if(!htif->running)
121           return memif_t::Invalid;
122
123         x86_packet p(ros_mac,appsvr_mac,X86_CMD_STORE,next_seqno(),len,addr,bytes);
124         send_packet(&p);
125         if(p.size() != sizeof(x86_packet_header))
126           throw std::runtime_error("bad packet size");
127
128         return memif_t::OK;
129 }
130
131 void memif_x86_dma_t::send_packet(x86_packet* packet)
132 {
133         x86_packet response;
134
135         while(1)
136         //for(int i = 0; i < 10; i++)
137         {
138           int ret = ::sendto(sock,(char*)packet,packet->size(),0,
139                              (sockaddr*)&myaddr,sizeof(myaddr));
140           if(ret != packet->size())
141             continue;
142           
143           debug("wait for response \n");
144           while(1)
145           {
146             ret = ::read(sock,(char*)&response,X86_MAX_PACKET_SIZE);
147             if(ret == -1)
148             {
149               debug("timeout\n");
150               break;
151             }
152             if(response.header.ethertype != htons(RAMP_ETHERTYPE) || 
153                memcmp(response.header.src_mac,packet->header.dst_mac,6) != 0)
154               continue;
155             else
156               break;
157           }
158           if(ret == -1)
159             continue;
160           
161         if(ret == 60)
162                 ret = sizeof(response.header) + ntohl(response.header.payload_size);
163
164           if(ntohl(response.header.payload_size) != ret-sizeof(response.header))
165           {
166           debug("ntohl(response.header.payload_size) != ret-sizeof(response.header)\n");
167             for(int i = 0; i < ret; i++)
168               debug("%02x ",(unsigned int)(unsigned char)((char*)&response)[i]);
169             debug("\n");
170             debug("packet size wrong\n");
171             continue;
172           }
173           response.packet_size = ret;
174
175           debug("got %d bytes: \n",ret);
176           for(int i = 0; i < ret; i++)
177             debug("%02x ",(unsigned int)(unsigned char)((char*)&response)[i]);
178           debug("\n");
179
180           // if we didn't send a broadcast packet, verify sender's mac
181           if(response.header.cmd != X86_CMD_ACK) {
182           debug("response.header.cmd != X86_CMD_ACK\n");
183             for(int i = 0; i < ret; i++)
184               debug("%02x ",(unsigned int)(unsigned char)((char*)&response)[i]);
185             debug("\n");
186             debug("packet type wrong\n");
187             continue;
188          }
189           if(response.header.seqno != packet->header.seqno) 
190             continue;
191           debug("got something good\n");
192
193           *packet = response;
194           return;
195         }
196
197         throw std::runtime_error("memif_sparc_dma_t::send_packet(): timeout");
198 }
199 */
200