Example #1
0
void *packet_consumer_thread(void *data) {

  if (bind_core >= 0)
    bind2core(bind_core);

  while(!do_shutdown) {

    if(pfring_zc_recv_pkt(inzq, &tmpbuff, wait_for_packet) > 0) {

      if (unlikely(verbose)) {
        char bigbuf[4096];
        pfring_print_pkt(bigbuf, sizeof(bigbuf), tmpbuff->data, tmpbuff->len, tmpbuff->len);
        fputs(bigbuf, stdout);
      }
#if 0
      int i;
      for(i = 0; i < tmpbuff->len; i++)
        printf("%02X ", tmpbuff->data[i]);
      printf("\n");
#endif

      numPkts++;
      numBytes += tmpbuff->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */

      while (unlikely(pfring_zc_send_pkt(outzq, &tmpbuff, flush_packet) < 0 && !do_shutdown))
        usleep(1);
    }

  }

  if (!flush_packet) pfring_zc_sync_queue(outzq, tx_only);
  pfring_zc_sync_queue(inzq, rx_only);

  return NULL;
}
Example #2
0
void* consumer_thread(void* _id) {
  long id = (long) _id;

  pfring_zc_pkt_buff *b = buffers[id];

  bind2core(bind_core[id]);

  while(!consumers_stats[id].do_shutdown) {

    if(pfring_zc_recv_pkt(outzq[id], &b, wait_for_packet) > 0) {

#if 0
      int i;

      for(i = 0; i < b->len; i++)
        printf("%02X ", pfring_zc_pkt_buff_data(b, outzq[id])[i]);
      printf("\n");
#endif

      consumers_stats[id].numPkts++;
      consumers_stats[id].numBytes += b->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */
    }

  }

  pfring_zc_sync_queue(outzq[id], rx_only);

  return NULL;
}
Example #3
0
void *time_pulse_thread(void *data) {
  struct volatile_globals *g = globals;
  u_int64_t ns;
  struct timespec tn;
#if 1
  u_int64_t pulse_clone = 0;
#endif

  bind2core(bind_time_pulse_core);

  while (likely(!g->do_shutdown)) {
    /* clock_gettime takes up to 30 nsec to get the time */
    clock_gettime(CLOCK_REALTIME, &tn);

    ns = ((u_int64_t) ((u_int64_t) tn.tv_sec * 1000000000) + (tn.tv_nsec));

#if 1 /* reduce cache thrashing*/ 
    if(ns >= pulse_clone + g->pulse_timestamp_precision_nsec /* (avoid updating each cycle) */ ) {
#endif
      *g->pulse_timestamp_ns = ((u_int64_t) ((u_int64_t) tn.tv_sec << 32) | tn.tv_nsec);
#if 1
      pulse_clone = ns;
    }
#endif
  }

  return NULL;
}
Example #4
0
void *pipeline_stage_thread(void* _id) {
  long id = (long) _id;

  pfring_zc_pkt_buff *b = buffers[id];

  bind2core(bind_core[id]);

  while(!do_shutdown) {

    if(pfring_zc_recv_pkt(zq[id], &b, wait_for_packet) > 0) {

#ifdef METADATA_TEST
      if (id == 0) { /* first pipeline stage */
        static u_int64_t counter = 0;
	u_int64_t *meta_p = (u_int64_t *) b->user;
	*meta_p = counter; 
	counter++;
      }
#endif

      if (id < num_threads-1) { /* send to the next pipeline stage */
        pfring_zc_send_pkt(zq[id+1], &b, flush_packet);
      } else {/* last pipeline stage */

#ifdef METADATA_TEST
	u_int64_t *meta_p = (u_int64_t *) b->user;
	if (*meta_p != numPkts)
	  printf("Buffer Metadata contains unexpected value: %llu != %llu\n", 
	    (long long unsigned) *meta_p, (long long unsigned) numPkts);
#endif

#if 0
        int i;

        for(i = 0; i < b->len; i++)
          printf("%02X ", b->data[i]);
        printf("\n");
#endif

        numPkts++;
        numBytes += b->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */
      }
    }

  }

  if (id < num_threads-1) pfring_zc_sync_queue(zq[id+1], tx_only);
  pfring_zc_sync_queue(zq[id], rx_only);

  return NULL;
}
Example #5
0
void *packet_consumer_thread(void *_id) {
  struct volatile_globals *g = globals;
  pfring_zc_queue *_inzq = inzq;
  pfring_zc_queue **_outzq = outzq;
  pfring_zc_multi_queue *_mq = mq;
  pfring_zc_pkt_buff **_ph = ph;
  u_int32_t _num_slaves = num_slaves;
  int i, ns, flush_tx = 0, toprocess = 0;
#ifdef USE_RECV_BURST
  int nr;
#endif

  bind2core(bind_core);

  while(!g->do_shutdown) {

#ifdef USE_RECV_BURST
    if ((nr = pfring_zc_recv_pkt_burst(_inzq, _ph, SWAP_BUFFERS, 0 /* g->wait_for_packet */)) > 0)
#else
    if (pfring_zc_recv_pkt(_inzq, _ph, 0 /* g->wait_for_packet */) > 0)
#endif
    {

#ifdef USE_RECV_BURST
      toprocess = 0;
      while (toprocess < nr) {
#endif
        pfring_zc_pkt_buff **buff_p = &_ph[toprocess];
        pfring_zc_pkt_buff *buff = *buff_p;

        if (g->time_pulse) {
          u_int64_t pulse_timestamp_ns = *g->pulse_timestamp_ns;
          buff->ts.tv_sec = pulse_timestamp_ns >> 32;
          buff->ts.tv_nsec = pulse_timestamp_ns & 0xffffffff;
        }

        g->numPkts++;
        g->numBytes += buff->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */

        ns = pfring_zc_send_pkt_multi(_mq, buff_p, 0xffffffff, 0);

	//drop += _num_slaves - ns;
        g->sentPkts += ns;

#ifdef USE_RECV_BURST
        toprocess++;
      }
#endif
      flush_tx = 1;

    } else {
Example #6
0
void *time_pulse_thread(void *data) {
  struct timespec tn;

  bind2core(bind_time_pulse_core);

  while (likely(!do_shutdown)) {
    /* clock_gettime takes up to 30 nsec to get the time */
    clock_gettime(CLOCK_REALTIME, &tn);
    if (append_timestamp) *pulse_timestamp_ns_n = ((u_int64_t) ((u_int64_t) htonl(tn.tv_sec) << 32) | htonl(tn.tv_nsec));
    if (use_pulse_time)   *pulse_timestamp_ns   = ((u_int64_t) ((u_int64_t) tn.tv_sec * 1000000000) + tn.tv_nsec);
  }

  return NULL;
}
Example #7
0
void *packet_consumer_thread(void *_i) {
  struct dir_info *i = (struct dir_info *) _i;
  int tx_queue_not_empty = 0;

  if (i->bind_core >= 0)
    bind2core(i->bind_core);

  while(!do_shutdown) {

    if(pfring_zc_recv_pkt(i->inzq, &i->tmpbuff, 0 /* wait_for_packet */) > 0) {

      if (unlikely(verbose)) {
#if 1
        char bigbuf[4096];
        pfring_print_pkt(bigbuf, sizeof(bigbuf), pfring_zc_pkt_buff_data(i->tmpbuff, i->inzq), i->tmpbuff->len, i->tmpbuff->len);
        fputs(bigbuf, stdout);
#else
	u_char *pkt_data = pfring_zc_pkt_buff_data(i->tmpbuff, i->inzq);
        int j;
        for(j = 0; j < i->tmpbuff->len; j++)
          printf("%02X ", pkt_data[j]);
        printf("\n");
#endif
      }

      i->numPkts++;
      i->numBytes += i->tmpbuff->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */
      
      errno = 0;
      while (unlikely(pfring_zc_send_pkt(i->outzq, &i->tmpbuff, flush_packet) < 0 && errno != EMSGSIZE && !do_shutdown))
        if (wait_for_packet) usleep(1);

      tx_queue_not_empty = 1;
    } else {
      if (tx_queue_not_empty) {
        pfring_zc_sync_queue(i->outzq, tx_only);
        tx_queue_not_empty = 0;
      }
      if (wait_for_packet) 
        usleep(1);
    }

  }

  if (!flush_packet) pfring_zc_sync_queue(i->outzq, tx_only);
  pfring_zc_sync_queue(i->inzq, rx_only);

  return NULL;
}
Example #8
0
void *forwarder_thread(void *_info) {
  forwarder_info_t *info = (forwarder_info_t *) _info;
  pfring_zc_pkt_buff *b = info->buffer;

  bind2core(info->bind_core);

  while(!do_shutdown)
    if(pfring_zc_recv_pkt(info->inzq, &b, wait_for_packet) > 0)
      while (unlikely(pfring_zc_send_pkt(info->outzq, &b, flush_packet) < 0 && !do_shutdown)) usleep(1);

  pfring_zc_sync_queue(info->outzq, tx_only);
  pfring_zc_sync_queue(info->inzq,  rx_only);

  return NULL;
}
Example #9
0
void *packet_consumer_thread(void *_id) {
  struct volatile_globals *g = globals;

  bind2core(bind_core);

  while(!g->do_shutdown) {

    if(pfring_zc_recv_pkt(zq, &buffer, g->wait_for_packet) > 0) {

      if (unlikely(g->verbose)) {
        u_char *pkt_data = pfring_zc_pkt_buff_data(buffer, zq);

        if (buffer->ts.tv_nsec)
          printf("[%u.%u] ", buffer->ts.tv_sec, buffer->ts.tv_nsec);

	if(g->dump_as_sysdig_event) {
	  struct sysdig_event_header *ev = (struct sysdig_event_header*)pkt_data;

	  printf("[cpu_id=%u][tid=%lu][%u|%s]",
		 buffer->hash, ev->thread_id,
		 ev->event_type, sysdig_event2name(ev->event_type));		 
	} else {
	  int i;

	  for(i = 0; i < buffer->len; i++)
	    printf("%02X ", pkt_data[i]);
	}

        printf("\n");
      }

      g->numPkts++;
      g->numBytes += buffer->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */
    }
  }

   pfring_zc_sync_queue(zq, rx_only);

  return NULL;
}
Example #10
0
void send_traffic() {
  ticks hz, tick_start = 0, tick_delta = 0;
  u_int32_t buffer_id = 0;
  int sent_bytes;
#ifdef BURST_API
  int i, sent_packets;
#endif

  if (bind_core >= 0)
    bind2core(bind_core);

  if(pps > 0) {
    /* cumputing usleep delay */
    tick_start = getticks();
    usleep(1);
    tick_delta = getticks() - tick_start;

    /* cumputing CPU freq */
    tick_start = getticks();
    usleep(1001);
    hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz*/;
    printf("Estimated CPU freq: %lu Hz\n", (long unsigned int) hz);

    tick_delta = (double) (hz / pps);
    tick_start = getticks();
  }

#ifdef BURST_API  
  /****** Burst API ******/
  if (use_pkt_burst_api) {
  while (likely(!do_shutdown && (!num_to_send || numPkts < num_to_send))) {

    if (numPkts < num_queue_buffers + NBUFF || num_ips > 1) { /* forge all buffers 1 time */
      for (i = 0; i < BURSTLEN; i++) {
        buffers[buffer_id + i]->len = packet_len;
        if (stdin_packet_len > 0)
          memcpy(buffers[buffer_id + i]->data, stdin_packet, stdin_packet_len);
        else
          forge_udp_packet(buffers[buffer_id + i]->data, numPkts + i);
      }
    }

    /* TODO send unsent packets when a burst is partially sent */
    while (unlikely((sent_packets = pfring_zc_send_pkt_burst(zq, &buffers[buffer_id], BURSTLEN, flush_packet)) <= 0)) {
      if (unlikely(do_shutdown)) break;
      if (!active) usleep(1);
    }

    numPkts += sent_packets;
    numBytes += ((packet_len + 24 /* 8 Preamble + 4 CRC + 12 IFG */ ) * sent_packets);

    buffer_id += BURSTLEN;
    buffer_id &= NBUFFMASK;

    if(pps > 0) {
      u_int8_t synced = 0;
      while((getticks() - tick_start) < (numPkts * tick_delta))
        if (!synced) pfring_zc_sync_queue(zq, tx_only), synced = 1;
    }

  } 

  } else {
#endif

  /****** Packet API ******/
  while (likely(!do_shutdown && (!num_to_send || numPkts < num_to_send))) {

    buffers[buffer_id]->len = packet_len;

#if 1
    if (numPkts < num_queue_buffers + NBUFF || num_ips > 1) { /* forge all buffers 1 time */
      if (stdin_packet_len > 0)
        memcpy(buffers[buffer_id]->data, stdin_packet, stdin_packet_len);
      else
        forge_udp_packet(buffers[buffer_id]->data, numPkts);
    }
#else
    {
      int k;
      u_int8_t j = numPkts;
      for(k = 0; k < buffers[buffer_id]->len; k++)
        buffers[buffer_id]->data[k] = j++;
      buffers[buffer_id]->data[k-1] = cluster_id;
    }
#endif

    while (unlikely((sent_bytes = pfring_zc_send_pkt(zq, &buffers[buffer_id], flush_packet)) < 0)) {
      if (unlikely(do_shutdown)) break;
      if (!active) usleep(1);
    }

    numPkts++;
    numBytes += sent_bytes + 24; /* 8 Preamble + 4 CRC + 12 IFG */

    buffer_id++;
    buffer_id &= NBUFFMASK;

    if(pps > 0) {
      u_int8_t synced = 0;
      while((getticks() - tick_start) < (numPkts * tick_delta))
        if (!synced) pfring_zc_sync_queue(zq, tx_only), synced = 1;
    }
  }

#ifdef BURST_API  
  }
#endif

  if (!flush_packet) 
    pfring_zc_sync_queue(zq, tx_only);
}
Example #11
0
int main(int argc, char* argv[]) {
  pfring *a_ring, *b_ring;
  char *a_dev = NULL, *b_dev = NULL, c;
  u_int8_t verbose = 0, use_pfring_send = 0;
  int a_ifindex, b_ifindex;
  int bind_core = -1;
  u_int16_t watermark = 1;

  while((c = getopt(argc,argv, "ha:b:c:fvpg:w:")) != -1) {
    switch(c) {
      case 'h':
	printHelp();
	return 0;
	break;
      case 'a':
	a_dev = strdup(optarg);
	break;
      case 'b':
	b_dev = strdup(optarg);
	break;
      case 'p':
	use_pfring_send = 1;
	break;
      case 'v':
	verbose = 1;
	break;
      case 'g':
        bind_core = atoi(optarg);
        break;
      case 'w':
        watermark = atoi(optarg);
        break;
    }
  }  

  if ((!a_dev) || (!b_dev)) {
    printf("You must specify two devices!\n");
    return -1;
  }

  if(strcmp(a_dev, b_dev) == 0) {
    printf("Bridge devices must be different!\n");
    return -1;
  }


  /* Device A */
  if((a_ring = pfring_open(a_dev, MAX_PKT_LEN, PF_RING_PROMISC | PF_RING_LONG_HEADER |
                           (use_pfring_send ? 0 : PF_RING_RX_PACKET_BOUNCE))
    ) == NULL) {
    printf("pfring_open error for %s [%s]\n", a_dev, strerror(errno));
    return(-1);
  }

  pfring_set_application_name(a_ring, "pfbridge-a");
  pfring_set_direction(a_ring, rx_only_direction);
  pfring_set_socket_mode(a_ring, recv_only_mode);
  pfring_set_poll_watermark(a_ring, watermark);
  pfring_get_bound_device_ifindex(a_ring, &a_ifindex);

  /* Device B */

  if((b_ring = pfring_open(b_dev, MAX_PKT_LEN, PF_RING_PROMISC|PF_RING_LONG_HEADER)) == NULL) {
    printf("pfring_open error for %s [%s]\n", b_dev, strerror(errno));
    pfring_close(a_ring);
    return(-1);
  }

  pfring_set_application_name(b_ring, "pfbridge-b");
  pfring_set_socket_mode(b_ring, send_only_mode);
  pfring_get_bound_device_ifindex(b_ring, &b_ifindex);
  
  /* Enable Sockets */

  if (pfring_enable_ring(a_ring) != 0) {
    printf("Unable enabling ring 'a' :-(\n");
    pfring_close(a_ring);
    pfring_close(b_ring);
    return(-1);
  }

  if(use_pfring_send) {
    if (pfring_enable_ring(b_ring)) {
      printf("Unable enabling ring 'b' :-(\n");
      pfring_close(a_ring);
      pfring_close(b_ring);
      return(-1);
    }
  } else {
    pfring_close(b_ring);
  }

  signal(SIGALRM, my_sigalarm);
  alarm(1);

  if(bind_core >= 0)
    bind2core(bind_core);

  while(1) {
    u_char *buffer;
    struct pfring_pkthdr hdr;
    
    if(pfring_recv(a_ring, &buffer, 0, &hdr, 1) > 0) {
      int rc;
      
      if(use_pfring_send) {

	rc = pfring_send(b_ring, (char *) buffer, hdr.caplen, 1);

	if(rc < 0)
	  printf("pfring_send(caplen=%u <= mtu=%u?) error %d\n", hdr.caplen, b_ring->mtu_len, rc);
	else if(verbose)
	  printf("Forwarded %d bytes packet\n", hdr.len);	
      } else {
	rc = pfring_send_last_rx_packet(a_ring, b_ifindex);
	
	if(rc < 0)
	  printf("pfring_send_last_rx_packet() error %d\n", rc);
	else if(verbose)
	  printf("Forwarded %d bytes packet\n", hdr.len);
      }

      if(rc >= 0) num_sent++;
	
    }
  }

  pfring_close(a_ring);
  if(use_pfring_send) pfring_close(b_ring);
  
  return(0);
}
Example #12
0
int main(int argc, char* argv[]) {
  char c, *pcap_in = NULL, mac_address[6];
  int promisc, i, verbose = 0, active_poll = 0, reforge_mac = 0;
  u_int mac_a, mac_b, mac_c, mac_d, mac_e, mac_f;
  char buffer[1500];
  int send_len = 60;
  u_int32_t num = 1;
  int bind_core = -1;
  u_int16_t cpu_percentage = 0;
  double gbit_s = 0, td, pps;
  ticks tick_start = 0, tick_delta = 0;
  ticks hz = 0;
  struct packet *tosend;

  while((c = getopt(argc,argv,"hi:n:g:l:af:r:vm:"
#if 0
		    "b:"
#endif
		    )) != -1) {
    switch(c) {
    case 'h':
      printHelp();
      break;
    case 'i':
      in_dev = strdup(optarg);
      break;
    case 'f':
      pcap_in = strdup(optarg);
      break;
    case 'n':
      num = atoi(optarg);
      break;
    case 'g':
      bind_core = atoi(optarg);
      break;
    case 'l':
      send_len = atoi(optarg);
      break;
    case 'v':
      verbose = 1;
      break;
    case 'a':
      active_poll = 1;
      break;
    case 'r':
      sscanf(optarg, "%lf", &gbit_s);
      break;
#if 0
    case 'b':
      cpu_percentage = atoi(optarg);
#endif
      break;

    case 'm':
      if(sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", &mac_a, &mac_b, &mac_c, &mac_d, &mac_e, &mac_f) != 6) {
	printf("Invalid MAC address format (XX:XX:XX:XX:XX:XX)\n");
	return(0);
      } else {
	reforge_mac = 1;
	mac_address[0] = mac_a, mac_address[1] = mac_b, mac_address[2] = mac_c;
	mac_address[3] = mac_d, mac_address[4] = mac_e, mac_address[5] = mac_f;
      }
      break;
    }
  }

  if(in_dev == NULL)  printHelp();

  printf("Sending packets on %s\n", in_dev);

  /* hardcode: promisc=1, to_ms=500 */
  promisc = 1;

  pd = pfring_open(in_dev, promisc, 1500, 0);
  if(pd == NULL) {
    printf("pfring_open %s error\n", in_dev);
    return(-1);
  } else {
    u_int32_t version;

    pfring_set_application_name(pd, "pfdnasend");
    pfring_version(pd, &version);

    printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16,
	   (version & 0x0000FF00) >> 8, version & 0x000000FF);
  }

  signal(SIGINT, sigproc);
  signal(SIGTERM, sigproc);
  signal(SIGINT, sigproc);

  if(send_len < 60)
    send_len = 60;

  if(gbit_s > 0) {
    /* cumputing usleep delay */
    tick_start = getticks();
    usleep(1);
    tick_delta = getticks() - tick_start;
    
    /* cumputing CPU freq */
    tick_start = getticks();
    usleep(1001);
    hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz*/;
    printf("Estimated CPU freq: %llu Hz\n", hz);

    /* computing max rate */
    pps = ((gbit_s * 1000000000) / 8 /*byte*/) / (8 /*Preamble*/ + send_len + 4 /*CRC*/ + 12 /*IFG*/);

    td = (double)(hz / pps);
    tick_delta = (ticks)td;

    printf("Number of %d-byte Packet Per Second at %.2f Gbit/s: %.2f\n", (send_len + 4 /*CRC*/), gbit_s, pps);
  }

  if(pcap_in) {
    char ebuf[256];
    u_char *pkt;
    struct pcap_pkthdr *h;
    pcap_t *pt = pcap_open_offline(pcap_in, ebuf);
    u_int num_pcap_pkts = 0;

    if(pt) {
      struct packet *last = NULL;

      while(1) {
	struct packet *p;
	int rc = pcap_next_ex(pt, &h, (const u_char**)&pkt);

	if(rc <= 0) break;

	p = (struct packet*)malloc(sizeof(struct packet));
	if(p) {
	  p->len = h->caplen;
	  p->next = NULL;
	  p->pkt = (char*)malloc(p->len);

	  if(p->pkt == NULL) {
	    printf("Not enough memory\n");
	    break;
	  } else {
	    memcpy(p->pkt, pkt, p->len);
	    if(reforge_mac) memcpy(p->pkt, mac_address, 6);
	  }

	  if(last) {
	    last->next = p;
	    last = p;
	  } else
	    pkt_head = p, last = p;
	} else {
	  printf("Not enough memory\n");
	  break;
	}

	if(verbose) 
	  printf("Read %d bytes packet from pcap file %s\n", 
		 p->len, pcap_in);
	num_pcap_pkts++;
      } /* while */

      pcap_close(pt);
      printf("Read %d packets from pcap file %s\n", 
	     num_pcap_pkts, pcap_in);
      last->next = pkt_head; /* Loop */
      num *= num_pcap_pkts;
    } else {
      printf("Unable to open file %s\n", pcap_in);
      pfring_close(pd);
      return(-1);
    }
  } else {
    struct packet *p;

    for(i=0; i<send_len; i++) buffer[i] = i;

    if(reforge_mac) memcpy(buffer, mac_address, 6);

    p = (struct packet*)malloc(sizeof(struct packet));
    if(p) {
      p->len = send_len;
      p->next = p; /* Loop */
      p->pkt = (char*)malloc(p->len);
      memcpy(p->pkt, buffer, send_len);
      pkt_head = p;
    }
  }

  if(bind_core >= 0)
    bind2core(bind_core);

  if(wait_for_packet && (cpu_percentage > 0)) {
    if(cpu_percentage > 99) cpu_percentage = 99;
    pfring_config(cpu_percentage);
  }

  if(!verbose) {
    signal(SIGALRM, my_sigalarm);
    alarm(1);
  }

  gettimeofday(&startTime, NULL);
  memcpy(&lastTime, &startTime, sizeof(startTime)); 

  if(gbit_s > 0)
    tick_start = getticks();

  tosend = pkt_head;
  i = 0;

  pfring_set_direction(pd, tx_only_direction);

  if(pfring_enable_ring(pd) != 0) {
    printf("Unable to enable ring :-(\n");
    pfring_close(pd);
    return(-1);
  }

  while(!num || i < num) {
    int rc;

  redo:
    rc = pfring_send(pd, tosend->pkt, tosend->len, 0 /* Don't flush (it does PF_RING automatically) */);

    if(verbose)
      printf("[%d] pfring_send(%d) returned %d\n", i, tosend->len, rc);

    if(rc == -1) {
      /* Not enough space in buffer */

      if(gbit_s == 0) {
	if(!active_poll) {
	  if(bind_core >= 0)
	    usleep(1);
	  else
	    pfring_poll(pd, 0);
	}
      } else {
	/* Just waste some time */
	while((getticks() - tick_start) < (num_pkt_good_sent * tick_delta)) ;
      }

      goto redo;
    } else
      num_pkt_good_sent++, num_bytes_good_sent += tosend->len+24 /* 8 Preamble + 4 CRC + 12 IFG */, tosend = tosend->next;

    if(num > 0) i++;
  } /* for */

  print_stats(0);
  pfring_close(pd);

  return(0);
}
Example #13
0
int main(int argc, char* argv[]) {
  char c, *pcap_in = NULL;
  int i, verbose = 0, active_poll = 0, disable_zero_copy = 0;
  int use_zero_copy_tx = 0;
  u_int mac_a, mac_b, mac_c, mac_d, mac_e, mac_f;
  char buffer[9000];
  u_int32_t num_to_send = 0;
  int bind_core = -1;
  u_int16_t cpu_percentage = 0;
  double gbit_s = 0, td, pps;
  ticks tick_start = 0, tick_delta = 0;
  ticks hz = 0;
  struct packet *tosend;
  u_int num_tx_slots = 0;
  int num_balanced_pkts = 1, watermark = 0;
  u_int num_pcap_pkts = 0;

  while((c = getopt(argc,argv,"b:hi:n:g:l:af:r:vm:w:zx:"
#if 0
		    "b:"
#endif
		    )) != -1) {
    switch(c) {
    case 'b':
      num_balanced_pkts = atoi(optarg);
      break;
    case 'h':
      printHelp();
      break;
    case 'i':
      in_dev = strdup(optarg);
      break;
    case 'f':
      pcap_in = strdup(optarg);
      break;
    case 'n':
      num_to_send = atoi(optarg);
      break;
    case 'g':
      bind_core = atoi(optarg);
      break;
    case 'l':
      send_len = atoi(optarg);
      break;
    case 'x':
      if_index = atoi(optarg);
      break;
    case 'v':
      verbose = 1;
      break;
    case 'a':
      active_poll = 1;
      break;
    case 'r':
      sscanf(optarg, "%lf", &gbit_s);
      break;
#if 0
    case 'b':
      cpu_percentage = atoi(optarg);
#endif
      break;

    case 'm':
      if(sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", &mac_a, &mac_b, &mac_c, &mac_d, &mac_e, &mac_f) != 6) {
	printf("Invalid MAC address format (XX:XX:XX:XX:XX:XX)\n");
	return(0);
      } else {
	reforge_mac = 1;
	mac_address[0] = mac_a, mac_address[1] = mac_b, mac_address[2] = mac_c;
	mac_address[3] = mac_d, mac_address[4] = mac_e, mac_address[5] = mac_f;
      }
      break;
    case 'w':
      watermark = atoi(optarg);

      if(watermark < 1) watermark = 1;
      break;
    case 'z':
      disable_zero_copy = 1;
      break;
    }
  }

  if((in_dev == NULL) || (num_balanced_pkts < 1))
    printHelp();

  printf("Sending packets on %s\n", in_dev);

  pd = pfring_open(in_dev, 1500, 0 /* PF_RING_PROMISC */);
  if(pd == NULL) {
    printf("pfring_open %s error [%s]\n", in_dev, strerror(errno));
    return(-1);
  } else {
    u_int32_t version;

    pfring_set_application_name(pd, "pfdnasend");
    pfring_version(pd, &version);

    printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16,
	   (version & 0x0000FF00) >> 8, version & 0x000000FF);
  }

  if (!pd->send && pd->send_ifindex && if_index == -1) {
    printf("Please use -x <if index>\n");
    return -1;
  }

  if(watermark > 0) {
    int rc;

    if((rc = pfring_set_tx_watermark(pd, watermark)) < 0)
      printf("pfring_set_tx_watermark() failed [rc=%d]\n", rc);
  }

  signal(SIGINT, sigproc);
  signal(SIGTERM, sigproc);
  signal(SIGINT, sigproc);

  if(send_len < 60)
    send_len = 60;

  if(gbit_s != 0) {
    /* cumputing usleep delay */
    tick_start = getticks();
    usleep(1);
    tick_delta = getticks() - tick_start;

    /* cumputing CPU freq */
    tick_start = getticks();
    usleep(1001);
    hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz*/;
    printf("Estimated CPU freq: %lu Hz\n", (long unsigned int)hz);
  }

  if(pcap_in) {
    char ebuf[256];
    u_char *pkt;
    struct pcap_pkthdr *h;
    pcap_t *pt = pcap_open_offline(pcap_in, ebuf);
    struct timeval beginning = { 0, 0 };
    int avg_send_len = 0;

    if(pt) {
      struct packet *last = NULL;

      while(1) {
	struct packet *p;
	int rc = pcap_next_ex(pt, &h, (const u_char**)&pkt);

	if(rc <= 0) break;

	if (num_pcap_pkts == 0) {
	  beginning.tv_sec = h->ts.tv_sec;
	  beginning.tv_usec = h->ts.tv_usec;
	}

	p = (struct packet*)malloc(sizeof(struct packet));
	if(p) {
	  p->len = h->caplen;
	  p->ticks_from_beginning = (((h->ts.tv_sec - beginning.tv_sec) * 1000000) + (h->ts.tv_usec - beginning.tv_usec)) * hz / 1000000;
	  p->next = NULL;
	  p->pkt = (char*)malloc(p->len);

	  if(p->pkt == NULL) {
	    printf("Not enough memory\n");
	    break;
	  } else {
	    memcpy(p->pkt, pkt, p->len);
	    if(reforge_mac) memcpy(p->pkt, mac_address, 6);
	  }

	  if(last) {
	    last->next = p;
	    last = p;
	  } else
	    pkt_head = p, last = p;
	} else {
	  printf("Not enough memory\n");
	  break;
	}

	if(verbose)
	  printf("Read %d bytes packet from pcap file %s [%lu.%lu Secs =  %lu ticks@%luhz from beginning]\n",
		 p->len, pcap_in, h->ts.tv_sec - beginning.tv_sec, h->ts.tv_usec - beginning.tv_usec,
		 (long unsigned int)p->ticks_from_beginning,
		 (long unsigned int)hz);

	avg_send_len += p->len;
	num_pcap_pkts++;
      } /* while */
      avg_send_len /= num_pcap_pkts;

      pcap_close(pt);
      printf("Read %d packets from pcap file %s\n",
	     num_pcap_pkts, pcap_in);
      last->next = pkt_head; /* Loop */
      send_len = avg_send_len;
    } else {
      printf("Unable to open file %s\n", pcap_in);
      pfring_close(pd);
      return(-1);
    }
  } else {
    struct packet *p = NULL, *last = NULL;

    for (i = 0; i < num_balanced_pkts; i++) {

      forge_udp_packet(buffer, i);

      p = (struct packet *) malloc(sizeof(struct packet));
      if(p) {
	if (i == 0) pkt_head = p;

        p->len = send_len;
        p->ticks_from_beginning = 0;
        p->next = pkt_head;
        p->pkt = (char*)malloc(p->len);

	if (p->pkt == NULL) {
	  printf("Not enough memory\n");
	  break;
	}

        memcpy(p->pkt, buffer, send_len);

	if (last != NULL) last->next = p;
	last = p;
      }
    }
  }

  if(gbit_s > 0) {
    /* computing max rate */
    pps = ((gbit_s * 1000000000) / 8 /*byte*/) / (8 /*Preamble*/ + send_len + 4 /*CRC*/ + 12 /*IFG*/);

    td = (double)(hz / pps);
    tick_delta = (ticks)td;

    printf("Number of %d-byte Packet Per Second at %.2f Gbit/s: %.2f\n", (send_len + 4 /*CRC*/), gbit_s, pps);
  }

  if(bind_core >= 0)
    bind2core(bind_core);

  if(wait_for_packet && (cpu_percentage > 0)) {
    if(cpu_percentage > 99) cpu_percentage = 99;
    pfring_config(cpu_percentage);
  }

  if(!verbose) {
    signal(SIGALRM, my_sigalarm);
    alarm(1);
  }

  gettimeofday(&startTime, NULL);
  memcpy(&lastTime, &startTime, sizeof(startTime));

  pfring_set_socket_mode(pd, send_only_mode);

  if(pfring_enable_ring(pd) != 0) {
    printf("Unable to enable ring :-(\n");
    pfring_close(pd);
    return(-1);
  }

  use_zero_copy_tx = 0;

  if((!disable_zero_copy)
     && (pd->dna_get_num_tx_slots != NULL)
     && (pd->dna_get_next_free_tx_slot != NULL)
     && (pd->dna_copy_tx_packet_into_slot != NULL)) {
    tosend = pkt_head;

    num_tx_slots = pd->dna_get_num_tx_slots(pd);

    if(num_tx_slots > 0
       && (((num_to_send > 0) && (num_to_send <= num_tx_slots))
        || ( pcap_in && (num_pcap_pkts     <= num_tx_slots) && (num_tx_slots % num_pcap_pkts     == 0))
        || (!pcap_in && (num_balanced_pkts <= num_tx_slots) && (num_tx_slots % num_balanced_pkts == 0)))) {
      int ret;
      u_int first_free_slot = pd->dna_get_next_free_tx_slot(pd);

      for(i=0; i<num_tx_slots; i++) {
	ret = pfring_copy_tx_packet_into_slot(pd, (first_free_slot+i)%num_tx_slots, tosend->pkt, tosend->len);
	if(ret < 0)
	  break;

	tosend = tosend->next;
      }

      use_zero_copy_tx = 1;
      printf("Using zero-copy TX\n");
    } else {
      printf("NOT using zero-copy: TX ring size (%u) is not a multiple of the number of unique packets to send (%u)\n", num_tx_slots, pcap_in ? num_pcap_pkts : num_balanced_pkts);
    }
  } else {
    if (!disable_zero_copy)
      printf("NOT using zero-copy: not supported by the driver\n");
  }

  tosend = pkt_head;
  i = 0;

  if(gbit_s != 0)
    tick_start = getticks();

  while((num_to_send == 0) 
	|| (i < num_to_send)) {
    int rc;

  redo:

    if (if_index != -1)
      rc = pfring_send_ifindex(pd, tosend->pkt, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */, if_index);
    else if(use_zero_copy_tx)
      /* We pre-filled the TX slots */
      rc = pfring_send(pd, NULL, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */);
    else
      rc = pfring_send(pd, tosend->pkt, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */);

    if(verbose)
      printf("[%d] pfring_send(%d) returned %d\n", i, tosend->len, rc);

    if(rc == PF_RING_ERROR_INVALID_ARGUMENT) {
      printf("Attempting to send invalid packet [len: %u][MTU: %u]%s\n",
	     tosend->len, pd->mtu_len,
      	     if_index != -1 ? " or using a wrong interface id" : "");
    } else if(rc < 0) {
      /* Not enough space in buffer */
      if(!active_poll) {
#if 1
	usleep(1);
#else
        if(bind_core >= 0)
	  usleep(1);
	else
	  pfring_poll(pd, 0); //sched_yield();
#endif
      }
      goto redo;
    }

    num_pkt_good_sent++;
    num_bytes_good_sent += tosend->len + 24 /* 8 Preamble + 4 CRC + 12 IFG */;

    tosend = tosend->next;

    if (use_zero_copy_tx
	&& (num_pkt_good_sent == num_tx_slots))
      tosend = pkt_head;

    if(gbit_s > 0) {
      /* rate set */
      while((getticks() - tick_start) < (num_pkt_good_sent * tick_delta)) ;
    } else if (gbit_s < 0) {
      /* real pcap rate */
      if (tosend->ticks_from_beginning == 0)
        tick_start = getticks(); /* first packet, resetting time */
      while((getticks() - tick_start) < tosend->ticks_from_beginning) ;
    }

    if(num_to_send > 0) i++;
  } /* for */

  print_stats(0);
  pfring_close(pd);

  return(0);
}