Exemple #1
0
/* Allocate and initialize a VI. */
static int init(const char* intf, int vi_i)
{
  struct vi* vi = &vis[vi_i];
  int i;
  unsigned vi_flags = EF_VI_FLAGS_DEFAULT;

  TRY(ef_driver_open(&vi->dh));
  /* check that RX merge is supported */
  if( cfg_rx_merge ) {
    unsigned long value;
    int ifindex = if_nametoindex(intf);
    TEST(ifindex > 0);
    int rc = ef_vi_capabilities_get(vi->dh, ifindex, EF_VI_CAP_RX_MERGE, &value);
    if( rc < 0 || ! value ) {
      fprintf(stderr, "WARNING: RX merge not supported on %s. Use '-c' "
              "option instead.\n", intf);
      exit(EXIT_FAILURE);
    }
    else {
      vi_flags |= EF_VI_RX_EVENT_MERGE;
    }
  }
  TRY(ef_pd_alloc_by_name(&vi->pd, vi->dh, intf, EF_PD_DEFAULT));
  TRY(ef_vi_alloc_from_pd(&vi->vi, vi->dh, &vi->pd, vi->dh, -1, RX_RING_SIZE,
                          TX_RING_SIZE, NULL, -1, vi_flags));


  /* Memory for pkt buffers has already been allocated.  Map it into
   * the VI. */
  TRY(ef_memreg_alloc(&vi->memreg, vi->dh, &vi->pd, vi->dh,
                      pbs.mem, pbs.mem_size));
  for( i = 0; i < pbs.num; ++i ) {
    struct pkt_buf* pkt_buf = pkt_buf_from_id(i);
    pkt_buf->rx_ef_addr[vi_i] =
      ef_memreg_dma_addr(&vi->memreg, i * PKT_BUF_SIZE) + RX_DMA_OFF
      + addr_offset_from_id(i);
    pkt_buf->tx_ef_addr[vi_i] =
      ef_memreg_dma_addr(&vi->memreg, i * PKT_BUF_SIZE) + RX_DMA_OFF +
      ef_vi_receive_prefix_len(&vi->vi) + addr_offset_from_id(i);
  }

  /* Our pkt buffer allocation function makes assumptions on queue sizes */
  assert(ef_vi_receive_capacity(&vi->vi) == RX_RING_SIZE - 1);
  assert(ef_vi_transmit_capacity(&vi->vi) == TX_RING_SIZE - 1);

  if( cfg_unidirectional && vi_i == 1 )
    return 0; /* only need filter and RX fill for ingress VI */

  while( ef_vi_receive_space(&vi->vi) > REFILL_BATCH_SIZE )
    vi_refill_rx_ring(vi_i);

  ef_filter_spec fs;
  ef_filter_spec_init(&fs, EF_FILTER_FLAG_NONE);
  TRY(ef_filter_spec_set_unicast_all(&fs));
  TRY(ef_vi_filter_add(&vi->vi, vi->dh, &fs, NULL));
  ef_filter_spec_init(&fs, EF_FILTER_FLAG_NONE);
  TRY(ef_filter_spec_set_multicast_all(&fs));
  TRY(ef_vi_filter_add(&vi->vi, vi->dh, &fs, NULL));
  return 0;
}
Exemple #2
0
static int install_filters(void)
{
  ef_filter_spec fs;
  ef_filter_spec_init(&fs, EF_FILTER_FLAG_NONE);
  TRY(ef_filter_spec_set_unicast_all(&fs));
  TRY(ef_vi_set_filter_add(&vi_set, dh, &fs, NULL));
  ef_filter_spec_init(&fs, cfg_loopback ?
                      EF_FILTER_FLAG_MCAST_LOOP_RECEIVE :
                      EF_FILTER_FLAG_NONE);
  TRY(ef_filter_spec_set_multicast_all(&fs));
  TRY(ef_vi_set_filter_add(&vi_set, dh, &fs, NULL));
  return 0;
}
static int sc_stream_add(struct sc_stream* s, void* vi_or_set,
                         ef_driver_handle dh, ef_filter_cookie *cookie_out)
{
  ef_filter_spec spec;

  ef_filter_spec_init(&spec, EF_FILTER_FLAG_NONE);

  switch( s->fields ) {
  case SC_SF_ALL:
    TRY(ef_filter_spec_set_unicast_all(&spec));
    TRY(ef_vi_set_filter_add(vi_or_set, dh, &spec, cookie_out));
    ef_filter_spec_init(&spec, EF_FILTER_FLAG_NONE);
    TRY(ef_filter_spec_set_multicast_all(&spec));
    TRY(ef_vi_set_filter_add(vi_or_set, dh, &spec, cookie_out));
    break;
  case SC_SF_SNIFF:
    TRY(ef_filter_spec_set_port_sniff(&spec, s->promiscuous));
    TRY(ef_vi_set_filter_add(vi_or_set, dh, &spec, cookie_out));
    break;
  case SC_SF_ETH_DHOST:
    TRY(ef_filter_spec_set_eth_local(&spec, EF_FILTER_VLAN_ID_ANY,
                                     s->eth_dhost));
    TRY(ef_vi_set_filter_add(vi_or_set, dh, &spec, cookie_out));
    break;
  case SC_SF_ETH_DHOST | SC_SF_ETH_VLAN_ID:
    TRY(ef_filter_spec_set_eth_local(&spec, s->eth_vlan_id, s->eth_dhost));
    TRY(ef_vi_set_filter_add(vi_or_set, dh, &spec, cookie_out));
    break;
  case SC_SF_ETH_TYPE | SC_SF_IP4_PROTOCOL | SC_SF_IP4_DEST_ADDR |
    SC_SF_IP4_DEST_PORT:
    TRY(ef_filter_spec_set_ip4_local(&spec, s->ip4_protocol,
                                     s->ip4_dest_addr, s->ip4_dest_port));
    TRY(ef_vi_set_filter_add(vi_or_set, dh, &spec, cookie_out));
    break;
  case SC_SF_ETH_TYPE | SC_SF_IP4_PROTOCOL | SC_SF_IP4_DEST_ADDR |
    SC_SF_IP4_DEST_PORT | SC_SF_IP4_SOURCE_ADDR | SC_SF_IP4_SOURCE_PORT:
    TRY(ef_filter_spec_set_ip4_full(&spec, s->ip4_protocol,
                                    s->ip4_dest_addr, s->ip4_dest_port,
                                    s->ip4_source_addr, s->ip4_source_port));
    TRY(ef_vi_set_filter_add(vi_or_set, dh, &spec, cookie_out));
    break;
  default:
    fprintf(stderr, "ERROR: sc_vi[_set]_add_stream_string: "
            "unsupported combination of fields (0x%x)\n", s->fields);
    return -EINVAL;
  }

  return 0;
}
Exemple #4
0
/* Allocate and initialize a VI. */
static int init(const char* intf, int vi_i)
{
  struct vi* vi = &vis[vi_i];
  int i;
  TRY(ef_driver_open(&vi->dh));
  TRY(ef_pd_alloc_by_name(&vi->pd, vi->dh, intf, EF_PD_DEFAULT));
  TRY(ef_vi_alloc_from_pd(&vi->vi, vi->dh, &vi->pd, vi->dh, -1, -1, -1, NULL,
                          -1, EF_VI_FLAGS_DEFAULT));

  /* Memory for pkt buffers has already been allocated.  Map it into
   * the VI. */
  TRY(ef_memreg_alloc(&vi->memreg, vi->dh, &vi->pd, vi->dh,
                      pbs.mem, pbs.mem_size));
  for( i = 0; i < pbs.num; ++i ) {
    struct pkt_buf* pkt_buf = pkt_buf_from_id(i);
    pkt_buf->rx_ef_addr[vi_i] =
      ef_memreg_dma_addr(&vi->memreg, i * PKT_BUF_SIZE) + RX_DMA_OFF;
    pkt_buf->tx_ef_addr[vi_i] =
      ef_memreg_dma_addr(&vi->memreg, i * PKT_BUF_SIZE) + RX_DMA_OFF +
      ef_vi_receive_prefix_len(&vi->vi);
    pkt_buf->rx_ptr[vi_i] = (char*) pkt_buf + RX_DMA_OFF +
      ef_vi_receive_prefix_len(&vi->vi);
  }

  /* Our pkt buffer allocation function makes assumptions on queue sizes */
  assert(ef_vi_receive_capacity(&vi->vi) == 511);
  assert(ef_vi_transmit_capacity(&vi->vi) == 511);

  while( ef_vi_receive_space(&vi->vi) > REFILL_BATCH_SIZE )
    vi_refill_rx_ring(vi_i);

  ef_filter_spec fs;
  ef_filter_spec_init(&fs, EF_FILTER_FLAG_NONE);
  TRY(ef_filter_spec_set_unicast_all(&fs));
  TRY(ef_vi_filter_add(&vi->vi, vi->dh, &fs, NULL));
  ef_filter_spec_init(&fs, EF_FILTER_FLAG_NONE);
  TRY(ef_filter_spec_set_multicast_all(&fs));
  TRY(ef_vi_filter_add(&vi->vi, vi->dh, &fs, NULL));
  return 0;
}
Exemple #5
0
int filter_parse(ef_filter_spec* fs, const char* s_in)
{
  struct sockaddr_in lsin, rsin;
  const char* type;
  const char* hostport;
  char* vlan;
  char* remainder;
  char *s;
  int rc = -EINVAL;
  int protocol;
  int i;

  ef_filter_spec_init(fs, EF_FILTER_FLAG_NONE);

  s = strdup(s_in);

  if( (type = strtok(s, ":")) == NULL )
    goto out;

  if( ! strcmp("udp", type) || ! strcmp("tcp", type) ) {
    protocol = strcasecmp(type, "tcp") ? IPPROTO_UDP : IPPROTO_TCP;

    remainder = strtok(NULL, "");
    if( ! strncmp("mcastloop-rx,", remainder, strlen("mcastloop-rx,")) ) {
      ef_filter_spec_init(fs, EF_FILTER_FLAG_MCAST_LOOP_RECEIVE);
      strtok(remainder, ",");
      remainder = strtok(NULL, "");
    }
    if( ! strncmp("vid=", remainder, strlen("vid=")) ) {
      vlan = strtok(remainder, ",");
      remainder = strtok(NULL, "");
      if( ! vlan )
        goto out;
      vlan = strchr(vlan, '=');
      ++vlan;
      TRY(ef_filter_spec_set_vlan(fs, atoi(vlan)));
    }

    if( strchr(remainder, ',') ) {
      hostport = strtok(remainder, ",");
      remainder = strtok(NULL, "");
      TRY(hostport_parse(&lsin, hostport));
      TRY(hostport_parse(&rsin, remainder));
      TRY(ef_filter_spec_set_ip4_full(fs, protocol, lsin.sin_addr.s_addr,
                                      lsin.sin_port, rsin.sin_addr.s_addr,
                                      rsin.sin_port));
      rc = 0;
    }
    else {
      TRY(hostport_parse(&lsin, strtok(remainder, ",")));
      TRY(ef_filter_spec_set_ip4_local(fs, protocol, lsin.sin_addr.s_addr,
                                       lsin.sin_port));
      rc = 0;
    }
  }

  else if( ! strcmp("eth", type) ) {
    uint8_t mac[6];
    int vlan_id = EF_FILTER_VLAN_ID_ANY;
    vlan = strtok(NULL, ",");
    remainder = strtok(NULL, "");
    if( remainder == '\0' ) /* No vlan */
      remainder = vlan;
    else {
      if( strncmp("vid=", vlan, strlen("vid=")) )
        goto out;
      vlan = strchr(vlan, '=');
      ++vlan;
      vlan_id = atoi(vlan);
    }
    for( i = 0; i < 6; ++i ) {
      mac[i] = strtol(remainder, &remainder, 16);
      if( i != 5 ) {
        if( *remainder != ':' )
          goto out;
        ++remainder;
        if( ! strlen(remainder) )
          goto out;
      }
    }
    if( strlen(remainder) )
      goto out;
    TRY(ef_filter_spec_set_eth_local(fs, vlan_id, mac));
    rc = 0;
  }

  else if( ! strcmp("multicast-all", type) ) {
    if( strlen(type) != strlen(s_in) )
      goto out;
    TRY(ef_filter_spec_set_multicast_all(fs));
    rc = 0;
  }

  else if( ! strcmp("unicast-all", type) ) {
    if( strlen(type) != strlen(s_in) )
      goto out;
    TRY(ef_filter_spec_set_unicast_all(fs));
    rc = 0;
  }

  else if( ! strcmp("multicast-mis", type) ) {
    TRY(ef_filter_spec_set_multicast_mismatch(fs));
    if( strlen(type) != strlen(s_in) ) {
      remainder = strtok(NULL, "");
      if( ! (vlan = strchr(remainder, '=')) )
        goto out;
      ++vlan;
      TRY(ef_filter_spec_set_vlan(fs, atoi(vlan)));
    }
    rc = 0;
  }

  else if( ! strcmp("unicast-mis", type) ) {
    TRY(ef_filter_spec_set_unicast_mismatch(fs));
    if( strlen(type) != strlen(s_in) ) {
      remainder = strtok(NULL, "");
      if( ! (vlan = strchr(remainder, '=')) )
        goto out;
      ++vlan;
      TRY(ef_filter_spec_set_vlan(fs, atoi(vlan)));
    }
    rc = 0;
  }

  else if( ! strcmp("sniff", type) ) {
    if( strlen(type) == strlen(s_in) ) {
      TRY(ef_filter_spec_set_port_sniff(fs, 1));
    }
    else {
      remainder = strtok(NULL, "");
      if( ! strcmp("promisc", remainder) )
        TRY(ef_filter_spec_set_port_sniff(fs, 1));
      else if( ! strcmp("no-promisc", remainder) )
        TRY(ef_filter_spec_set_port_sniff(fs, 0));
      else
        TRY(-EINVAL);
    }
    rc = 0;
  }

  else if( ! strcmp("tx-sniff", type) ) {
    TRY(ef_filter_spec_set_tx_port_sniff(fs));
    rc = 0;
  }

  else if( ! strcmp("block-kernel", type) ) {
    TRY(ef_filter_spec_set_block_kernel(fs));
    rc = 0;
  }

  else if( ! strcmp("block-kernel-unicast", type) ) {
    TRY(ef_filter_spec_set_block_kernel_unicast(fs));
    rc = 0;
  }

  else if( ! strcmp("block-kernel-multicast", type) ) {
    TRY(ef_filter_spec_set_block_kernel_multicast(fs));
    rc = 0;
  }

 out:
  free(s);
  return rc;
}