コード例 #1
0
int
pcap_set_promisc(pcap_t *p, int promisc)
{
	D("promisc %d", promisc);
        if (nm_do_ioctl(p, SIOCGIFFLAGS, 0))
		D("SIOCGIFFLAGS failed");
	if (promisc) {
		p->if_flags |= IFF_PPROMISC;
	} else {
		p->if_flags &= ~IFF_PPROMISC;
	}
	if (nm_do_ioctl(p, SIOCSIFFLAGS, 0))
		D("SIOCSIFFLAGS failed");
	return 0;
}
コード例 #2
0
ファイル: pcap.c プロジェクト: ChaosJohn/freebsd
int
pcap_set_promisc(pcap_t *p, int promisc)
{
	struct pcap_ring *me = p;

	D("promisc %d", promisc);
        if (nm_do_ioctl(&me->me, SIOCGIFFLAGS, 0))
		D("SIOCGIFFLAGS failed");
	if (promisc) {
		me->me.if_flags |= IFF_PPROMISC;
	} else {
		me->me.if_flags &= ~IFF_PPROMISC;
	}
	if (nm_do_ioctl(&me->me, SIOCSIFFLAGS, 0))
		D("SIOCSIFFLAGS failed");
	return 0;
}
コード例 #3
0
ファイル: netmap.c プロジェクト: Mipam/tcpreplay
void sendpacket_close_netmap(void *p)
{
    sendpacket_t *sp = p;
    fprintf(stderr, "Switching network driver for %s to normal mode... ",
            sp->device);
    fflush(NULL);
      /* flush any remaining packets */
    ioctl(sp->handle.fd, NIOCTXSYNC, NULL);

#ifdef linux
    if (!sp->is_vale) {
        /* restore original settings:
         * - generic-segmentation-offload
         * - tcp-segmentation-offload
         * - rx-checksumming
         * - tx-checksumming
         */
        sp->data = sp->gso;
        nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_SGSO);
        sp->data = sp->tso;
        nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_STSO);
        sp->data = sp->rxcsum;
        nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_SRXCSUM);
        sp->data = sp->txcsum;
        nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_STXCSUM);
    }
#endif /* linux */

    /* restore interface to normal mode */
#if NETMAP_API < 10
    ioctl(sp->handle.fd, NIOCUNREGIF, NULL);
#endif
    if (sp->mmap_addr)
        munmap(sp->mmap_addr, sp->mmap_size);
    close(sp->handle.fd);
    notice("done!");
}
コード例 #4
0
ファイル: netmap.c プロジェクト: Mipam/tcpreplay
/**
 * Inner sendpacket_open() method for using netmap
 */
