Exemplo n.º 1
0
int main(int argc, char* argv[]) {
  char *device = NULL, c;
  pthread_t thread;
  pthread_t time_thread;
  char *vm_sock = NULL;
  int i, rc, ipc_q_attach = 0;

  startTime.tv_sec = 0;

  while((c = getopt(argc,argv,"ab:c:g:hi:n:p:l:zN:S:P:Q:")) != '?') {
    if((c == 255) || (c == -1)) break;

    switch(c) {
    case 'h':
      printHelp();
      break;
    case 'a':
      active = 1;
      break;
    case 'b':
      num_ips = atoi(optarg);
      break;
    case 'c':
      cluster_id = atoi(optarg);
      break;
    case 'i':
      device = strdup(optarg);
      break;
    case 'l':
      packet_len = atoi(optarg);
      break;
    case 'n':
      num_to_send = atoi(optarg);
      break;
    case 'p':
      pps = atoi(optarg);
      /* auto flush on wait flush_packet = 1; */
      break;
    case 'g':
      bind_core = atoi(optarg);
      break;
    case 'Q':
      enable_vm_support = 1;
      vm_sock = strdup(optarg);
      break;
#ifdef BURST_API
    case 'z':
      use_pkt_burst_api = 1;
      break;
#endif
    case 'N':
      n2disk_producer = 1;
      n2disk_threads = atoi(optarg);
      break;
    case 'S':
      append_timestamp = 1;
      bind_time_pulse_core = atoi(optarg);
      break;
    case 'P':
      use_pulse_time = 1;
      bind_time_pulse_core = atoi(optarg);
      break;
    }
  }

  if (n2disk_producer) 
    device = NULL;

  /* checking if the interface is a queue allocated by an external cluster (ipc) */
  if (device != NULL && is_a_queue(device, &cluster_id, &queue_id)) 
    ipc_q_attach = 1;

  if (cluster_id < 0) printHelp();

  stdin_packet_len = read_packet_hex(stdin_packet, sizeof(stdin_packet));

  if (stdin_packet_len > 0)
    packet_len = stdin_packet_len;

  if (n2disk_producer) {
    if (device != NULL || ipc_q_attach) printHelp();
    if (n2disk_threads < 1) printHelp();
    metadata_len = N2DISK_METADATA;
    num_consumer_buffers += (n2disk_threads * (N2DISK_CONSUMER_QUEUE_LEN + 1)) + N2DISK_PREFETCH_BUFFERS;
  }
 
  if (!ipc_q_attach) {

    if (device != NULL)
      num_queue_buffers = MAX_CARD_SLOTS;
    else
      num_queue_buffers = QUEUE_LEN;

    zc = pfring_zc_create_cluster(
      cluster_id, 
      max_packet_len(device),
      metadata_len, 
      num_queue_buffers + NBUFF + num_consumer_buffers, 
      numa_node_of_cpu(bind_core),
      NULL /* auto hugetlb mountpoint */ 
    );

    if(zc == NULL) {
      fprintf(stderr, "pfring_zc_create_cluster error [%s] Please check your hugetlb configuration\n",
  	      strerror(errno));
      return -1;
    }

    for (i = 0; i < NBUFF; i++) {
      buffers[i] = pfring_zc_get_packet_handle(zc);

      if (buffers[i] == NULL) {
        fprintf(stderr, "pfring_zc_get_packet_handle error\n");
        return -1;
      }
    }

    if (device) {
      zq = pfring_zc_open_device(zc, device, tx_only, 0);
  
      if(zq == NULL) {
        fprintf(stderr, "pfring_zc_open_device error [%s] Please check that %s is up and not already used\n",
	        strerror(errno), device);
        return -1;
      }

      fprintf(stderr, "Sending packets to %s\n", device);
    } else {
      zq = pfring_zc_create_queue(zc, num_queue_buffers);

      if(zq == NULL) {
        fprintf(stderr, "pfring_zc_create_queue error [%s]\n", strerror(errno));
        return -1;
      }

      if (pfring_zc_create_buffer_pool(zc, n2disk_producer ? (N2DISK_PREFETCH_BUFFERS + n2disk_threads) : 1) == NULL) {
        fprintf(stderr, "pfring_zc_create_buffer_pool error\n");
        return -1;
      }
   
      fprintf(stderr, "Sending packets to cluster %u queue %u\n", cluster_id, 0);

      if (n2disk_producer) {
        char queues_list[256];
        queues_list[0] = '\0';

        for (i = 0; i < n2disk_threads; i++) {
          if(pfring_zc_create_queue(zc, N2DISK_CONSUMER_QUEUE_LEN) == NULL) {
            fprintf(stderr, "pfring_zc_create_queue error [%s]\n", strerror(errno));
            return -1;
          }
          sprintf(&queues_list[strlen(queues_list)], "%d,", i+1);
        }
        queues_list[strlen(queues_list)-1] = '\0';

        fprintf(stderr, "Run n2disk with: --cluster-ipc-attach --cluster-id %d --cluster-ipc-queues %s --cluster-ipc-pool 0\n", cluster_id, queues_list);
      }

    }

    if (enable_vm_support) {
      rc = pfring_zc_vm_register(zc, vm_sock);

      if (rc < 0) {
        fprintf(stderr, "pfring_zc_vm_register(%s) error\n", vm_sock);
        return -1;
      }

      rc = pfring_zc_vm_backend_enable(zc);

      if (rc < 0) {
        fprintf(stderr, "pfring_zc_vm_backend_enable error\n");
        return -1;
      }
    }

  } else { /* IPC */

    fprintf(stderr, "Attaching to cluster %d queue %d (IPC)\n", cluster_id, queue_id);

    zq = pfring_zc_ipc_attach_queue(cluster_id, queue_id, tx_only);

    if(zq == NULL) {
      fprintf(stderr, "pfring_zc_ipc_attach_queue error [%s] Please check that cluster %d is running\n",
  	      strerror(errno), cluster_id);
      return -1;
    }

    zp = pfring_zc_ipc_attach_buffer_pool(cluster_id, queue_id);

    if(zp == NULL) {
      fprintf(stderr, "pfring_zc_ipc_attach_buffer_pool error [%s] Please check that cluster %d is running\n",
  	      strerror(errno), cluster_id);
      return -1;
    }

    for (i = 0; i < NBUFF; i++) {
      buffers[i] = pfring_zc_get_packet_handle_from_pool(zp);

      if (buffers[i] == NULL) {
        fprintf(stderr, "pfring_zc_get_packet_handle_from_pool error\n");
        return -1;
      }
    } 
  }

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

  if (use_pulse_time)   pulse_timestamp_ns   = calloc(CACHE_LINE_LEN/sizeof(u_int64_t), sizeof(u_int64_t));
  if (append_timestamp) pulse_timestamp_ns_n = calloc(CACHE_LINE_LEN/sizeof(u_int64_t), sizeof(u_int64_t));
  if (append_timestamp || use_pulse_time) pthread_create(&time_thread, NULL, time_pulse_thread, NULL);
  if (use_pulse_time)   while (!*pulse_timestamp_ns   && !do_shutdown); /* wait for ts */
  if (append_timestamp) while (!*pulse_timestamp_ns_n && !do_shutdown); /* wait for ts */

  pthread_create(&thread, NULL, send_traffic, NULL);

  while (!do_shutdown) {
    sleep(ALARM_SLEEP);
    print_stats();
  }

  pthread_join(thread, NULL);

  print_stats();

  if (append_timestamp || use_pulse_time)
    pthread_join(time_thread, NULL);

  if (!ipc_q_attach) {
    pfring_zc_destroy_cluster(zc);
  } else {
    for (i = 0; i < NBUFF; i++)
      pfring_zc_release_packet_handle_to_pool(zp, buffers[i]);
    pfring_zc_ipc_detach_queue(zq);
    pfring_zc_ipc_detach_buffer_pool(zp);  
  }

  return 0;
}
Exemplo n.º 2
0
static int pfring_zc_daq_initialize(const DAQ_Config_t *config,
                                    void **ctxt_ptr, char *errbuf, size_t len) {
    Pfring_Context_t *context;
    DAQ_Dict* entry;
    u_int numCPU = get_nprocs();
    int i, max_buffer_len = 0, card_buffers;
    int num_buffers;
    int ipc_cluster_id;

    context = calloc(1, sizeof(Pfring_Context_t));

    if (context == NULL) {
        snprintf(errbuf, len, "%s: Couldn't allocate memory for context!", __FUNCTION__);
        return DAQ_ERROR_NOMEM;
    }

    context->mode = config->mode;
    context->snaplen = config->snaplen;
    context->promisc_flag =(config->flags & DAQ_CFG_PROMISC);
    context->timeout = (config->timeout > 0) ? (int) config->timeout : -1;
    context->devices[DAQ_PF_RING_PASSIVE_DEV_IDX] = strdup(config->name);
    context->num_devices = 1;
    context->ids_bridge = 0;
    context->cluster_id = -1;
    context->max_buffer_len = 0;
    context->bindcpu = 0;
    context->ipc_attach = 0;

    if (!context->devices[DAQ_PF_RING_PASSIVE_DEV_IDX]) {
        snprintf(errbuf, len, "%s: Couldn't allocate memory for the device string!", __FUNCTION__);
        free(context);
        return DAQ_ERROR_NOMEM;
    }

    for (entry = config->values; entry; entry = entry->next) {
        if (!entry->value || !*entry->value) {
            snprintf(errbuf, len, "%s: variable needs value(%s)\n", __FUNCTION__, entry->key);
            return DAQ_ERROR;
        } else if (!strcmp(entry->key, "bindcpu")) {
            char *end = entry->value;
            context->bindcpu = (int) strtol(entry->value, &end, 0);
            if (*end
                    || (context->bindcpu >= numCPU)) {
                snprintf(errbuf, len, "%s: bad bindcpu(%s)\n", __FUNCTION__, entry->value);
                return DAQ_ERROR;
            } else {
                cpu_set_t mask;

                CPU_ZERO(&mask);
                CPU_SET((int)context->bindcpu, &mask);
                if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
                    snprintf(errbuf, len, "%s:failed to set bindcpu(%u) on pid %i\n", __FUNCTION__, context->bindcpu, getpid());
                    return DAQ_ERROR;
                }
            }
        } else if (!strcmp(entry->key, "timeout")) {
            char *end = entry->value;
            context->timeout = (int) strtol(entry->value, &end, 0);
            if (*end || (context->timeout < 0)) {
                snprintf(errbuf, len, "%s: bad timeout(%s)\n", __FUNCTION__, entry->value);
                return DAQ_ERROR;
            }
        } else if (!strcmp(entry->key, "idsbridge")) {
            if (context->mode == DAQ_MODE_PASSIVE) {
                char* end = entry->value;
                context->ids_bridge = (int) strtol(entry->value, &end, 0);
                if (*end || (context->ids_bridge < 0) || (context->ids_bridge > 2)) {
                    snprintf(errbuf, len, "%s: bad ids bridge mode(%s)\n", __FUNCTION__, entry->value);
                    return DAQ_ERROR;
                }
            } else {
                snprintf(errbuf, len, "%s: idsbridge is for passive mode only\n", __FUNCTION__);
                return DAQ_ERROR;
            }
        } else if (!strcmp(entry->key, "clusterid")) {
            char *end = entry->value;
            context->cluster_id = (int) strtol(entry->value, &end, 0);
            if (*end || (context->cluster_id < 0)) {
                snprintf(errbuf, len, "%s: bad clusterid(%s)\n", __FUNCTION__, entry->value);
                return DAQ_ERROR;
            }
        } else {
            snprintf(errbuf, len, "%s: unsupported variable(%s=%s)\n", __FUNCTION__, entry->key, entry->value);
            return DAQ_ERROR;
        }
    }

    if (context->mode == DAQ_MODE_READ_FILE) {
        snprintf(errbuf, len, "%s: function not supported on PF_RING", __FUNCTION__);
        free(context);
        return DAQ_ERROR;
    } else if (context->mode == DAQ_MODE_INLINE || (context->mode == DAQ_MODE_PASSIVE && context->ids_bridge)) {
        /* zc:ethX+zc:ethY,zc:ethZ+zc:ethJ */
        char *twins, *twins_pos = NULL;
        context->num_devices = 0;

        twins = strtok_r(context->devices[DAQ_PF_RING_PASSIVE_DEV_IDX], ",", &twins_pos);
        while (twins != NULL) {
            char *dev, *dev_pos = NULL, *tx_dev;
            int last_twin = 0;

            dev = strtok_r(twins, "+", &dev_pos);
            while (dev != NULL) {

                if (context->num_devices >= DAQ_PF_RING_MAX_NUM_DEVICES) {
                    snprintf(errbuf, len, "%s: Maximum num of devices reached (%d), you should increase "
                             "DAQ_PF_RING_MAX_NUM_DEVICES.\n", __FUNCTION__, DAQ_PF_RING_MAX_NUM_DEVICES);
                    free(context);
                    return DAQ_ERROR;
                }

                last_twin = context->num_devices;

                context->devices[context->num_devices] = dev;

                tx_dev = strchr(dev, '-');
                if (tx_dev != NULL) { /* use the specified device for tx */
                    tx_dev[0] = '\0';
                    tx_dev++;
                    context->tx_devices[context->num_devices] = tx_dev;
                } else {
                    context->tx_devices[context->num_devices] = dev;
                }

                context->num_devices++;

                dev = strtok_r(NULL, "+", &dev_pos);
            }

            if (context->num_devices & 0x1) {
                snprintf(errbuf, len, "%s: Wrong format: %s requires pairs of devices",
                         __FUNCTION__, context->mode == DAQ_MODE_INLINE ? "inline mode" : "ids bridge");
                free(context);
                return DAQ_ERROR;
            }

            if (last_twin > 0) /* new dev pair */
                printf("%s <-> %s\n", context->devices[last_twin - 1], context->devices[last_twin]);

            twins = strtok_r(NULL, ",", &twins_pos);
        }
    } else if (context->mode == DAQ_MODE_PASSIVE) {
        /* zc:ethX,zc:ethY */
        char *dev, *dev_pos = NULL;
        context->num_devices = 0;
        context->ipc_attach = 1; /* IPC queue attach supported in pure IDS only at the moment */

        dev = strtok_r(context->devices[DAQ_PF_RING_PASSIVE_DEV_IDX], ",", &dev_pos);
        while (dev != NULL) {

            /* checking for IPC Queue */
            if (!is_a_queue(dev, &ipc_cluster_id, &context->ipc_queues[context->num_devices])) {
                context->ipc_attach = 0;
            } else {
                if (context->cluster_id == -1)
                    context->cluster_id = ipc_cluster_id;
                else if (ipc_cluster_id != context->cluster_id)
                    context->ipc_attach = 0;
            }

            context->devices[context->num_devices++] = dev;
            dev = strtok_r(NULL, ",", &dev_pos);
        }
    }

