| #include <net/if.h> | 
 | #include <net/ethernet.h> | 
 | #include <netinet/in.h> | 
 | #include <unistd.h> | 
 | #include <stdint.h> | 
 | #include <netdb.h> | 
 | #include <sys/ioctl.h> | 
 | #include <sys/time.h> | 
 | #include <stdio.h> | 
 | #include <assert.h> | 
 | #include <packetizer.h> | 
 | #include <stdexcept> | 
 | #include <fstream> | 
 |  | 
 | #ifdef DEBUG_MODE | 
 | # define debug(...) (__VA_ARGS__) | 
 | #else | 
 | # define debug(...) do { } while(0) | 
 | #endif | 
 |  | 
 | static __inline uint64_t | 
 | read_tsc(void) | 
 | { | 
 |     uint64_t tsc; | 
 |     __asm __volatile("rdtsc" : "=A" (tsc)); | 
 |     return tsc; | 
 | } | 
 |  | 
 | packetizer::packetizer(const char *target_mac, const char *eth_device,  | 
 | 	                     const char *filename) | 
 | { | 
 | 	seqno = 0; | 
 | 	memcpy(this->target_mac, target_mac, 6); | 
 | 	strcpy(this->eth_device, eth_device); | 
 | 	strcpy(this->filename, filename); | 
 | 	memset(&myaddr, 0, sizeof(myaddr)); | 
 |  | 
 | 	// setuid root to open a raw socket.  if we fail, too bad | 
 | 	seteuid(0); | 
 | 	sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); | 
 | 	seteuid(getuid()); | 
 | 	if(sock < 0) | 
 | 	  throw std::runtime_error("socket() failed! Maybe try running as root..."); | 
 |  | 
 | 	myaddr.sll_ifindex = if_nametoindex(eth_device); | 
 | 	myaddr.sll_family = AF_PACKET; | 
 |  | 
 | 	int ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr)); | 
 | 	if (ret < 0) | 
 | 	  throw std::runtime_error("bind() failed!"); | 
 |  | 
 | 	struct timeval tv; | 
 | 	tv.tv_sec = 1; | 
 | 	tv.tv_usec = 0; | 
 | 	if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(struct timeval)) < 0) | 
 | 	  throw std::runtime_error("setsockopt() failed!"); | 
 |  | 
 | 	// get MAC address of local ethernet device | 
 | 	struct ifreq ifr; | 
 | 	strcpy(ifr.ifr_name, eth_device); | 
 | 	ret = ioctl(sock, SIOCGIFHWADDR, (char *)&ifr); | 
 | 	if (ret < 0) | 
 | 	  throw std::runtime_error("ioctl() failed!"); | 
 | 	memcpy(&host_mac, &ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); | 
 | } | 
 |  | 
 | int packetizer::start() | 
 | { | 
 | 	std::ifstream file(filename, std::ios::in | std::ios::binary); | 
 | 	packet p(target_mac, host_mac, seqno, MAX_PAYLOAD_SIZE, NULL); | 
 |  | 
 | 	int ret; | 
 | 	printf("Starting to packetize the file: %s\n", filename); | 
 | 	file.read(p.payload, MAX_PAYLOAD_SIZE); | 
 | 	while(file) { | 
 | 		//printf("Sending chunk %d\n", seqno); | 
 | 		ret = ::sendto(sock, (char*)&p, p.size(), 0, | 
 | 		               (sockaddr*)&myaddr,sizeof(myaddr)); | 
 | 		 | 
 | 		volatile uint64_t tsc = read_tsc(); | 
 | 		while((read_tsc() - tsc) < 34800); | 
 | 		if (ret < 0) | 
 | 		  throw std::runtime_error("sending packet failed!"); | 
 | 		p.header.seqno = htons(next_seqno()); | 
 | 		file.read(p.payload, MAX_PAYLOAD_SIZE); | 
 | 	} | 
 | 	if(file.gcount()) { | 
 | 		p.header.payload_size = ntohl(file.gcount()); | 
 | 		p.packet_size = sizeof(p.header)+file.gcount(); | 
 | 		 | 
 | 		ret = ::sendto(sock, (char*)&p, p.size(), 0, | 
 | 		               (sockaddr*)&myaddr,sizeof(myaddr)); | 
 | 		if (ret < 0) | 
 | 		  throw std::runtime_error("sending packet failed!"); | 
 | 		//printf("Sending chunk %d\n", seqno); | 
 | 	} | 
 | 	printf("Last chunk had %u bytes...\n", file.gcount()); | 
 | } | 
 |  | 
 | int main(int argc, char** argv) | 
 | { | 
 | 	char target_mac[6]; | 
 | 	char eth_device[256]; | 
 | 	char filename[256]; | 
 | 	if(argc == 1) { | 
 | 		target_mac[0] = 0x00; | 
 | 		target_mac[1] = 0x24; | 
 | 		target_mac[2] = 0x1d; | 
 | 		target_mac[3] = 0x10; | 
 | 		target_mac[4] = 0xa2; | 
 | 		target_mac[5] = 0xb5; | 
 | 		strcpy(eth_device, "eth0"); | 
 | 		strcpy(filename, "../../fs/i686/tests/e.y4m"); | 
 | 	} | 
 | 	if(argc > 1) { | 
 | 		assert(argc == 4); | 
 | 		assert(strlen(argv[1]) == 17); | 
 | 		sscanf(argv[1], "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&target_mac[0], | 
 | 		                                           (unsigned int *)&target_mac[1], | 
 | 		                                           (unsigned int *)&target_mac[2], | 
 | 		                                           (unsigned int *)&target_mac[3], | 
 | 		                                           (unsigned int *)&target_mac[4], | 
 | 		                                           (unsigned int *)&target_mac[5]); | 
 | 		strcpy(eth_device, argv[2]); | 
 | 		strcpy(filename, argv[3]); | 
 | 		 | 
 | 	} | 
 | 	packetizer p(target_mac, eth_device, filename); | 
 | 	p.start(); | 
 | 	return 0; | 
 | } | 
 |  |