void *
sendpacket_open_netmap(const char *device, char *errbuf, void *arg) {
    tcpreplay_t *ctx = (tcpreplay_t*)arg;
    sendpacket_t *sp = NULL;
    nmreq_t nmr;
    char ifname_buf[MAX_IFNAMELEN];
    const char *ifname;
    const char *port = NULL;
    size_t namelen;
    u_int32_t nr_ringid = 0;
    u_int32_t nr_flags = NR_REG_DEFAULT;
    int is_default = 0;

    assert(device);
    assert(errbuf);

    dbg(1, "sendpacket_open_netmap: using netmap");

    bzero(&nmr, sizeof(nmr));

    /* prep & return our sp handle */
    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t));

    if (strlen(device) > MAX_IFNAMELEN - 8) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Interface name is to long: %s\n", device);
        goto IFACENAME_INVALID;
    }

    /* get the version of the netmap driver. If < 0, driver is not installed */
    sp->netmap_version = get_netmap_version();
    if (sp->netmap_version < 0) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to determine the running netmap version.\n"
                "See INSTALL document for details on installing or upgrading netmap.");
        goto NETMAP_NOT_INSTALLED;
    }

    /*
     * Sort out interface names
     *
     * ifname   (foo, netmap:foo or vale:foo) is the port name
     *      foo         bind to a single NIC hardware queue
     *      netmap:foo  bind to a single NIC hardware queue
     *      vale:foo    bind to the Vale virtual interface
     *
     * for netmap version 10+ a suffix can indicate the following:
     *      netmap:foo!     bind to all NIC hardware queues (may cause TX reordering)
     *      netmap:foo^     bind to the host (sw) ring pair
     *      netmap:foo*     bind to the host (sw) and NIC ring pairs (transparent)
     *      netmap:foo-NN   bind to the individual NIC ring pair (queue) where NN = the ring number
     *      netmap:foo{NN   bind to the master side of pipe NN
     *      netmap:foo}NN   bind to the slave side of pipe NN
     */
    if (strncmp(device, "netmap:", 7) && strncmp(device, "vale", 4)) {
        snprintf(ifname_buf, sizeof(ifname_buf), "netmap:%s", device);
        ifname = ifname_buf;
    } else {
        ifname = device;
    }

    if (!strncmp("vale", device, 4))
        sp->is_vale = 1;

    if (ifname[0] == 'n')
        ifname += 7;

    /* scan for a separator */
    for (port = ifname; *port && !index("!-*^{}", *port); port++)
        ;

    namelen = port - ifname;
    if (namelen > sizeof(nmr.nr_name)) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Interface name is to long: %s\n", device);
        goto IFACENAME_INVALID;
    }
    /*
     * Open the netmap device to fetch the number of queues of our
     * interface.
     *
     * The first NIOCREGIF also detaches the card from the
     * protocol stack and may cause a reset of the card,
     * which in turn may take some time for the PHY to
     * reconfigure.
     */
    if ((sp->handle.fd = open("/dev/netmap", O_RDWR)) < 0) {
        dbg(1, "sendpacket_open_netmap: Unable to access netmap");
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to access netmap.\n"
                "See INSTALL to learn which NICs are supported and\n"
                "how to set up netmap-capable network drivers.");
        goto OPEN_FAILED;
    }

    /*
     * The nmreq structure must have the NETMAP_API version for the running machine.
     * However the binary may have been compiled on a different machine than the
     * running machine. Discover the true netmap API version, and be careful to call
     * fuctions that are available on all netmap versions.
     */
    if (sp->netmap_version >= 10) {
        switch (*port) {
        case '-': /* one NIC */
            nr_flags = NR_REG_ONE_NIC;
            nr_ringid = atoi(port + 1);
            break;

        case '*': /* NIC and SW, ignore port */
            nr_flags = NR_REG_NIC_SW;
            if (port[1]) {
                snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid netmap port for nic+sw");
                goto NETMAP_IF_PARSE_FAIL;
            }
            break;

        case '^': /* only sw ring */
            nr_flags = NR_REG_SW;
            if (port[1]) {
                snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid port for sw ring");
                goto NETMAP_IF_PARSE_FAIL;
            }
            break;

        case '{':
            nr_flags = NR_REG_PIPE_MASTER;
            nr_ringid = atoi(port + 1);
            break;

        case '}':
            nr_flags = NR_REG_PIPE_SLAVE;
            nr_ringid = atoi(port + 1);
            break;

        case '!':
            nr_flags = NR_REG_ALL_NIC;
            break;

        default:  /* '\0', no suffix */
            nr_flags = NR_REG_ALL_NIC;
            is_default = 1;
            break;
        }

        if (nr_ringid >= NETMAP_RING_MASK) {
            snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid ringid");
            goto NETMAP_IF_PARSE_FAIL;
        }

        nmr.nr_ringid = nr_ringid;
        nmr.nr_flags = nr_flags;
    }

    nmr.nr_version = sp->netmap_version;
    memcpy(nmr.nr_name, ifname, namelen);
    nmr.nr_name[namelen] = '\0';
    strlcpy(sp->device, nmr.nr_name, sizeof(sp->device));

    /*
     * Register the interface on the netmap device: from now on,
     * we can operate on the network interface without any
     * interference from the legacy network stack.
     *
     * Cards take a long time to reset the PHY.
     */
    fprintf(stderr, "Switching network driver for %s to netmap bypass mode... ",
            sp->device);
    fflush(NULL);
    sleep(1);   /* ensure message prints when user is connected via ssh */

    if (ioctl (sp->handle.fd, NIOCREGIF, &nmr)) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Failure accessing netmap.\n"
                "\tRequest for netmap version %u failed.\n\tCompiled netmap driver is version %u.\n\tError=%s\n",
                sp->netmap_version, NETMAP_API, strerror(errno));
        goto NETMAP_IF_FAILED;
    }

    if (!nmr.nr_memsize) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Netmap interface '%s' not configured.\n",
                device);
        goto NETMAP_IF_FAILED;
    }

    sp->mmap_size = nmr.nr_memsize;
    sp->mmap_addr = (struct netmap_d *)mmap (0, sp->mmap_size,
            PROT_WRITE | PROT_READ, MAP_SHARED, sp->handle.fd, 0);

    if (!sp->mmap_addr || sp->mmap_addr == MAP_FAILED) {
        snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "mmap: %s", strerror (errno));
        goto MMAP_FAILED;
    }

    dbgx(1, "sendpacket_open_netmap: mapping %d Kbytes queues=%d",
            sp->mmap_size >> 10, nmr.nr_tx_rings);

    sp->nm_if = NETMAP_IF(sp->mmap_addr, nmr.nr_offset);
    sp->nmr = nmr;
    sp->handle_type = SP_TYPE_NETMAP;

    /* set up ring IDs */
    sp->cur_tx_ring = 0;
    switch(nr_flags) {
    case NR_REG_DEFAULT:    /* only use one queue to prevent TX reordering */
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
        break;

    case NR_REG_ALL_NIC:
        if (is_default) {
            sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
        } else {
            sp->first_tx_ring = sp->cur_tx_ring = 0;
            sp->last_tx_ring = nmr.nr_tx_rings - 1;
        }
        break;

    case NR_REG_SW:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = nmr.nr_tx_rings;
        break;

    case NR_REG_NIC_SW:
        sp->first_tx_ring = sp->cur_tx_ring = 0;
        sp->last_tx_ring = nmr.nr_tx_rings;
        break;

    case NR_REG_ONE_NIC:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = nr_ringid;
        break;

    default:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
    }
    {
        /* debugging code */
        int i;

        dbgx(1, "%s tx first=%d last=%d  num=%d", ifname,
                sp->first_tx_ring, sp->last_tx_ring, sp->nmr.nr_tx_rings);
        for (i = 0; i <= sp->nmr.nr_tx_rings; i++) {
#ifdef HAVE_NETMAP_RING_HEAD_TAIL
            dbgx(1, "TX%d 0x%p head=%d cur=%d tail=%d", i, NETMAP_TXRING(sp->nm_if, i),
                    (NETMAP_TXRING(sp->nm_if, i))->head,
                    (NETMAP_TXRING(sp->nm_if, i))->cur, (NETMAP_TXRING(sp->nm_if, i))->tail);
#else
            dbgx(1, "TX%d 0x%p cur=%d avail=%d", i, NETMAP_TXRING(sp->nm_if, i),
                    (NETMAP_TXRING(sp->nm_if, i))->cur, (NETMAP_TXRING(sp->nm_if, i))->avail);
#endif
        }
    }

    dbgx(2, "Waiting %d seconds for phy reset...", ctx->options->netmap_delay);
    sleep(ctx->options->netmap_delay);
    dbg(2, "Ready!");

    if (!sp->is_vale) {
        if (nm_do_ioctl(sp, SIOCGIFFLAGS, 0) < 0)
            goto NM_DO_IOCTL_FAILED;

        if ((sp->if_flags & IFF_RUNNING) == 0) {
            dbgx(1, "sendpacket_open_netmap: %s is not running", sp->device);
            snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "interface %s is not running - check cables\n", sp->device);
            goto NETMAP_IF_NOT_RUNNING;
        }

        if ((sp->if_flags & IFF_UP) == 0) {
            dbgx(1, "%s is down, bringing up...", sp->device);
            sp->if_flags |= IFF_UP;
        }

        /* set promiscuous mode */
        sp->if_flags |= IFF_PROMISC;
        if (nm_do_ioctl(sp, SIOCSIFFLAGS, 0) < 0)
            goto NM_DO_IOCTL_FAILED;

