ProcessorData *init_processor(TableStateMachine *machine, pcap_t *pcap_in, pcap_t *pcap_out, int linkHdrLen, int num_workers, int no_report, int batch) { int i; ProcessorData *processor; processor = (ProcessorData*)malloc(sizeof(ProcessorData)); processor->counter = 0; processor->machine = machine; processor->pcap_in = pcap_in; processor->pcap_out = pcap_out; processor->linkHdrLen = linkHdrLen; processor->no_report = no_report; processor->terminated = 0; processor->next_queue = 0; processor->batch_mode = batch; processor->num_workers = num_workers; for (i = 0; i < num_workers; i++) { packet_buffer_init(&(processor->queues[i])); processor->started[i] = 0; processor->bytes[i] = 0; processor->total_reports[i] = 0; processor->workerData[i].id = i; processor->workerData[i].processor = processor; processor->workerData[i].queue = &(processor->queues[i]); #ifdef __linux__ CPU_ZERO(&(processor->workerData[i].cpuset)); CPU_SET(i, &(processor->workerData[i].cpuset)); pthread_attr_init(&(processor->workerData[i].attr)); pthread_attr_setaffinity_np(&(processor->workerData[i].attr), sizeof(cpu_set_t), &(processor->workerData[i].cpuset)); pthread_attr_setscope(&(processor->workerData[i].attr), PTHREAD_SCOPE_SYSTEM); pthread_create(&(processor->workers[i]), &(processor->workerData[i].attr), worker_start, &(processor->workerData[i])); #else pthread_create(&(processor->workers[i]), NULL, worker_start, &(processor->workerData[i])); #endif } return processor; }
int main(int argc, char *argv[]) { int sockfd_snd, sockfd_rcv_sender, sockfd_rcv_monitor, sockfd_monitor=-1; struct sockaddr_in my_addr; // my address information struct sockaddr_in their_addr; // connector's address information fd_set read_fds_copy, write_fds_copy; socklen_t sin_size; struct timeval start_tv, left_tv; int yes=1;//, flag_send_monitor=0; struct timeval packet_deadline; struct in_addr addr; int flag_measure=0; char ch; unsigned short standalone_port = SENDER_PORT; // Do we use live data? Or previously recorded data? FILE * logfile = NULL; unsigned long quantum_no=0; int logflags = LOG_NOTHING; int select_count = 0; gettimeofday(&packet_deadline, NULL); init(); //set up debug flag if (getenv("Debug")!=NULL) flag_debug=1; else flag_debug=0; flag_standalone = 0; /* * Process command-line arguments */ while ((ch = getopt(argc,argv,"df:l:b:rst")) != -1) { switch (ch) { case 'd': flag_debug = 1; break; case 'f': if (logfile == NULL) { logfile = fopen(optarg, "a"); if (logfile == NULL) { perror("Log fopen()"); exit(1); } } break; case 'b': if (strcmp(optarg, "average") == 0) { bandwidth_method = BANDWIDTH_AVERAGE; } else if (strcmp(optarg, "max") == 0) { bandwidth_method = BANDWIDTH_MAX; } else if (strcmp(optarg, "vegas") == 0) { bandwidth_method = BANDWIDTH_VEGAS; } else if (strcmp(optarg, "buffer") == 0) { bandwidth_method = BANDWIDTH_BUFFER; } else { fprintf(stderr, "Unknown bandwidth method\n"); usage(); exit(1); } break; case 'l': if (strcmp(optarg, "everything") == 0) { logflags = LOG_EVERYTHING; } else if (strcmp(optarg, "nothing") == 0) { logflags = LOG_NOTHING; } else if (strcmp(optarg, "control-send") == 0) { logflags = logflags | CONTROL_SEND; } else if (strcmp(optarg, "control-receive") == 0) { logflags = logflags | CONTROL_RECEIVE; } else if (strcmp(optarg, "tcptrace-send") == 0) { logflags = logflags | TCPTRACE_SEND; } else if (strcmp(optarg, "tcptrace-receive") == 0) { logflags = logflags | TCPTRACE_RECEIVE; } else if (strcmp(optarg, "sniff-send") == 0) { logflags = logflags | SNIFF_SEND; } else if (strcmp(optarg, "sniff-receive") == 0) { logflags = logflags | SNIFF_RECEIVE; } else if (strcmp(optarg, "peer-write") == 0) { logflags = logflags | PEER_WRITE; } else if (strcmp(optarg, "peer-read") == 0) { logflags = logflags | PEER_READ; } else if (strcmp(optarg, "main-loop") == 0) { logflags = logflags | MAIN_LOOP; } else if (strcmp(optarg, "lookup-db") == 0) { logflags = logflags | LOOKUP_DB; } else if (strcmp(optarg, "delay-detail") == 0) { logflags = logflags | DELAY_DETAIL; } else if (strcmp(optarg, "packet-buffer-detail") == 0) { logflags = logflags | PACKET_BUFFER_DETAIL; } else { fprintf(stderr, "Unknown logging option %s\n", optarg); usage(); exit(1); } break; case 's': flag_standalone = 1; break; case 'r': flag_standalone = 1; is_live = 0; break; case 't': flag_testmode = 1; break; default: fprintf(stderr,"Unknown option %c\n",ch); usage(); exit(1); } } argc -= optind; argv += optind; if (logfile == NULL) { logfile = stderr; } logInit(logfile, logflags, 1); if (flag_standalone) { if (argc != 3) { fprintf(stderr,"Wrong number of options for standalone: %i\n",argc); usage(); exit(1); } else { flag_measure = 1; // rcvdb[0].valid = 1; standalone_port = atoi(argv[2]); inet_aton(argv[1], &addr); insert_fake(addr.s_addr, standalone_port); // rcvdb[0].ip = addr.s_addr; // rcvdb[0].sockfd= -1; //show error if used // rcvdb[0].last_usetime = time(NULL); } printf("Running in standalone mode\n"); } else { if (argc != 1) { fprintf(stderr,"Wrong number of options: %i\n",argc); usage(); exit(1); } } if (flag_testmode) { printf("Running in testmode\n"); test_state = TEST_NOTSTARTED; } if (strlen(argv[0]) > 127) { fprintf(stderr,"Error: the <sniff-interface> name must be less than 127 characters \n"); exit(1); } // strcpy(sniff_interface, argv[0]); //set up the sender connection listener if ((sockfd_rcv_sender = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sockfd_rcv_sender, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(SENDER_PORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP // memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct if (flag_debug) printf("Listen on %s\n",inet_ntoa(my_addr.sin_addr)); if (bind(sockfd_rcv_sender, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } if (listen(sockfd_rcv_sender, PENDING_CONNECTIONS) == -1) { perror("listen"); exit(1); } //set up the monitor connection listener if ((sockfd_rcv_monitor = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sockfd_rcv_monitor, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(MONITOR_PORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP // memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct if (flag_debug) printf("Listen on %s\n",inet_ntoa(my_addr.sin_addr)); if (bind(sockfd_rcv_monitor, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } if (listen(sockfd_rcv_monitor, 1) == -1) { perror("listen"); exit(1); } //initialization packet_buffer_init(); init_random_buffer(); init_pcap(SNIFF_TIMEOUT, standalone_port, argv[0]); FD_ZERO(&read_fds); FD_ZERO(&read_fds_copy); FD_ZERO(&write_fds); FD_ZERO(&write_fds_copy); FD_SET(pcapfd, &read_fds); FD_SET(sockfd_rcv_sender, &read_fds); FD_SET(sockfd_rcv_monitor, &read_fds); maxfd = pcapfd; //socket order sin_size = sizeof(struct sockaddr_in); //main loop - the stubd runs forever while (1) { // flag_send_monitor=0; //reset flag for each quanta gettimeofday(&start_tv, NULL); //reset start time for each quanta // printf("Total: %d\n", total_size); // printf("========== Quantum %lu ==========\n", quantum_no); logWrite(MAIN_LOOP, NULL, "Quantum %lu", quantum_no); if (is_live) { update_stats(); logWrite(MAIN_LOOP, NULL, "PCAP Received: %u Dropped: %u", received_stat(), dropped_stat()); } quantum_no++; //while in a quanta while(have_time(&start_tv, &left_tv)) { read_fds_copy = read_fds; write_fds_copy = write_fds; select_count = select(maxfd+1, &read_fds_copy, &write_fds_copy, NULL, &left_tv); if (select_count == -1) { perror("select"); clean_exit(1); } // fprintf(stderr, "Select count: %d\n", select_count); // Send out packets to our peers if the deadline has passed. // logWrite(MAIN_LOOP, NULL, "Send normal packets to peers"); handle_packet_buffer(&packet_deadline, &write_fds_copy); // send to destinations which are writeable and are behind. // logWrite(MAIN_LOOP, NULL, "Send pending packets to peers"); #ifdef USE_PACKET_BUFFER for_each_pending(try_pending, &write_fds_copy); #endif // receive from existing senders // logWrite(MAIN_LOOP, NULL, "Receive packets from peers"); for_each_readable_sender(receive_sender, &read_fds_copy); /* //receive from existent senders for (i=0; i<CONCURRENT_SENDERS; i++){ // Send pending data if it exists. if (snddb[i].valid==1 && FD_ISSET(snddb[i].sockfd, &read_fds_copy)) { receive_sender(i); } } */ //handle new senders if (FD_ISSET(sockfd_rcv_sender, &read_fds_copy)) { if ((sockfd_snd = accept(sockfd_rcv_sender, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } else { logWrite(MAIN_LOOP, NULL, "Accept new peer (%s)", inet_ntoa(their_addr.sin_addr)); replace_sender_by_stub_port(their_addr.sin_addr.s_addr, ntohs(their_addr.sin_port), sockfd_snd, &read_fds); // insert_db(their_addr.sin_addr.s_addr, their_addr.sin_port, // SENDER_PORT, sockfd_snd, 1); //insert snddb // FD_SET(sockfd_snd, &read_fds); // add to master set // if (sockfd_snd > maxfd) { // keep track of the maximum // maxfd = sockfd_snd; // } if (flag_debug) printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr)); } } //handle the new monitor if (FD_ISSET(sockfd_rcv_monitor, &read_fds_copy)) { if ((sockfd_monitor = accept(sockfd_rcv_monitor, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } else { int nodelay = 1; int nodelay_error = setsockopt(sockfd_monitor, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); if (nodelay_error == -1) { perror("setsockopt (TCP_NODELAY)"); clean_exit(1); } logWrite(MAIN_LOOP, NULL, "Accept new monitor (%s)", inet_ntoa(their_addr.sin_addr)); FD_CLR(sockfd_rcv_monitor, &read_fds); //allow only one monitor connection FD_SET(sockfd_monitor, &read_fds); //check the monitor connection for read // FD_SET(sockfd_monitor, &write_fds); //check the monitor connection for write if (sockfd_monitor > maxfd) { //keep track of the maximum maxfd = sockfd_monitor; } if (flag_debug) printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr)); } } //receive from the monitor if (sockfd_monitor!=-1 && FD_ISSET(sockfd_monitor, &read_fds_copy)) { logWrite(MAIN_LOOP, NULL, "Receive control message from monitor"); if (receive_monitor(sockfd_monitor, &packet_deadline) == 0) { //socket_monitor closed by peer FD_CLR(sockfd_monitor, &read_fds); //stop checking the monitor socket // FD_CLR(sockfd_monitor, &write_fds); sockfd_monitor = -1; FD_SET(sockfd_rcv_monitor, &read_fds); //start checking the receiver control socket if (sockfd_rcv_monitor > maxfd) { // keep track of the maximum maxfd = sockfd_rcv_monitor; } } } //sniff packets if (FD_ISSET(pcapfd, &read_fds_copy)) { logWrite(MAIN_LOOP, NULL, "Sniff packet stream"); sniff(); } } //while in quanta //send measurements to the monitor once in each quanta if (sockfd_monitor!=-1) // && FD_ISSET(sockfd_monitor, &write_fds_copy)) { { logWrite(MAIN_LOOP, NULL, "Send control message to monitor"); if (send_monitor(sockfd_monitor) == 0) { //socket_monitor closed by peer logWrite(MAIN_LOOP, NULL, "Message to monitor failed"); FD_CLR(sockfd_monitor, &read_fds); //stop checking the monitor socket // FD_CLR(sockfd_monitor, &write_fds); sockfd_monitor = -1; FD_SET(sockfd_rcv_monitor, &read_fds); //start checking the receiver control socket if (sockfd_rcv_monitor > maxfd) { // keep track of the maximum maxfd = sockfd_rcv_monitor; } } else { logWrite(MAIN_LOOP, NULL, "Message to monitor succeeded"); // flag_send_monitor=1; } } // In testmode, we only start printing in the quanta we first see a packet if (flag_standalone) { print_measurements(); } // If running in testmode, and the test is over, exit! if (flag_testmode && test_state == TEST_DONE) { printf("Test done - total bytes transmitted: %llu\n",total_bytes); break; } } //while forever packet_buffer_cleanup(); return 0; }