diff options
Diffstat (limited to 'recv_image.c')
-rw-r--r-- | recv_image.c | 484 |
1 files changed, 0 insertions, 484 deletions
diff --git a/recv_image.c b/recv_image.c deleted file mode 100644 index 0093831..0000000 --- a/recv_image.c +++ /dev/null @@ -1,484 +0,0 @@ - -#define PROGRAM_NAME "recv_image" -#define _XOPEN_SOURCE 500 -#define _BSD_SOURCE /* struct ip_mreq */ - -#include <errno.h> -#include <stdio.h> -#include <netdb.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <crc32.h> -#include "mtd/mtd-user.h" -#include "mcast_image.h" - -#include "common.h" - -#define WBUF_SIZE 4096 -struct eraseblock { - uint32_t flash_offset; - unsigned char wbuf[WBUF_SIZE]; - int wbuf_ofs; - int nr_pkts; - int *pkt_indices; - uint32_t crc; -}; - -int main(int argc, char **argv) -{ - struct addrinfo *ai; - struct addrinfo hints; - struct addrinfo *runp; - int ret; - int sock; - ssize_t len; - int flfd; - struct mtd_info_user meminfo; - unsigned char *eb_buf, *decode_buf, **src_pkts; - int nr_blocks = 0; - int pkts_per_block; - int block_nr = -1; - uint32_t image_crc = 0; - int total_pkts = 0; - int ignored_pkts = 0; - loff_t mtdoffset = 0; - int badcrcs = 0; - int duplicates = 0; - int file_mode = 0; - struct fec_parms *fec = NULL; - int i; - struct eraseblock *eraseblocks = NULL; - uint32_t start_seq = 0; - struct timeval start, now; - unsigned long fec_time = 0, flash_time = 0, crc_time = 0, - rflash_time = 0, erase_time = 0, net_time = 0; - - if (argc != 4) { - fprintf(stderr, "usage: %s <host> <port> <mtddev>\n", - PROGRAM_NAME); - exit(1); - } - /* Open the device */ - flfd = open(argv[3], O_RDWR); - - if (flfd >= 0) { - /* Fill in MTD device capability structure */ - if (ioctl(flfd, MEMGETINFO, &meminfo) != 0) { - perror("MEMGETINFO"); - close(flfd); - flfd = -1; - } else { - printf("Receive to MTD device %s with erasesize %d\n", - argv[3], meminfo.erasesize); - } - } - if (flfd == -1) { - /* Try again, as if it's a file */ - flfd = open(argv[3], O_CREAT|O_TRUNC|O_RDWR, 0644); - if (flfd < 0) { - perror("open"); - exit(1); - } - meminfo.erasesize = 131072; - file_mode = 1; - printf("Receive to file %s with (assumed) erasesize %d\n", - argv[3], meminfo.erasesize); - } - - pkts_per_block = (meminfo.erasesize + PKT_SIZE - 1) / PKT_SIZE; - - eb_buf = malloc(pkts_per_block * PKT_SIZE); - decode_buf = malloc(pkts_per_block * PKT_SIZE); - if (!eb_buf && !decode_buf) { - fprintf(stderr, "No memory for eraseblock buffer\n"); - exit(1); - } - src_pkts = malloc(sizeof(unsigned char *) * pkts_per_block); - if (!src_pkts) { - fprintf(stderr, "No memory for decode packet pointers\n"); - exit(1); - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_ADDRCONFIG; - hints.ai_socktype = SOCK_DGRAM; - - ret = getaddrinfo(argv[1], argv[2], &hints, &ai); - if (ret) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); - exit(1); - } - runp = ai; - for (runp = ai; runp; runp = runp->ai_next) { - sock = socket(runp->ai_family, runp->ai_socktype, - runp->ai_protocol); - if (sock == -1) { - perror("socket"); - continue; - } - if (runp->ai_family == AF_INET && - IN_MULTICAST( ntohl(((struct sockaddr_in *)runp->ai_addr)->sin_addr.s_addr))) { - struct ip_mreq rq; - rq.imr_multiaddr = ((struct sockaddr_in *)runp->ai_addr)->sin_addr; - rq.imr_interface.s_addr = INADDR_ANY; - if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &rq, sizeof(rq))) { - perror("IP_ADD_MEMBERSHIP"); - close(sock); - continue; - } - - } else if (runp->ai_family == AF_INET6 && - ((struct sockaddr_in6 *)runp->ai_addr)->sin6_addr.s6_addr[0] == 0xff) { - struct ipv6_mreq rq; - rq.ipv6mr_multiaddr = ((struct sockaddr_in6 *)runp->ai_addr)->sin6_addr; - rq.ipv6mr_interface = 0; - if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &rq, sizeof(rq))) { - perror("IPV6_ADD_MEMBERSHIP"); - close(sock); - continue; - } - } - if (bind(sock, runp->ai_addr, runp->ai_addrlen)) { - perror("bind"); - close(sock); - continue; - } - break; - } - if (!runp) - exit(1); - - while (1) { - struct image_pkt thispkt; - - len = read(sock, &thispkt, sizeof(thispkt)); - - if (len < 0) { - perror("read socket"); - break; - } - if (len < sizeof(thispkt)) { - fprintf(stderr, "Wrong length %zd bytes (expected %zu)\n", - len, sizeof(thispkt)); - continue; - } - if (!eraseblocks) { - image_crc = thispkt.hdr.totcrc; - start_seq = ntohl(thispkt.hdr.pkt_sequence); - - if (meminfo.erasesize != ntohl(thispkt.hdr.blocksize)) { - fprintf(stderr, "Erasesize mismatch (0x%x not 0x%x)\n", - ntohl(thispkt.hdr.blocksize), meminfo.erasesize); - exit(1); - } - nr_blocks = ntohl(thispkt.hdr.nr_blocks); - - fec = fec_new(pkts_per_block, ntohs(thispkt.hdr.nr_pkts)); - - eraseblocks = malloc(nr_blocks * sizeof(*eraseblocks)); - if (!eraseblocks) { - fprintf(stderr, "No memory for block map\n"); - exit(1); - } - for (i = 0; i < nr_blocks; i++) { - eraseblocks[i].pkt_indices = malloc(sizeof(int) * pkts_per_block); - if (!eraseblocks[i].pkt_indices) { - fprintf(stderr, "Failed to allocate packet indices\n"); - exit(1); - } - eraseblocks[i].nr_pkts = 0; - if (!file_mode) { - if (mtdoffset >= meminfo.size) { - fprintf(stderr, "Run out of space on flash\n"); - exit(1); - } -#if 1 /* Deliberately use bad blocks... test write failures */ - while (ioctl(flfd, MEMGETBADBLOCK, &mtdoffset) > 0) { - printf("Skipping flash bad block at %08x\n", (uint32_t)mtdoffset); - mtdoffset += meminfo.erasesize; - } -#endif - } - eraseblocks[i].flash_offset = mtdoffset; - mtdoffset += meminfo.erasesize; - eraseblocks[i].wbuf_ofs = 0; - } - gettimeofday(&start, NULL); - } - if (image_crc != thispkt.hdr.totcrc) { - fprintf(stderr, "\nImage CRC changed from 0x%x to 0x%x. Aborting\n", - ntohl(image_crc), ntohl(thispkt.hdr.totcrc)); - exit(1); - } - - block_nr = ntohl(thispkt.hdr.block_nr); - if (block_nr >= nr_blocks) { - fprintf(stderr, "\nErroneous block_nr %d (> %d)\n", - block_nr, nr_blocks); - exit(1); - } - for (i=0; i<eraseblocks[block_nr].nr_pkts; i++) { - if (eraseblocks[block_nr].pkt_indices[i] == ntohs(thispkt.hdr.pkt_nr)) { -// printf("Discarding duplicate packet at %08x pkt %d\n", -// block_nr * meminfo.erasesize, eraseblocks[block_nr].pkt_indices[i]); - duplicates++; - break; - } - } - if (i < eraseblocks[block_nr].nr_pkts) { - continue; - } - - if (eraseblocks[block_nr].nr_pkts >= pkts_per_block) { - /* We have a block which we didn't really need */ - eraseblocks[block_nr].nr_pkts++; - ignored_pkts++; - continue; - } - - if (mtd_crc32(-1, thispkt.data, PKT_SIZE) != ntohl(thispkt.hdr.thiscrc)) { - printf("\nDiscard %08x pkt %d with bad CRC (%08x not %08x)\n", - block_nr * meminfo.erasesize, ntohs(thispkt.hdr.pkt_nr), - mtd_crc32(-1, thispkt.data, PKT_SIZE), - ntohl(thispkt.hdr.thiscrc)); - badcrcs++; - continue; - } - pkt_again: - eraseblocks[block_nr].pkt_indices[eraseblocks[block_nr].nr_pkts++] = - ntohs(thispkt.hdr.pkt_nr); - total_pkts++; - if (!(total_pkts % 50) || total_pkts == pkts_per_block * nr_blocks) { - uint32_t pkts_sent = ntohl(thispkt.hdr.pkt_sequence) - start_seq + 1; - long time_msec; - gettimeofday(&now, NULL); - - time_msec = ((now.tv_usec - start.tv_usec) / 1000) + - (now.tv_sec - start.tv_sec) * 1000; - - printf("\rReceived %d/%d (%d%%) in %lds @%ldKiB/s, %d lost (%d%%), %d dup/xs ", - total_pkts, nr_blocks * pkts_per_block, - total_pkts * 100 / nr_blocks / pkts_per_block, - time_msec / 1000, - total_pkts * PKT_SIZE / 1024 * 1000 / time_msec, - pkts_sent - total_pkts - duplicates - ignored_pkts, - (pkts_sent - total_pkts - duplicates - ignored_pkts) * 100 / pkts_sent, - duplicates + ignored_pkts); - fflush(stdout); - } - - if (eraseblocks[block_nr].wbuf_ofs + PKT_SIZE < WBUF_SIZE) { - /* New packet doesn't full the wbuf */ - memcpy(eraseblocks[block_nr].wbuf + eraseblocks[block_nr].wbuf_ofs, - thispkt.data, PKT_SIZE); - eraseblocks[block_nr].wbuf_ofs += PKT_SIZE; - } else { - int fits = WBUF_SIZE - eraseblocks[block_nr].wbuf_ofs; - ssize_t wrotelen; - static int faked = 1; - - memcpy(eraseblocks[block_nr].wbuf + eraseblocks[block_nr].wbuf_ofs, - thispkt.data, fits); - wrotelen = pwrite(flfd, eraseblocks[block_nr].wbuf, WBUF_SIZE, - eraseblocks[block_nr].flash_offset); - - if (wrotelen < WBUF_SIZE || (block_nr == 5 && eraseblocks[block_nr].nr_pkts == 5 && !faked)) { - faked = 1; - if (wrotelen < 0) - perror("\npacket write"); - else - fprintf(stderr, "\nshort write of packet wbuf\n"); - - if (!file_mode) { - struct erase_info_user erase; - /* FIXME: Perhaps we should store pkt crcs and try - to recover data from the offending eraseblock */ - - /* We have increased nr_pkts but not yet flash_offset */ - erase.start = eraseblocks[block_nr].flash_offset & - ~(meminfo.erasesize - 1); - erase.length = meminfo.erasesize; - - printf("Will erase at %08x len %08x (bad write was at %08x)\n", - erase.start, erase.length, eraseblocks[block_nr].flash_offset); - if (ioctl(flfd, MEMERASE, &erase)) { - perror("MEMERASE"); - exit(1); - } - if (mtdoffset >= meminfo.size) { - fprintf(stderr, "Run out of space on flash\n"); - exit(1); - } - while (ioctl(flfd, MEMGETBADBLOCK, &mtdoffset) > 0) { - printf("Skipping flash bad block at %08x\n", (uint32_t)mtdoffset); - mtdoffset += meminfo.erasesize; - if (mtdoffset >= meminfo.size) { - fprintf(stderr, "Run out of space on flash\n"); - exit(1); - } - } - eraseblocks[block_nr].flash_offset = mtdoffset; - printf("Block #%d will now be at %08lx\n", block_nr, (long)mtdoffset); - total_pkts -= eraseblocks[block_nr].nr_pkts; - eraseblocks[block_nr].nr_pkts = 0; - eraseblocks[block_nr].wbuf_ofs = 0; - mtdoffset += meminfo.erasesize; - goto pkt_again; - } - else /* Usually nothing we can do in file mode */ - exit(1); - } - eraseblocks[block_nr].flash_offset += WBUF_SIZE; - /* Copy the remainder into the wbuf */ - memcpy(eraseblocks[block_nr].wbuf, &thispkt.data[fits], PKT_SIZE - fits); - eraseblocks[block_nr].wbuf_ofs = PKT_SIZE - fits; - } - - if (eraseblocks[block_nr].nr_pkts == pkts_per_block) { - eraseblocks[block_nr].crc = ntohl(thispkt.hdr.block_crc); - - if (total_pkts == nr_blocks * pkts_per_block) - break; - } - } - printf("\n"); - gettimeofday(&now, NULL); - net_time = (now.tv_usec - start.tv_usec) / 1000; - net_time += (now.tv_sec - start.tv_sec) * 1000; - close(sock); - for (block_nr = 0; block_nr < nr_blocks; block_nr++) { - ssize_t rwlen; - gettimeofday(&start, NULL); - eraseblocks[block_nr].flash_offset -= meminfo.erasesize; - rwlen = pread(flfd, eb_buf, meminfo.erasesize, eraseblocks[block_nr].flash_offset); - - gettimeofday(&now, NULL); - rflash_time += (now.tv_usec - start.tv_usec) / 1000; - rflash_time += (now.tv_sec - start.tv_sec) * 1000; - if (rwlen < 0) { - perror("read"); - /* Argh. Perhaps we could go back and try again, but if the flash is - going to fail to read back what we write to it, and the whole point - in this program is to write to it, what's the point? */ - fprintf(stderr, "Packets we wrote to flash seem to be unreadable. Aborting\n"); - exit(1); - } - - memcpy(eb_buf + meminfo.erasesize, eraseblocks[block_nr].wbuf, - eraseblocks[block_nr].wbuf_ofs); - - for (i=0; i < pkts_per_block; i++) - src_pkts[i] = &eb_buf[i * PKT_SIZE]; - - gettimeofday(&start, NULL); - if (fec_decode(fec, src_pkts, eraseblocks[block_nr].pkt_indices, PKT_SIZE)) { - /* Eep. This cannot happen */ - printf("The world is broken. fec_decode() returned error\n"); - exit(1); - } - gettimeofday(&now, NULL); - fec_time += (now.tv_usec - start.tv_usec) / 1000; - fec_time += (now.tv_sec - start.tv_sec) * 1000; - - for (i=0; i < pkts_per_block; i++) - memcpy(&decode_buf[i*PKT_SIZE], src_pkts[i], PKT_SIZE); - - /* Paranoia */ - gettimeofday(&start, NULL); - if (mtd_crc32(-1, decode_buf, meminfo.erasesize) != eraseblocks[block_nr].crc) { - printf("\nCRC mismatch for block #%d: want %08x got %08x\n", - block_nr, eraseblocks[block_nr].crc, - mtd_crc32(-1, decode_buf, meminfo.erasesize)); - exit(1); - } - gettimeofday(&now, NULL); - crc_time += (now.tv_usec - start.tv_usec) / 1000; - crc_time += (now.tv_sec - start.tv_sec) * 1000; - start = now; - - if (!file_mode) { - struct erase_info_user erase; - - erase.start = eraseblocks[block_nr].flash_offset; - erase.length = meminfo.erasesize; - - printf("\rErasing block at %08x...", erase.start); - - if (ioctl(flfd, MEMERASE, &erase)) { - perror("MEMERASE"); - /* This block has dirty data on it. If the erase failed, we're screwed */ - fprintf(stderr, "Erase to clean FEC data from flash failed. Aborting\n"); - exit(1); - } - gettimeofday(&now, NULL); - erase_time += (now.tv_usec - start.tv_usec) / 1000; - erase_time += (now.tv_sec - start.tv_sec) * 1000; - start = now; - } - else printf("\r"); - write_again: - rwlen = pwrite(flfd, decode_buf, meminfo.erasesize, eraseblocks[block_nr].flash_offset); - if (rwlen < meminfo.erasesize) { - if (rwlen < 0) { - perror("\ndecoded data write"); - } else - fprintf(stderr, "\nshort write of decoded data\n"); - - if (!file_mode) { - struct erase_info_user erase; - erase.start = eraseblocks[block_nr].flash_offset; - erase.length = meminfo.erasesize; - - printf("Erasing failed block at %08x\n", - eraseblocks[block_nr].flash_offset); - - if (ioctl(flfd, MEMERASE, &erase)) { - perror("MEMERASE"); - exit(1); - } - if (mtdoffset >= meminfo.size) { - fprintf(stderr, "Run out of space on flash\n"); - exit(1); - } - while (ioctl(flfd, MEMGETBADBLOCK, &mtdoffset) > 0) { - printf("Skipping flash bad block at %08x\n", (uint32_t)mtdoffset); - mtdoffset += meminfo.erasesize; - if (mtdoffset >= meminfo.size) { - fprintf(stderr, "Run out of space on flash\n"); - exit(1); - } - } - printf("Will try again at %08lx...", (long)mtdoffset); - eraseblocks[block_nr].flash_offset = mtdoffset; - - goto write_again; - } - else /* Usually nothing we can do in file mode */ - exit(1); - } - gettimeofday(&now, NULL); - flash_time += (now.tv_usec - start.tv_usec) / 1000; - flash_time += (now.tv_sec - start.tv_sec) * 1000; - - printf("wrote image block %08x (%d pkts) ", - block_nr * meminfo.erasesize, eraseblocks[block_nr].nr_pkts); - fflush(stdout); - } - close(flfd); - printf("Net rx %ld.%03lds\n", net_time / 1000, net_time % 1000); - printf("flash rd %ld.%03lds\n", rflash_time / 1000, rflash_time % 1000); - printf("FEC time %ld.%03lds\n", fec_time / 1000, fec_time % 1000); - printf("CRC time %ld.%03lds\n", crc_time / 1000, crc_time % 1000); - printf("flash wr %ld.%03lds\n", flash_time / 1000, flash_time % 1000); - printf("flash er %ld.%03lds\n", erase_time / 1000, erase_time % 1000); - - return 0; -} |