Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _GNU_SOURCE
- #include <fcntl.h>
- #include <pthread.h>
- #include <dirent.h>
- #include <errno.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <linux/if_packet.h>
- #include <linux/ip.h>
- #include <net/if.h>
- #include <netinet/ether.h>
- #include <signal.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <sys/syscall.h>
- #include <mfe_control.h>
- #include <mfe_control_linux_uland.h>
- #include <mfe_config.h>
- #include "libarg.h"
- #define ETHERTYPE_BER 0xa5a5
- #define FUNC_SENDTO 0
- #define FUNC_SENDMSG 1
- #define FUNC_SENDMMSG 2
- #ifndef PACKET_QDISC_BYPASS
- #define PACKET_QDISC_BYPASS 20
- #endif
- typedef struct func_ctx func_ctx_t;
- typedef unsigned long long (*func_t)(struct func_ctx *);
- typedef struct ftable_entry {
- char *name;
- func_t func;
- func_t rfunc;
- } ftable_entry_t;
- unsigned long long do_sendto(struct func_ctx *ctx);
- unsigned long long do_recvfrom(struct func_ctx *ctx);
- #define LOG_BASE 0
- #define LOG_META 1
- #define LOG_EXTENDED 2
- static int log_level;
- typedef struct thread_arg {
- uint8_t suppress_all;
- uint8_t func_no;
- char *if_name;
- ssize_t fsize;
- struct supp_adrs* supp_head;
- func_t rfunc;
- func_ctx_t *ctx;
- pthread_spinlock_t lock;
- } thread_arg_t;
- typedef struct supp_adrs {
- struct ether_addr *eaddr;
- struct supp_adrs *next;
- } supp_adrs_t;
- typedef struct mac_addresses {
- char *if_name;
- char *if_mac;
- struct mac_addresses *next;
- } mac_addresses_t;
- struct ber_proto {
- unsigned long long num;
- unsigned short csum;
- unsigned short tail;
- } __attribute__((packed));
- static volatile sig_atomic_t g_stop = 0, g_alarm = 0;
- void sighandler(int n)
- {
- static char buf[32];
- memset(buf, 0, 32);
- switch (n) {
- case SIGINT:
- case SIGPIPE:
- case SIGHUP:
- case SIGTERM:
- g_stop = 1;
- snprintf(buf, 32, "\nINTERRUPT SIGNAL CATCHED\n");
- break;
- case SIGALRM:
- snprintf(buf, 32, "ALARM SIGNAL CATCHED\n");
- g_alarm = 1;
- break;
- default:
- snprintf(buf, 32, "\nsignal %d arrived\npipe", n);
- };
- write(0, buf, 32);
- }
- int print_log(int level, const char *format, ...)
- {
- int ret = 0;
- va_list args;
- if (level <= log_level) {
- va_start(args, format);
- ret = vprintf(format, args);
- va_end(args);
- fflush(stdout);
- }
- return ret;
- }
- struct mac_addresses* getmactable()
- {
- DIR *dir;
- struct dirent *entry;
- char *if_name, *if_mac, *p;
- int fd, ret;
- struct stat st;
- struct mac_addresses *head = NULL, *t = NULL;
- if (!(dir = opendir("/sys/class/net/")))
- return NULL;
- if (!(entry = readdir(dir)))
- return NULL;
- do {
- if (entry->d_type == DT_LNK) {
- char fname[strlen("/sys/class/net/") + strlen(entry->d_name) + strlen("/address") + 1];
- if_name = (char *)malloc(sizeof(char) * strlen(entry->d_name) + 1);
- memset(if_name, 0, sizeof(char) * strlen(entry->d_name) + 1);
- strcpy(if_name, entry->d_name);
- sprintf(fname, "/sys/class/net/%s/address", entry->d_name);
- fd = open(fname, 0);
- if (fd < 0) {
- free(if_name);
- continue;
- }
- ret = stat(fname, &st);
- if (ret < 0) {
- free(if_name);
- continue;
- }
- if_mac = (char*)malloc(sizeof(char) * st.st_size + 1);
- memset(if_mac, 0, sizeof(char) * st.st_size + 1);
- ret = read(fd, if_mac, st.st_size);
- if (ret < 0) {
- free(if_name);
- free(if_mac);
- continue;
- }
- p = strchr(if_mac, '\n');
- if (p)
- *p = '\0';
- if (head == NULL) {
- head = (struct mac_addresses *)malloc(sizeof(struct mac_addresses));
- t = head;
- } else {
- t->next = (struct mac_addresses *)malloc(sizeof(struct mac_addresses));
- t = t->next;
- }
- t->if_name = if_name;
- t->if_mac = if_mac;
- t->next = NULL;
- }
- } while ((entry = readdir(dir)));
- closedir(dir);
- return head;
- }
- char* getifnamebymac(char *mac, struct mac_addresses* table)
- {
- char *ret = NULL;
- while (table) {
- // printf("'%s' ~ '%s'\n", mac, table->if_mac);
- if (!strncmp(mac, table->if_mac, strlen(mac))) {
- ret = table->if_name;
- break;
- }
- table = table->next;
- }
- return ret;
- }
- int is_suppressed(supp_adrs_t *supp_head, uint8_t *addr)
- {
- supp_adrs_t *t = supp_head;
- int ret = 0;
- while (t) {
- #if 0
- printf("%x:%x:%x:%x:%x:%x ~ %x:%x:%x:%x:%x:%x\n", t->eaddr->ether_addr_octet[0], t->eaddr->ether_addr_octet[1], t->eaddr->ether_addr_octet[2],
- t->eaddr->ether_addr_octet[3], t->eaddr->ether_addr_octet[4], t->eaddr->ether_addr_octet[5], addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
- #endif
- if (!memcmp(t->eaddr->ether_addr_octet, addr, ETH_ALEN)) {
- ret = 1;
- break;
- }
- t = t->next;
- }
- return ret;
- }
- unsigned short csum(unsigned short *buf, unsigned int n)
- {
- unsigned short byte;
- short ret;
- register unsigned long sum = 0;
- while (n > 1) {
- sum += *buf++;
- n -= 2;
- }
- if (n == 1) {
- byte = 0;
- *((u_char*)&byte) = *(u_char*)buf;
- sum += byte;
- sum += htons(*(u_char *)buf << 8);
- }
- sum = (sum >> 16) + (sum & 0xffff);
- sum = sum + (sum >> 16);
- ret = (unsigned short)~sum;
- return ret;
- }
- struct func_ctx {
- int sockfd;
- int rsockfd;
- struct ether_header *ether_hdr;
- int tx_len;
- unsigned long long fcount;
- ssize_t fsize;
- struct sockaddr_ll *sockaddr;
- thread_arg_t *th_arg;
- int msgs_cnt;
- struct iovec *iov;
- unsigned char *dest_mac;
- union {
- uint8_t *buf;
- uint8_t **msgbuf;
- } b;
- uint32_t time;
- uint8_t type;
- };
- int wait_snd(int sock)
- {
- fd_set RD, WR, EXP;
- struct timespec ts;
- int R;
- FD_ZERO(&RD);
- FD_ZERO(&WR);
- FD_ZERO(&EXP);
- FD_SET(sock, &RD);
- ts.tv_sec = 0;
- ts.tv_nsec = 1;
- reselect:
- // We assume that tmo recalculated by Linux kernel
- R = pselect(sock, &RD, &WR, &EXP, &ts, NULL);
- switch (R)
- {
- case 0:
- case 1:
- return R;
- case -1:
- default:
- switch(errno)
- {
- case EINTR:
- goto reselect;
- default:
- return -errno;
- }
- }
- }
- inline unsigned long long do_sendto(struct func_ctx *ctx)
- {
- unsigned long long i = 0, sent_bytes = 0, fcount = ctx->fcount;
- int sockfd = ctx->sockfd, tx_len = ctx->tx_len;
- ssize_t ret, fsize = ctx->fsize;
- struct sockaddr_ll *sockaddr = ctx->sockaddr;
- uint8_t *buf = ctx->b.buf;
- struct ether_header *ether_hdr = (struct ether_header *)buf;
- struct ber_proto *ber = (struct ber_proto *) &buf[sizeof(struct ether_header)];
- // thread_arg_t *th_arg = ctx->th_arg;
- for (i = 0; ((i < fcount - (fcount > 2 ? 2 : 0))|| (ctx->time && !g_alarm)) && !g_stop; i++) {
- ber->num = i + 1;
- ber->csum = 0;
- ber->tail = 0;
- ber->csum = csum((unsigned short *)buf, fsize);
- do_send1:
- ether_hdr->ether_type = ETHERTYPE_BER;
- if (g_stop)
- return ber->num;
- ret = sendto(sockfd, buf, tx_len, /*MSG_DONTWAIT*/0, (struct sockaddr *)sockaddr, sizeof(struct sockaddr_ll));
- if (ret < 0) {
- if (errno == ENOBUFS || errno == EAGAIN) {
- goto do_send1;
- }
- fprintf(stderr, "sendto[%llu]: %s (%d)\n", i, sys_errlist[errno], errno);
- ret = 1;
- break;
- }
- sent_bytes += ret;
- }
- ber->num = i + 1;
- ber->csum = 0;
- ber->tail = 0xE4ED;
- ber->csum = csum((unsigned short *)buf, fsize);
- do_send2:
- ret = sendto(sockfd, buf, tx_len, /*MSG_DONTWAIT*/0, (struct sockaddr *)sockaddr, sizeof(struct sockaddr_ll));
- if (ret < 0) {
- if (errno == ENOBUFS || errno == EAGAIN) {
- usleep(300000);
- goto do_send2;
- } else
- fprintf(stderr, "sendto[%llu]: %s (%d)\n", i, sys_errlist[errno], errno);
- }
- ber->num = i + 2;
- ber->csum = 0;
- ber->tail = 0xe6ed;
- ber->csum = csum((unsigned short *)buf, fsize);
- do_send3:
- ret = sendto(sockfd, buf, tx_len, /*MSG_DONTWAIT*/0, (struct sockaddr *)sockaddr, sizeof(struct sockaddr_ll));
- print_log(LOG_EXTENDED, "-> packet[%d]: ", fsize);
- for (i = 0; (ssize_t)i < fsize; i++)
- print_log(LOG_EXTENDED, "%02x%c", buf[i], (ssize_t)i == fsize - 1 ? '\0' : ':');
- print_log(LOG_EXTENDED, "\n");
- if (ret < 0) {
- if (errno == ENOBUFS || errno == EAGAIN) {
- usleep(300000);
- goto do_send3;
- } else
- fprintf(stderr, "sendto[%llu]: %s (%d)\n", i, sys_errlist[errno], errno);
- }
- return ber->num;
- }
- void* receiver(void *arg)
- {
- int sockfd, sockopt = 1, i;
- struct ifreq ifopts;
- struct ifreq ifr;
- uint8_t *buf = NULL;
- unsigned char dest_mac[6];
- unsigned long long pkt_received = 0;
- struct thread_arg *th_arg = (struct thread_arg *)arg;
- func_t rfunc = th_arg->rfunc;
- struct func_ctx *ctx = th_arg->ctx;
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, SIGINT);
- if (pthread_sigmask(SIG_BLOCK, &set, NULL)) {
- printf("error: cannot block SIGINT\n");
- return (void *)-1;
- }
- memset(&ifr, 0, sizeof(struct ifreq));
- if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
- fprintf(stderr, "socket: %s\n", sys_errlist[errno]);
- return (void *)-1;
- }
- strncpy(ifopts.ifr_name, th_arg->if_name, IFNAMSIZ - 1);
- ioctl(sockfd, SIOCGIFFLAGS, &ifopts);
- ifopts.ifr_flags |= IFF_PROMISC;
- if (ioctl(sockfd, SIOCSIFFLAGS, &ifopts)) {
- fprintf(stderr, "ioctl(SIOCSIFFLAGS): %s: %s\n", th_arg->if_name, sys_errlist[errno]);
- close(sockfd);
- return (void *)-1;
- }
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)) == -1) {
- fprintf(stderr, "setcockopt(SO_REUSEADDR): %s: %s\n", th_arg->if_name, sys_errlist[errno]);
- close(sockfd);
- return (void *)-1;
- }
- if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifopts.ifr_name, IFNAMSIZ - 1) == -1) {
- fprintf(stderr, "setsockopt(SO_BINDTODEVICE): %s: %s\n", th_arg->if_name, sys_errlist[errno]);
- close(sockfd);
- return (void *)-1;
- }
- strncpy(ifr.ifr_name, th_arg->if_name, IFNAMSIZ - 1);
- ioctl(sockfd, SIOCGIFHWADDR, &ifr);
- print_log(LOG_BASE, "receiving on %s ", ifr.ifr_name);
- for(i = 0; i < 6; i++) {
- dest_mac[i] = ifr.ifr_hwaddr.sa_data[i] & 0xff;
- print_log(LOG_BASE, "%02x%s", dest_mac[i], i < 5 ? ":" : "");
- }
- print_log(LOG_BASE, "\n");
- ctx->rsockfd = sockfd;
- if (ctx->dest_mac == NULL)
- ctx->dest_mac = dest_mac;
- ctx->th_arg = th_arg;
- pkt_received = rfunc(ctx);
- strncpy(ifopts.ifr_name, th_arg->if_name, IFNAMSIZ - 1);
- ifopts.ifr_flags &= ~IFF_PROMISC;
- if (ioctl(sockfd, SIOCGIFFLAGS, &ifopts))
- fprintf(stderr, "ioctl(SIOCSIFFLAGS): %s: %s\n", th_arg->if_name, sys_errlist[errno]);
- close(sockfd);
- free(buf);
- return (void *)pkt_received;
- }
- int wait_recv(int sock)
- {
- fd_set RD, WR, EXP;
- struct timeval tmo;
- int R;
- FD_ZERO(&RD);
- FD_ZERO(&WR);
- FD_ZERO(&EXP);
- FD_SET(sock, &RD);
- tmo.tv_sec = 0;
- tmo.tv_usec = 100000;
- reselect:
- // We assume that tmo recalculated by Linux kernel
- R = select(sock + 1, &RD, &WR, &EXP, &tmo);
- switch (R)
- {
- case 0:
- case 1:
- return R;
- case -1:
- default:
- switch(errno)
- {
- case EINTR:
- goto reselect;
- default:
- return -errno;
- }
- }
- }
- inline unsigned long long do_recvfrom(struct func_ctx *ctx)
- {
- int sockfd = ctx->rsockfd, i, j;
- thread_arg_t *th_arg = (thread_arg_t *)ctx->th_arg;
- ssize_t fsize = th_arg->fsize;
- uint8_t xor, *buf = (uint8_t *)malloc(sizeof(uint8_t) * ctx->fsize); //ctx->b.buf;
- unsigned char *dest_mac = ctx->dest_mac;
- struct ether_header *ether_hdr = (struct ether_header *)buf;
- struct ber_proto *ber = (struct ber_proto *) &buf[sizeof(struct ether_header)];
- unsigned short pcsum;
- unsigned long long bit_err = 0, pkt_num = 0, out_of_order = 0, pkt_received = 0, pkt_csum_err = 0;
- int tail = 0;//, pl = sizeof(struct ether_header) + sizeof(struct ber_proto);
- pthread_spin_unlock(&th_arg->lock);
- while (g_stop != 1) {
- if (wait_recv(sockfd) < 0) {
- fprintf(stderr, "error: wait_recv: %s\n", sys_errlist[errno]);
- g_stop = 1;
- break;
- }
- fsize = recvfrom(sockfd, buf, th_arg->fsize, 0, NULL, NULL);
- if (ntohs(ether_hdr->ether_type) == ETHERTYPE_BER && ether_hdr->ether_dhost[0] == dest_mac[0] && ether_hdr->ether_dhost[1] == dest_mac[1]
- && ether_hdr->ether_dhost[2] == dest_mac[2] && ether_hdr->ether_dhost[3] == dest_mac[3]
- && ether_hdr->ether_dhost[4] == dest_mac[4] && ether_hdr->ether_dhost[5] == dest_mac[5]) {
- pkt_num++;
- if (!ber->tail && ber->num != pkt_num) {
- out_of_order++;
- pkt_num = ber->num;
- bit_err++;
- }
- pkt_received++;
- pcsum = ber->csum;
- ber->csum = 0;
- if (pcsum != csum((unsigned short *)buf, fsize)) {
- pkt_csum_err++;
- print_log(LOG_META, "checksum error %X != %X\n", pcsum, csum((unsigned short *)buf, fsize));
- for (i = 0; i < fsize; i++) {
- if (buf[i] != ctx->b.buf[i]) {
- xor = buf[i] ^ ctx->b.buf[i];
- for (j = 0; j < 8; j++) {
- if ((xor >> j) == 1)
- bit_err++;
- }
- // printf("%llu-%d) buf[i] = %x, ctx->b.buf[i] = %x, buf[i] ^ ctx->b.buf[i] = %x\n", pkt_num, i, buf[i], ctx->b.buf[i], buf[i] ^ ctx->b.buf[i]);
- }
- }
- ber->csum = pcsum;
- }
- // printf("pkt_num = %llu/%llu\n", ber->num, ctx->fcount);
- if (ber->tail == 0xE4ED || ber->tail == 0xE6ED) {
- // printf("tail packet %x captured\n", ber->tail);
- tail++;
- }
- print_log(LOG_EXTENDED,
- "%02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x, %d bytes received\n",
- ether_hdr->ether_shost[0], ether_hdr->ether_shost[1], ether_hdr->ether_shost[2],
- ether_hdr->ether_shost[3], ether_hdr->ether_shost[4], ether_hdr->ether_shost[5],
- ether_hdr->ether_dhost[0], ether_hdr->ether_dhost[1], ether_hdr->ether_dhost[2],
- ether_hdr->ether_dhost[3], ether_hdr->ether_dhost[4], ether_hdr->ether_dhost[5], fsize);
- print_log(LOG_EXTENDED, "packet[%d]: ", fsize);
- ber->csum = pcsum;
- for (i = 0; i < fsize; i++)
- print_log(LOG_EXTENDED, "%02x%c", buf[i], i == fsize - 1 ? '\0' : ':');
- print_log(LOG_EXTENDED, "\n");
- } else {
- if (ntohs(ether_hdr->ether_type) == ETHERTYPE_ARP) {
- print_log(LOG_META, "ARP destination MAC (0x%04x) %02x:%02x:%02x:%02x:%02x:%02x\n", ntohs(ether_hdr->ether_type),
- ether_hdr->ether_dhost[0], ether_hdr->ether_dhost[1], ether_hdr->ether_dhost[2],
- ether_hdr->ether_dhost[3], ether_hdr->ether_dhost[4], ether_hdr->ether_dhost[5]);
- continue;
- }
- if (!th_arg->suppress_all && !is_suppressed(th_arg->supp_head, ether_hdr->ether_dhost)) {
- print_log(LOG_BASE, "wrong destination MAC (0x%04x) %02x:%02x:%02x:%02x:%02x:%02x != %02x:%02x:%02x:%02x:%02x:%02x\n", ntohs(ether_hdr->ether_type),
- ether_hdr->ether_dhost[0], ether_hdr->ether_dhost[1], ether_hdr->ether_dhost[2],
- ether_hdr->ether_dhost[3], ether_hdr->ether_dhost[4], ether_hdr->ether_dhost[5],
- dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5]);
- }
- }
- }
- free(buf);
- printf("number of received packets = %llu\n", pkt_received);
- printf("bit error rate = %.12Lf\n", (long double)bit_err / (ctx->fsize * 8) / (pkt_received + out_of_order));
- printf("test of resistance to load: %s\n", tail > 0 ? "SUCCESS" : "FAIL");
- return pkt_received;
- }
- int fill_suppressed(supp_adrs_t *supp_head, const char *supp_str, uint8_t *suppress_all)
- {
- supp_adrs_t *t, *suppressed;
- struct ether_addr *eaddr;
- int i;
- if (supp_str) {
- char *p = NULL;
- int s = 0, len = strlen(supp_str), n;
- if (!strcmp(supp_str, "all")) {
- *suppress_all = 1;
- } else {
- do {
- p = strchr(supp_str + s, ',');
- if(p)
- *p = 0;
- eaddr = (struct ether_addr *)malloc(sizeof(struct ether_addr));
- n = sscanf(supp_str + s, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
- &eaddr->ether_addr_octet[0], &eaddr->ether_addr_octet[1], &eaddr->ether_addr_octet[2],
- &eaddr->ether_addr_octet[3], &eaddr->ether_addr_octet[4], &eaddr->ether_addr_octet[5]);
- if (n != 6) {
- if (s < len + 1) {
- p = strchr(supp_str + s, ',');
- if (p)
- *p = '\0';
- fprintf(stderr, "error in address '%s'\n", supp_str);
- return 1;
- }
- if (p)
- *p = ',';
- break;
- }
- suppressed = (supp_adrs_t *) malloc(sizeof(supp_adrs_t));
- suppressed->next = NULL;
- suppressed->eaddr = eaddr;
- if (supp_head->next) {
- t = supp_head;
- while (t->next)
- t = t->next;
- t->next = suppressed;
- } else {
- supp_head->next = suppressed;
- }
- s += strlen(supp_str + s) + 1;
- if (p)
- *p = ',';
- } while (p != NULL);
- t = supp_head->next;
- printf ("suppressed list:\n");
- while (t) {
- printf(" ");
- for (i = 0; i < ETH_ALEN; i++)
- printf("%02x%c", t->eaddr->ether_addr_octet[i], i == ETH_ALEN - 1 ? '\0' : ':');
- printf("\n");
- t = t->next;
- }
- }
- }
- return 0;
- }
- #define SEND_MODE 0x0001
- #define RECV_MODE 0x0010
- #define LBCK_MODE 0x0100
- #define CHK(Expr) \
- if ((err = (Expr)) != 0) \
- { \
- printf(#Expr " failed with error %d\n", -err); \
- }
- int get_speed_capability(struct MFE *dev)
- {
- int caps = 0;
- uint16_t reg = 0;
- if (dev == NULL)
- return (uint32_t)-1;
- reg = mfe_reg_read(dev, MFE_BASIC_STATUS_REG);
- if (reg & _10BASE_HD_ST) caps |= MFE_SPEED_10BASE_T_HD;
- if (reg & _10BASE_FD_ST) caps |= MFE_SPEED_10BASE_T_FD;
- if (reg & _100BASE_TX_HD_ST) caps |= MFE_SPEED_100BASE_T_HD;
- if (reg & _100BASE_TX_FD_ST) caps |= MFE_SPEED_100BASE_T_FD;
- if (reg & EXTENDED_STATUS) {
- reg = mfe_reg_read(dev, MFE_EXTENDED_STATUS_REG);
- if (reg & XS_1000BASE_T_HD) caps |= MFE_SPEED_1000BASE_T_HD;
- if (reg & XS_1000BASE_T_FD) caps |= MFE_SPEED_1000BASE_T_FD;
- }
- return caps;
- }
- int configure_device(struct MFE *mfe, int speed, char *name)
- {
- int ret;
- unsigned int id;
- printf("configuring %s with speed mask %x\n", name, speed);
- id = mfe_device_type_id(mfe);
- /*
- if (id != MFE_DEV_TYPE_ID_MICREL && id != MFE_DEV_TYPE_ID_MFE && mfe_check_bit_state(mfe, MFE_BASIC_CONTROL_REG, POWER_DOWN)) {
- mfe_power_down(mfe, 0);
- usleep(1000000);
- } else {
- mfe_reset(mfe);
- do {
- ret = mfe_reg_read(mfe, 0x0);
- } while (ret & RESET);
- }
- */
- if (mfe_check_bit_state(mfe, MFE_BASIC_CONTROL_REG, POWER_DOWN)) {
- printf("configure_device %s wakeup\n", name);
- mfe_power_down(mfe, 0);
- usleep(2000000);
- }
- ret = mfe_reg_read(mfe, 0);
- print_log(LOG_META, "%s[0] = 0x%x\n", name, ret);
- #if 1
- if ((ret = mfe_reg_write(mfe, 0, ret & ~AUTO_NEG_EN)) < 0) {
- printf("configure_device - 1\n");
- // goto out;
- }
- // mfe_reg_write(mfe, MFE_AN_ADVERTISEMENT_REG, 0);
- // mfe_set_autoneg_speeds(mfe, speed);
- if ((ret = mfe_set_fixed_speed(mfe, speed)) < 0) {
- printf("configure_device - 2\n");
- // goto out;
- }
- #else
- if ((mode == LBCK_MODE) && selftest) {
- mfe_reg_write(mfe, 0, ret & ~AUTO_NEG_EN);
- mfe_set_fixed_speed(mfe, speed);
- } else
- mfe_set_autoneg_speeds(mfe, speed);
- #endif
- ret = mfe_reg_read(mfe, 0);
- print_log(LOG_META, "%s[0] = %x\n", name, ret);
- ret = 0;
- //out:
- return ret;
- }
- int init_mfe_devices(struct MFE **ptm, struct MFE **pam, int mode, char *dev, char *rdev, int speed, int selftest)
- {
- int ret = 0, err = 0;
- struct MFE_IDENT mfeid;
- struct MFE *tm = NULL, *am = NULL;
- uint16_t tm_caps, am_caps;
- mfeid.ifname = dev;
- print_log(LOG_META, "dev = %s; rdev = %s\n", dev, rdev);
- if (!(mode == RECV_MODE) && dev && ((err = mfe_open(ptm, &mfeid)) != 0)) {
- printf("failed mfe_open() for '%s' with error %d\n", mfeid.ifname, err);
- ret = -1;
- goto out;
- }
- if (mode == LBCK_MODE) {
- am = tm;
- *pam = *ptm;
- } else {
- mfeid.ifname = rdev;
- if (!(mode == SEND_MODE) && rdev && ((err = mfe_open(pam, &mfeid)) != 0)) {
- printf("failed mfe_open() for '%s' with error %d\n", mfeid.ifname, err);
- ret = -1;
- goto out;
- }
- }
- if (ptm) tm = *ptm;
- if (pam) am = *pam;
- if (tm) {
- printf("TM type ID = 0x%x\n", mfe_device_type_id(tm));
- tm_caps = get_speed_capability(tm);
- printf("tm_caps = 0x%0x\n", tm_caps);
- } else
- tm_caps = 0xffff;
- if (am) {
- printf("AM type ID = 0x%x\n", mfe_device_type_id(am));
- am_caps = get_speed_capability(am);
- printf("am_caps = 0x%0x\n", am_caps);
- } else
- am_caps = 0xffff;
- print_log(LOG_META, "tm speed = %x\n", tm_caps);
- print_log(LOG_META, "am speed = %x\n", am_caps);
- if (tm) {
- print_log(LOG_META, "speed = %dMbps\n", speed);
- switch (speed) {
- case 10:
- if (tm_caps & MFE_SPEED_10BASE_T_FD && am_caps & MFE_SPEED_10BASE_T_FD)
- speed = MFE_SPEED_10BASE_T_FD;
- else
- if (tm_caps & MFE_SPEED_10BASE_T_HD && am_caps & MFE_SPEED_10BASE_T_HD)
- speed = MFE_SPEED_10BASE_T_HD;
- else
- ret = -1;
- break;
- case 100:
- if (tm_caps & MFE_SPEED_100BASE_T_FD && am_caps & MFE_SPEED_100BASE_T_FD)
- speed = MFE_SPEED_100BASE_T_FD;
- else
- if (tm_caps & MFE_SPEED_100BASE_T_HD && am_caps & MFE_SPEED_100BASE_T_HD)
- speed = MFE_SPEED_100BASE_T_HD;
- else
- ret = -1;
- break;
- case 1000:
- if (tm_caps & MFE_SPEED_1000BASE_T_FD && am_caps & MFE_SPEED_1000BASE_T_FD)
- speed = MFE_SPEED_1000BASE_T_FD;
- else
- if (tm_caps & MFE_SPEED_1000BASE_T_HD && am_caps & MFE_SPEED_1000BASE_T_HD)
- speed = MFE_SPEED_1000BASE_T_HD;
- else
- ret = -1;
- break;
- default:
- printf("unknown speed value %d\n", speed);
- ret = -1;
- goto out;
- };
- }
- if (ret == -1) {
- printf ("%s device can not operate at speed %d\n", am_caps < tm_caps ? "am" : "tm", speed);
- goto out;
- }
- if (tm) {
- if ((ret = configure_device(tm, speed, "tm")) < 0) {
- printf("configure_device error %d\n", ret);
- goto out;
- }
- if (speed > MFE_SPEED_100BASE_T_FD) {
- ret = mfe_reg_read(tm, 9);
- mfe_reg_write(tm, 9, ret | (1 << 12));
- ret = mfe_reg_read(tm, 9);
- mfe_reg_write(tm, 9, ret & ~(1 << 11));
- }
- }
- if ((mode == LBCK_MODE) && selftest) {
- printf("loopback selftest mode\n");
- ret = mfe_reg_read(tm, 0);
- print_log(LOG_META, "writing %x to [0]\n", (ret | 0x4000) & ~0x1000);
- do {
- ret = mfe_reg_write(tm, 0, (ret | LOOPBACK) & ~AUTO_NEG_EN);
- usleep(300000);
- ret = mfe_reg_read(tm, 0);
- print_log(LOG_META, "turning loopback (0x%0x) on [0] = 0x%x\n", (ret | LOOPBACK) & ~0x1000, ret);
- } while(!g_stop && ((ret & 0x4000) != 0x4000));
- print_log(LOG_META, "ret = 0x%x\n", ret);
- }
- if ((mode & RECV_MODE) == RECV_MODE) {
- print_log(LOG_META, "init am...\n");
- if (configure_device(am, speed, "am") < 0)
- goto out;
- if (speed > MFE_SPEED_100BASE_T_FD) {
- ret = mfe_reg_read(am, 9);
- mfe_reg_write(am, 9, ret | (1 << 12));
- ret = mfe_reg_read(am, 9);
- mfe_reg_write(am, 9, ret | (1 << 11));
- }
- }
- usleep(500000);
- printf("SPEED = 0x%0x\n", speed);
- if (tm) {
- printf("waiting for tm link... ");
- fflush(stdout);
- // ret = mfe_reg_read(tm, 0x1f);
- // mfe_reg_write(tm, 0x1f, ret & ~((1 << 9) | (1 << 2)));
- //usleep(1000000);
- if (mfe_check_bit_state(tm, MFE_BASIC_CONTROL_REG, POWER_DOWN)) {
- printf("do tm wakeup loop\n");
- mfe_power_down(tm, 0);
- usleep(1000000);
- do {
- usleep(300000);
- ret = mfe_reg_read(tm, 0x01);
- print_log(LOG_META, "tm waiting ret = 0x%x\n", ret);
- } while (!mfe_link_status(tm) && !g_stop);
- }
- printf("done.\n");
- printf("tm speed = %x\n", mfe_get_speed(tm));
- }
- if (am && am != tm && !g_stop) {
- ret = mfe_reg_read(am, 1);
- print_log(LOG_META, "am[1] = 0x%x\n", ret);
- printf("waiting for am link... ");
- fflush(stdout);
- if (mfe_check_bit_state(am, MFE_BASIC_CONTROL_REG, POWER_DOWN)) {
- printf("do am wakeup loop\n");
- mfe_power_down(am, 0);
- // usleep(1000000);
- do {
- usleep(300000);
- ret = mfe_reg_read(am, 0x01);
- print_log(LOG_META, "am waiting ret = 0x%x\n", ret);
- } while (!mfe_link_status(am) && !g_stop);
- }
- printf("done.\n");
- printf("am speed = %x\n", mfe_get_speed(am));
- }
- ret = 0;
- if (g_stop)
- ret = -1;
- out:
- return ret;
- }
- void show_usage(char *arg)
- {
- printf("usage: %s [ options... ]\n"
- "options:\n"
- " [-l eth]\n"
- " loopback mode on interface eth\n"
- " [-s eth]\n"
- " transmitting mode on interface eth\n"
- " [-r eth]\n"
- " receiving mode on interface eth\n"
- " [-smac <MAC address>]\n"
- " force source MAC address\n"
- " [-dmac <MAC address>]\n"
- " force destination MAC address\n"
- " [-f size]\n"
- " size of frame in bytes (1518 by default)\n"
- " [-n number]\n"
- " number of frames\n"
- " [-t time]\n"
- " suggested time of transmitting\n"
- " [-p all|mac1,...,macN]\n"
- " suppess MAC-address(es)\n"
- " [-v number]\n"
- " level of verbosity (0 - 2)\n", arg);
- }
- int main(int argc, char *argv[])
- {
- char *endptr, *dev = NULL, *rdev = NULL, *lo_dev = NULL, *supp_str = NULL, *smac = NULL, *dmac = NULL;
- int sockfd, speed = 0, j = 0, if_src_idx = 0;
- uint8_t suppress_all = 0, err;
- ssize_t ret = 0, fsize;
- struct ifreq if_src, if_dst;
- struct ether_header *ether_hdr;
- struct sockaddr_ll sockaddr;
- uint8_t *buf = NULL, dest_mac[6];
- unsigned long long pkt_sent = 0, i;
- long long fcount;
- unsigned int time;
- struct timespec start_time, stop_time;
- time_t sec = 0;
- long long nsec = 0;
- pthread_t rthr;
- thread_arg_t *th_arg = NULL;
- supp_adrs_t supp_head;
- libarg_ctx *actx = NULL;
- struct mac_addresses *addrs = NULL, *ma_tmp;
- struct func_ctx fctx;
- const int pl = sizeof(struct ether_header) + sizeof(struct ber_proto);
- // uint8_t remote_tm = 0, remote_am = 0;
- int mode = 0, selftest;
- struct MFE *tm = NULL, *am = NULL;
- supp_head.eaddr = NULL;
- supp_head.next = NULL;
- memset(&fctx, 0, sizeof(struct func_ctx));
- if (signal(SIGALRM, sighandler) == SIG_ERR)
- printf("warning: cannot catch SIGALRM\n");
- if (signal(SIGINT, sighandler) == SIG_ERR)
- printf("warning: cannot catch SIGINT\n");
- if (signal(SIGTERM, sighandler) == SIG_ERR)
- printf("warning: cannot catch SIGTERM\n");
- /*
- if (signal(SIGHUP, sighandler) == SIG_ERR)
- printf("warning: cannot catch SIGHUP\n");
- if (signal(SIGPIPE, sighandler) == SIG_ERR)
- printf("warning: cannot catch SIGPIPE\n");
- */
- addrs = getmactable();
- if (addrs == NULL) {
- printf("error: cannot open devices list via sysfs\n");
- return 1;
- }
- actx = libarg_init(show_usage);
- libarg_add_str(actx, 0, &lo_dev, 'l', "--loopback", NULL);
- libarg_add_flag(actx, &selftest, '\0', "--selftest");
- libarg_add_str(actx, 0, &dev, 's', "--send", NULL);
- libarg_add_str(actx, 0, &rdev, 'r', "--recv", NULL);
- libarg_add_longlong(actx, 0, &fcount, 'n', "--fcount", 0);
- libarg_add_uint(actx, 0, &time, 't', "--time", 0);
- libarg_add_ssize(actx, 0, &fsize, 'f', "--fsize", 1518);
- libarg_add_int(actx, 0, &speed, 'c', "--speed", 0);
- libarg_add_int(actx, 0, &log_level, 'v', "--verbosity", 0);
- libarg_add_str(actx, 0, &supp_str, 'p', "--suppress", NULL);
- libarg_add_str(actx, 0, &smac, '\0', "-smac", NULL);
- libarg_add_str(actx, 0, &dmac, '\0', "-dmac", NULL);
- if ((ret = libarg_settle(actx, 1, argc, argv, 0, ' ')) != 0) {
- printf("error with %s\n", ret > 0 ? argv[ret] : argv[0]);
- goto out;
- }
- if (dev)
- mode += SEND_MODE;
- if (rdev)
- mode += RECV_MODE;
- if (lo_dev)
- mode += LBCK_MODE;
- if (mode > LBCK_MODE) {
- printf ("error: loopback mode can not be mixed with another mode\n");
- show_usage(argv[0]);
- goto out;
- }
- if (selftest && (mode != LBCK_MODE)) {
- printf("error: selftest allowed only in loopback mode\n");
- show_usage(argv[0]);
- goto out;
- }
- if (mode == LBCK_MODE) {
- if (dev || rdev) {
- show_usage(argv[0]);
- goto out;
- }
- dev = rdev = lo_dev;
- }
- if ((mode == SEND_MODE)/* && !rdev*/) {
- if (dmac == NULL) {
- printf ("error: dmac either receiving device are needed in transmit mode\n");
- goto out;
- }
- // printf("dmac = %s\n", dmac);
- }
- /*
- if (mode == RECV_MODE) {
- remote_tm = 1;
- }
- */
- if ((mode != RECV_MODE) && fcount <= 0 && time <= 0) {
- printf("error: frame count or time should be setled more than 0\n");
- goto out;
- }
- if (fsize < pl) {
- fsize = pl;
- printf("fsize forced to be minimal %d\n", pl);
- }
- buf = (uint8_t *) malloc(sizeof(uint8_t) * fsize);
- if(fill_suppressed(&supp_head, supp_str, &suppress_all))
- goto out;
- ether_hdr = (struct ether_header *)buf;
- if (dmac) {
- unsigned int a1, a2, a3, a4, a5, a6;
- if (sscanf(dmac, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) == 6) {
- dest_mac[0] = a1;
- dest_mac[1] = a2;
- dest_mac[2] = a3;
- dest_mac[3] = a4;
- dest_mac[4] = a5;
- dest_mac[5] = a6;
- } else {
- printf("error: bad dmac address '%s'\n", dmac);
- goto out;
- }
- }
- if (init_mfe_devices(&tm, &am, mode, dev, rdev, speed, selftest) == -1)
- goto out;
- if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
- fprintf(stderr, "socket: %s\n", sys_errlist[errno]);
- goto out;
- }
- j = 1;
- if (setsockopt(sockfd, SOL_PACKET, PACKET_QDISC_BYPASS, &j, sizeof(j)) == -1) {
- fprintf(stderr, "setsockopt(PACKET_QDISC_BYPASS): %s: %s\n", dev, sys_errlist[errno]);
- goto out;
- }
- fctx.sockfd = sockfd;
- fctx.tx_len = sizeof(struct ether_header) + fsize - 14;
- fctx.fcount = fcount;
- fctx.fsize = fsize;
- fctx.sockaddr = &sockaddr;
- fctx.th_arg = th_arg;
- fctx.ether_hdr = ether_hdr;
- fctx.time = time;
- if (dmac)
- fctx.dest_mac = dest_mac;
- for (j = 0; j < fsize - pl; j++)
- buf[pl + j] = j % 256;
- fctx.b.buf = buf;
- if (dev) {
- memset(&if_src, 0, sizeof(struct ifreq));
- printf("// tm[0] = %x\n", mfe_reg_read(tm, 0));
- CHK(mfe_ifindex(tm, &if_src_idx));
- printf("// tm[0] = %x\n", mfe_reg_read(tm, 0));
- CHK(mfe_macaddr(tm, if_src.ifr_hwaddr.sa_data));
- printf("// tm[0] = %x\n", mfe_reg_read(tm, 0));
- for (i = 0; i < 6; i++)
- ether_hdr->ether_shost[i] = ((uint8_t *)&if_src.ifr_hwaddr.sa_data)[i];
- }
- if (smac) {
- for (i = 0; i < 6; i++) {
- ether_hdr->ether_shost[i] = strtoll(smac + 3 * i, &endptr, 16);
- sockaddr.sll_addr[i] = ether_hdr->ether_shost[i];
- if (!((*endptr == ':' && i < 5) || (*endptr == '\0' && i == 5))) {
- break;
- }
- }
- print_log(LOG_EXTENDED, "smac = %s\n", smac);
- }
- if (dmac) {
- for (i = 0; i < 6; i++) {
- ether_hdr->ether_dhost[i] = strtoll(dmac + 3 * i, &endptr, 16);
- sockaddr.sll_addr[i] = ether_hdr->ether_dhost[i];
- if (!((*endptr == ':' && i < 5) || (*endptr == '\0' && i == 5))) {
- break;
- }
- }
- print_log(LOG_EXTENDED, "dmac = %s\n", dmac);
- }
- ether_hdr->ether_type = htons(ETHERTYPE_BER);
- memset(&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sll_family = AF_PACKET;
- sockaddr.sll_protocol = htons(ETHERTYPE_BER);
- sockaddr.sll_ifindex = if_src_idx;
- sockaddr.sll_hatype = ARPHRD_ETHER;
- sockaddr.sll_pkttype = PACKET_OTHERHOST;
- sockaddr.sll_halen = ETH_ALEN;
- if (rdev || (mode == LBCK_MODE)) {
- if (am) {
- printf("creating receiving thread on %s...\n", rdev);
- CHK(mfe_macaddr(am, if_dst.ifr_hwaddr.sa_data));
- for (i = 0; i < 6; i++) {
- ether_hdr->ether_dhost[i] = ((uint8_t *) & if_dst.ifr_hwaddr.sa_data)[i];
- sockaddr.sll_addr[i] = ether_hdr->ether_dhost[i];
- }
- sockaddr.sll_addr[6] = 0x00;
- sockaddr.sll_addr[7] = 0x00;
- th_arg = (struct thread_arg *)malloc(sizeof(struct thread_arg));
- th_arg->if_name = (char *)malloc(strlen(rdev) + 1);
- strcpy(th_arg->if_name, rdev);
- th_arg->supp_head = supp_head.next;
- th_arg->suppress_all = suppress_all;
- th_arg->fsize = fsize;
- th_arg->ctx = &fctx;
- th_arg->rfunc = do_recvfrom;
- pthread_spin_init(&th_arg->lock, PTHREAD_PROCESS_SHARED);
- pthread_spin_lock(&th_arg->lock);
- pthread_create(&rthr, NULL, receiver, th_arg);
- pthread_spin_lock(&th_arg->lock);
- if (!dev) {
- goto out;
- }
- }
- } else
- printf("receiving thread off\n");
- printf("src MAC = ");
- for (i = 0; i < 6; i++)
- printf("%02x%c", ether_hdr->ether_shost[i], i < 5 ? ':' : ' ');
- printf("\n");
- printf("dst MAC = ");
- for (i = 0; i < 6; i++)
- printf("%02x%c", ether_hdr->ether_dhost[i], i < 5 ? ':' : ' ');
- printf("\n");
- print_log(LOG_EXTENDED, "fcount = %lld, fsize = %ld\n", fcount, fsize);
- printf("time = %d\n", time);
- if (time > 0) {
- // sigaction(SIGALRM, &sa, 0);
- printf("alarm time = %d seconds\n", time);
- alarm(time);
- }
- pkt_sent = 0;
- clock_gettime(CLOCK_REALTIME, &start_time);
- pkt_sent = do_sendto(&fctx);
- clock_gettime(CLOCK_REALTIME, &stop_time);
- if (th_arg)
- th_arg->ctx->fcount = pkt_sent;
- sleep(1); // wait for last packet
- printf("number of sent packets = %llu\n", pkt_sent);
- sec = stop_time.tv_sec - start_time.tv_sec;
- nsec = stop_time.tv_nsec - start_time.tv_nsec;
- if (nsec < 0) {
- sec -= 1;
- nsec = 1e9 - -nsec;
- }
- out:
- if (th_arg) {
- void *th_ret = NULL;
- if(dev)
- g_stop = 1;
- pthread_join(rthr, &th_ret);
- fflush(stdout);
- pthread_spin_unlock(&th_arg->lock);
- pthread_spin_destroy(&th_arg->lock);
- free(th_arg->if_name);
- free(th_arg);
- }
- if (pkt_sent > 0) {
- printf("average speed: %.4lf MB/s\n", fsize * pkt_sent / (sec + (double)nsec / 1e9) / 1024 / 1024);
- }
- if (tm) {
- if (mode == LBCK_MODE) {
- ret = mfe_reg_read(tm, 0);
- // printf ("// tm at exit = 0x%x\n", ret);
- mfe_reg_write(tm, 0, ret & ~0x4000);
- ret = mfe_reg_read(tm, 0);
- // printf ("// reverted tm = 0x%x\n", ret);
- }
- mfe_reset(tm);
- // mfe_power_down(tm, 1);
- mfe_close(tm);
- }
- if (am && !(mode == LBCK_MODE)) {
- mfe_reset(am);
- // mfe_power_down(am, 1);
- mfe_close(am);
- }
- while(addrs) {
- ma_tmp = addrs->next;
- free(addrs->if_name);
- free(addrs->if_mac);
- free(addrs);
- addrs = ma_tmp;
- }
- if (supp_head.next) {
- supp_adrs_t *t = supp_head.next, *tmp;
- while(t) {
- free(t->eaddr);
- tmp = t;
- t = t->next;
- free(tmp);
- }
- }
- libarg_destroy(actx);
- free(buf);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement