/* * This program opens a netmap port and starts receiving packets, * counting all the TCP packets with a destination port specified * by command-line option. */ #include #include #include #include #include #include #include #include #include #define NETMAP_WITH_LIBS #include #include #include #include #include #include #include static int stop = 0; static void sigint_handler(int signum) { stop = 1; } static inline int tcp_port_match(const char *buf, unsigned len, int tcp_port) { struct ether_header *ethh; struct ip *iph; struct tcphdr *tcph; ethh = (struct ether_header *)buf; if (ethh->ether_type != htons(ETHERTYPE_IP)) { /* Filter out non-IP traffic. */ if (ethh->ether_type == htons(ETHERTYPE_ARP)){ printf("ARP PACKET %s: src %s dest %s\n", buf, ethh->ether_dhost, ethh->ether_shost); } else{ printf("Not IP or ARP packet %d\n", ethh->ether_type); } return 0; } else{ printf("Received IP packet %s: src %s dest %s\n", buf, ethh->ether_dhost, ethh->ether_shost); } iph = (struct ip *)(ethh + 1); if (iph->ip_p != IPPROTO_TCP) { /* Filter out non-TCP traffic. */ //printf("NOT TCP packet: %d\n", iph->ip_p); return 0; } tcph = (struct tcphdr *)(iph + 1); /* Match the destination port. */ if (tcph->th_dport == htons(tcp_port)) { printf("PORT matches %d\n", tcph->th_dport ); return 1; } printf("PORT doesn't match %d\n", tcph->th_dport ); return 0; } static int main_loop(const char *netmap_port, int tcp_port) { struct nm_desc *nmd; unsigned long long cnt = 0; unsigned long long tot = 0; nmd = nm_open(netmap_port, NULL, 0, NULL); if (nmd == NULL) { if (!errno) { printf("Failed to nm_open(%s): not a netmap port\n", netmap_port); } else { printf("Failed to nm_open(%s): %s\n", netmap_port, strerror(errno)); } return -1; } while (!stop) { struct pollfd pfd[1]; unsigned int ri; int ret; pfd[0].fd = nmd->fd; pfd[0].events = POLLIN; /* We poll with a timeout to have a chance to break the main loop if * no packets are coming. */ ret = poll(pfd, 1, 1000); if (ret < 0) { perror("poll()"); } else if (ret == 0) { /* Timeout */ continue; } /* Scan all the receive rings. */ for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { struct netmap_ring *rxring; unsigned head, tail; int batch; rxring = NETMAP_RXRING(nmd->nifp, ri); head = rxring->head; tail = rxring->tail; batch = tail - head; if (batch < 0) { batch += rxring->num_slots; } tot += batch; for (; head != tail; head = nm_ring_next(rxring, head)) { struct netmap_slot *slot = rxring->slot + head; char *buf = NETMAP_BUF(rxring, slot->buf_idx); //printf("Received packet %s\n", buf); if (tcp_port_match(buf, slot->len, tcp_port)) { cnt++; } } rxring->cur = rxring->head = head; } } nm_close(nmd); printf("Total received packets: %llu\n", tot); printf("Counted packets : %llu\n", cnt); return 0; } static void usage(char **argv) { printf("usage: %s [-h] [-p TCP_PORT] [-i NETMAP_PORT]\n", argv[0]); exit(EXIT_SUCCESS); } int main(int argc, char **argv) { const char *netmap_port = NULL; int tcp_port = 8000; struct sigaction sa; int opt; int ret; while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { case 'h': usage(argv); return 0; case 'i': netmap_port = optarg; break; case 'p': tcp_port = atoi(optarg); if (tcp_port <= 0 || tcp_port >= 65535) { printf(" invalid TCP port %s\n", optarg); usage(argv); } break; default: printf(" unrecognized option '-%c'\n", opt); usage(argv); return -1; } } if (netmap_port == NULL) { printf(" missing netmap port\n"); usage(argv); } /* Register Ctrl-C handler. */ sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); } printf("Port : %s\n", netmap_port); printf("TCP port: %d\n", tcp_port); main_loop(netmap_port, tcp_port); (void)tcp_port_match; /* silence the compiler */ return 0; }