#ifdef linux
        /* disable:
         * - generic-segmentation-offload
         * - tcp-segmentation-offload
         * - rx-checksumming
         * - tx-checksumming
         */
        if (nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GGSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GTSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GRXCSUM) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GTXCSUM) < 0)
            goto NM_DO_IOCTL_FAILED;

        sp->data = 0;
        if (nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_SGSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_STSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_SRXCSUM) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_STXCSUM))
            goto NM_DO_IOCTL_FAILED;
#endif
    }

    if(sp->abort)
        goto NETMAP_ABORT;

    notice("done!");

    return sp;

NM_DO_IOCTL_FAILED:
    snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "nm_do_ioctl: %s", strerror (errno));
NETMAP_IF_NOT_RUNNING:
    notice("failed!");
NETMAP_ABORT:
    fprintf(stderr, " Switching network driver for %s to normal mode... ",
            sp->device);
    fflush(NULL);
    munmap(sp->mmap_addr, sp->mmap_size);
MMAP_FAILED:
#if NETMAP_API < 10
    ioctl(sp->handle.fd, NIOCUNREGIF, NULL);
#endif
NETMAP_IF_FAILED:
NETMAP_IF_PARSE_FAIL:
    close (sp->handle.fd);
OPEN_FAILED:
    safe_free(sp);
IFACENAME_INVALID:
NETMAP_NOT_INSTALLED:

    return NULL;
}