#ifdef SIG_RELOAD
    /* catching the SIGRELOAD signal, replacing the default snort handler */
    if ((default_sig_reload_handler = signal(SIGHUP, pfring_zc_daq_sig_reload)) == SIG_ERR)
        default_sig_reload_handler = NULL;
#endif

    if (!context->ipc_attach) {

        num_buffers = 2 /* buffer, buffer_inject */;

#ifdef DAQ_PF_RING_BEST_EFFORT_BOOST
        if (context->mode == DAQ_MODE_PASSIVE && context->ids_bridge == 2)
            num_buffers += QUEUE_LEN;
#endif

        for (i = 0; i < context->num_devices; i++) {
            max_buffer_len = max_packet_len(context, context->devices[i], i, &card_buffers);
            if (max_buffer_len > context->max_buffer_len) context->max_buffer_len = max_buffer_len;
            if (strstr(context->devices[i], "zc:") != NULL) num_buffers += card_buffers;
            if (context->tx_devices[i] != NULL) {
                max_buffer_len = max_packet_len(context, context->tx_devices[i], i, &card_buffers);
                if (max_buffer_len > context->max_buffer_len) context->max_buffer_len = max_buffer_len;
                if (strstr(context->tx_devices[i], "zc:") != NULL) num_buffers += card_buffers;
            }
        }

        context->cluster = pfring_zc_create_cluster(context->cluster_id, context->max_buffer_len, 0, num_buffers,
                           context->bindcpu == 0 ? -1 : numa_node_of_cpu(context->bindcpu), NULL);

        if (context->cluster == NULL) {
            DPE(context->errbuf, "%s: Cluster failed: %s(%d)", __FUNCTION__, strerror(errno), errno);
            return DAQ_ERROR;
        }

        context->buffer = pfring_zc_get_packet_handle(context->cluster);

        if (context->buffer == NULL) {
            DPE(context->errbuf, "%s: Buffer allocation failed: %s(%d)", __FUNCTION__, strerror(errno), errno);
            return DAQ_ERROR;
        }

        context->buffer_inject = pfring_zc_get_packet_handle(context->cluster);

        if (context->buffer_inject == NULL) {
            DPE(context->errbuf, "%s: Buffer allocation failed: %s(%d)", __FUNCTION__, strerror(errno), errno);
            return DAQ_ERROR;
        }

    } else {

        context->ipc_pool = pfring_zc_ipc_attach_buffer_pool(context->cluster_id, context->ipc_queues[0]);

        if (context->ipc_pool == NULL) {
            snprintf(errbuf, len, "%s: pfring_zc_ipc_attach_buffer_pool error %s(%d), please check that cluster %d is running\n",
                     __FUNCTION__, strerror(errno), errno, context->cluster_id);
            return -1;
        }

        context->buffer = pfring_zc_get_packet_handle_from_pool(context->ipc_pool);

        if (context->buffer == NULL) {
            DPE(context->errbuf, "%s: Buffer allocation failed: %s(%d)", __FUNCTION__, strerror(errno), errno);
            return DAQ_ERROR;
        }

    }

    for (i = 0; i < context->num_devices; i++) {
        if (pfring_zc_daq_open(context, i) == -1)
            return DAQ_ERROR;
    }

    if (!context->ipc_attach) {
#ifdef DAQ_PF_RING_BEST_EFFORT_BOOST
        if (context->mode == DAQ_MODE_PASSIVE && context->ids_bridge == 2) {
            context->q = pfring_zc_create_queue(context->cluster, QUEUE_LEN);

            if (context->q == NULL) {
                snprintf(errbuf, len, "%s: Couldn't create queue: '%s'", __FUNCTION__, strerror(errno));
                return DAQ_ERROR_NOMEM;
            }

            context->mq_queues[context->num_devices] = context->q;
            context->mq = pfring_zc_create_multi_queue(context->mq_queues, context->num_devices + 1);
        }
#endif
    }

    context->state = DAQ_STATE_INITIALIZED;

    *ctxt_ptr = context;
    return DAQ_SUCCESS;
}