[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r7495 - in usrp2/trunk/host: apps lib
From: |
eb |
Subject: |
[Commit-gnuradio] r7495 - in usrp2/trunk/host: apps lib |
Date: |
Tue, 22 Jan 2008 21:39:37 -0700 (MST) |
Author: eb
Date: 2008-01-22 21:39:32 -0700 (Tue, 22 Jan 2008)
New Revision: 7495
Added:
usrp2/trunk/host/lib/gri_ethernet_pf_ring.cc
usrp2/trunk/host/lib/gri_ethernet_pf_ring.h
usrp2/trunk/host/lib/gri_ethernet_pfring.cc
usrp2/trunk/host/lib/gri_ethernet_pfring.h
usrp2/trunk/host/lib/pfring.c
usrp2/trunk/host/lib/pfring.h
usrp2/trunk/host/lib/ring.h
Modified:
usrp2/trunk/host/apps/rx_samples.cc
usrp2/trunk/host/lib/Makefile.am
usrp2/trunk/host/lib/gri_ethernet.cc
usrp2/trunk/host/lib/gri_ethernet.h
usrp2/trunk/host/lib/usrp2_basic.cc
usrp2/trunk/host/lib/usrp2_basic.h
Log:
We now have two ways to get packets into the host. The old way and
the PF_RING way. By restructuring rx_samples so that almost nothing
is happening in the inner loop, we can receive samples at 100MB/s with
250 samples / frame, using either method.
{{{
sudo apps/rx_samples -e eth1 -d 4 -F 250 -N 8M
}}}
Modified: usrp2/trunk/host/apps/rx_samples.cc
===================================================================
--- usrp2/trunk/host/apps/rx_samples.cc 2008-01-22 23:16:10 UTC (rev 7494)
+++ usrp2/trunk/host/apps/rx_samples.cc 2008-01-23 04:39:32 UTC (rev 7495)
@@ -99,6 +99,14 @@
fprintf(stderr, " -S SCALE fpga scaling factor for I & Q
[default=256]\n");
}
+struct pkt_info {
+ int d_nsamples;
+ int d_timestamp;
+
+ pkt_info(int nsamples, int timestamp)
+ : d_nsamples(nsamples), d_timestamp(timestamp) {}
+};
+
int
main(int argc, char **argv)
{
@@ -117,6 +125,8 @@
double tmp;
u2_mac_addr_t mac_addr;
+ setvbuf(stdout, 0, _IOFBF, 64 * 1024); // make stdout fully buffered
+
while ((ch = getopt(argc, argv, "he:m:o:f:d:N:F:S")) != EOF){
switch (ch){
@@ -230,9 +240,12 @@
}
+ std::vector<pkt_info> history;
+ history.reserve(64*1024); // preallocate 64K entries
+
+
long total_samples_recvd = 0;
- long total_pkts_recvd = 0;
-
+
while (!signaled && total_samples_recvd < nsamples){
u2_eth_samples_t pkt;
// fcomplex c_samples[U2_MAX_SAMPLES];
@@ -242,11 +255,10 @@
if (n <= 0)
break;
- total_pkts_recvd++;
total_samples_recvd += n;
- printf("%3d %8d %8ld %8ld\n", n, u2p_timestamp(&pkt.fixed),
- total_pkts_recvd, total_samples_recvd);
+ history.push_back(pkt_info(n, u2p_timestamp(&pkt.fixed)));
+
// convert_samples_to_complex(n, pkt.samples, c_samples);
// size_t r = fwrite(c_samples, sizeof(fcomplex), n, of);
@@ -256,6 +268,7 @@
}
}
+
gri_get_if_stats(interface, &stop);
if (!u2->stop_rx(which)){
@@ -263,12 +276,40 @@
return 1;
}
+
long expected_rx_packets = (nsamples + samples_per_frame -
1)/samples_per_frame;
long expected_rx_bytes = (expected_rx_packets * 24) + nsamples * 4;
- long long delta;
+
+
+ long total_pkts_recvd = 0;
+ total_samples_recvd = 0;
+
+ for (unsigned i = 0; i < history.size(); i++){
+ total_pkts_recvd++;
+ total_samples_recvd += history[i].d_nsamples;
+ printf("%3d %8d %8ld %8ld\n",
+ history[i].d_nsamples,
+ history[i].d_timestamp,
+ total_pkts_recvd, total_samples_recvd);
+ }
+
+ printf("\nUser space statistics:\n");
+ printf(" rx_samples: %8ld", total_samples_recvd);
+ printf(" expected %8d %s\n",
+ nsamples,
+ nsamples - total_samples_recvd == 0 ? "OK" : "NOT OK");
- printf("\nInterface statistics:\n");
+ printf(" rx_packets: %8ld", total_pkts_recvd);
+ printf(" expected %8ld %s\n",
+ expected_rx_packets,
+ expected_rx_packets - total_pkts_recvd == 0 ? "OK" : "NOT OK");
+
+ fflush(stdout);
+
+ printf("\nKernel interface statistics:\n");
+
+ long long delta;
delta = stop.rx_bytes - start.rx_bytes;
printf(" rx_bytes: %8Ld", delta);
printf(" expected %8ld %s\n",
Modified: usrp2/trunk/host/lib/Makefile.am
===================================================================
--- usrp2/trunk/host/lib/Makefile.am 2008-01-22 23:16:10 UTC (rev 7494)
+++ usrp2/trunk/host/lib/Makefile.am 2008-01-23 04:39:32 UTC (rev 7495)
@@ -20,9 +20,15 @@
INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES)
lib_LTLIBRARIES = libusrp2.la
+noinst_LTLIBRARIES = libpfring.la
+libpfring_la_SOURCES = \
+ pfring.c
+
+
libusrp2_la_SOURCES = \
gri_ethernet.cc \
+ gri_ethernet_pfring.cc \
gri_if_stats.cc \
gri_pktfilter.cc \
strtod_si.c \
@@ -31,8 +37,10 @@
include_HEADERS = \
gri_ethernet.h \
+ gri_ethernet_pfring.h \
gri_if_stats.h \
gri_pktfilter.h \
strtod_si.h \
usrp2_basic.h
+libusrp2_la_LIBADD = libpfring.la
Modified: usrp2/trunk/host/lib/gri_ethernet.cc
===================================================================
--- usrp2/trunk/host/lib/gri_ethernet.cc 2008-01-22 23:16:10 UTC (rev
7494)
+++ usrp2/trunk/host/lib/gri_ethernet.cc 2008-01-23 04:39:32 UTC (rev
7495)
@@ -152,35 +152,19 @@
}
int
-gri_ethernet::read_packet (void *buf, int buflen, struct sockaddr_ll *sa)
+gri_ethernet::read_packet (void *buf, int buflen)
{
- struct sockaddr_ll sock_addr;
- if (0 && sa == 0)
- sa = &sock_addr;
-
- socklen_t fromlen = sizeof (*sa);
- int len = recvfrom (d_fd, buf, buflen, 0, (sockaddr *) sa, &fromlen);
- if (0 && len != -1)
- fprintf(stderr, "pkttype = %d\n", sa->sll_pkttype);
-
+ int len = recvfrom (d_fd, buf, buflen, 0, (sockaddr *) 0, 0);
return len;
}
int
-gri_ethernet::read_packet_dont_block (void *buf, int buflen, struct
sockaddr_ll *sa)
+gri_ethernet::read_packet_dont_block (void *buf, int buflen)
{
- struct sockaddr_ll sock_addr;
- if (0 && sa == 0)
- sa = &sock_addr;
-
- socklen_t fromlen = sizeof (*sa);
- int len = recvfrom (d_fd, buf, buflen, MSG_DONTWAIT,
- (sockaddr *) sa, &fromlen);
+ int len = recvfrom (d_fd, buf, buflen, MSG_DONTWAIT, 0, 0);
if (len == -1 && errno == EAGAIN)
return 0;
- if (0)
- fprintf(stderr, "pkttype = %d\n", sa->sll_pkttype);
return len;
}
Modified: usrp2/trunk/host/lib/gri_ethernet.h
===================================================================
--- usrp2/trunk/host/lib/gri_ethernet.h 2008-01-22 23:16:10 UTC (rev 7494)
+++ usrp2/trunk/host/lib/gri_ethernet.h 2008-01-23 04:39:32 UTC (rev 7495)
@@ -68,26 +68,24 @@
*
* \param buf where to put the packet
* \param buflen maximum length of packet in bytes (should be >= 1528)
- * \param sa returned sockaddr
*
* \returns number of bytes read or -1 if trouble.
*
* Returned packet includes 14-byte ethhdr
*/
- int read_packet (void *buf, int buflen, struct sockaddr_ll *sa);
+ int read_packet (void *buf, int buflen);
/*!
* \brief Read packet from interface, but don't block waiting
*
* \param buf where to put the packet
* \param buflen maximum length of packet in bytes (should be >= 1528)
- * \param sa returned sockaddr
*
* \returns number of bytes read, -1 if trouble or 0 if nothing available.
*
* Returned packet includes 14-byte ethhdr
*/
- int read_packet_dont_block (void *buf, int buflen, struct sockaddr_ll *sa);
+ int read_packet_dont_block (void *buf, int buflen);
/*
* \brief Write ethernet packet to interface.
Added: usrp2/trunk/host/lib/gri_ethernet_pf_ring.cc
===================================================================
--- usrp2/trunk/host/lib/gri_ethernet_pf_ring.cc
(rev 0)
+++ usrp2/trunk/host/lib/gri_ethernet_pf_ring.cc 2008-01-23 04:39:32 UTC
(rev 7495)
@@ -0,0 +1,217 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gri_ethernet_pfring.h>
+#include <gri_pktfilter.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <features.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+#include <linux/types.h>
+#include <linux/filter.h> // packet filter
+
+#include <pfring.h>
+
+static int
+open_packet_socket (std::string ifname, int protocol)
+{
+ if (protocol == 0)
+ protocol = htons(ETH_P_ALL);
+
+ int fd = socket (PF_PACKET, SOCK_RAW, protocol);
+ if (fd == -1){
+ fprintf (stderr, "%s: socket: %s\n", ifname.c_str(), strerror (errno));
+ return -1;
+ }
+
+ // get interface index
+ struct ifreq ifr;
+ memset (&ifr, 0, sizeof(ifr));
+ strncpy (ifr.ifr_name, ifname.c_str(), sizeof (ifr.ifr_name));
+ int res = ioctl (fd, SIOCGIFINDEX, &ifr);
+ if (res != 0){
+ ::close (fd);
+ fprintf (stderr, "%s: SIOCGIFINDEX: %s\n", ifname.c_str(),
strerror(errno));
+ return -1;
+ }
+ int ifindex = ifr.ifr_ifindex;
+
+ // bind to the specified interface
+ sockaddr_ll sa;
+ memset (&sa, 0, sizeof (sa));
+ sa.sll_family = AF_PACKET;
+ sa.sll_protocol = protocol;
+ sa.sll_ifindex = ifindex;
+ res = bind (fd, (struct sockaddr *)&sa, sizeof (sa));
+ if (res != 0){
+ ::close (fd);
+ fprintf (stderr, "%s: bind: %s\n", ifname.c_str(), strerror(errno));
+ return -1;
+ }
+ return fd;
+}
+
+static void
+extract_mac_addr (unsigned char *mac, const unsigned char *hwaddr)
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ mac[i] = 0xff;
+
+ i = 0;
+ for (int j = 0; j < 14; j++){
+ if (hwaddr[j] != 0xff){
+ mac[i++] = hwaddr[j];
+ if (i == 6)
+ return;
+ }
+ }
+}
+
+static bool
+get_mac_addr (std::string ifname, int fd, unsigned char *mac)
+{
+ struct ifreq ifr;
+ memset (&ifr, 0, sizeof(ifr));
+ strncpy (ifr.ifr_name, ifname.c_str(), sizeof (ifr.ifr_name));
+ int res = ioctl (fd, SIOCGIFHWADDR, &ifr);
+ if (res != 0){
+ fprintf (stderr, "%s: SIOCGIFHWADDR: %s\n", ifname.c_str(),
strerror(errno));
+ return false;
+ }
+ else {
+ if (0){
+ for (unsigned i = 0; i < sizeof (ifr.ifr_hwaddr.sa_data); i++)
+ fprintf (stderr, "%02x", ifr.ifr_hwaddr.sa_data[i]);
+ fprintf (stderr, "\n");
+ }
+ }
+ extract_mac_addr (mac, (unsigned char *)ifr.ifr_hwaddr.sa_data);
+ return true;
+}
+
+
+
+gri_ethernet::gri_ethernet ()
+{
+ d_fd = -1;
+ memset (d_mac, 0, sizeof (d_mac));
+}
+
+gri_ethernet::~gri_ethernet ()
+{
+ close ();
+}
+
+bool
+gri_ethernet::open (std::string ifname, int protocol)
+{
+ if (d_fd != -1){
+ fprintf (stderr, "gri_ethernet: already open\n");
+ return false;
+ }
+ if ((d_fd = open_packet_socket (ifname, protocol)) == -1){
+ return false;
+ }
+ get_mac_addr (ifname, d_fd, d_mac);
+ return true;
+}
+
+bool
+gri_ethernet::close ()
+{
+ if (d_fd >= 0){
+ ::close (d_fd);
+ d_fd = -1;
+ }
+ return true;
+}
+
+int
+gri_ethernet::read_packet (void *buf, int buflen, struct sockaddr_ll *sa)
+{
+ struct sockaddr_ll sock_addr;
+ if (0 && sa == 0)
+ sa = &sock_addr;
+
+ socklen_t fromlen = sizeof (*sa);
+ int len = recvfrom (d_fd, buf, buflen, 0, (sockaddr *) sa, &fromlen);
+ if (0 && len != -1)
+ fprintf(stderr, "pkttype = %d\n", sa->sll_pkttype);
+
+ return len;
+}
+
+int
+gri_ethernet::read_packet_dont_block (void *buf, int buflen, struct
sockaddr_ll *sa)
+{
+ struct sockaddr_ll sock_addr;
+ if (0 && sa == 0)
+ sa = &sock_addr;
+
+ socklen_t fromlen = sizeof (*sa);
+ int len = recvfrom (d_fd, buf, buflen, MSG_DONTWAIT,
+ (sockaddr *) sa, &fromlen);
+ if (len == -1 && errno == EAGAIN)
+ return 0;
+
+ if (0)
+ fprintf(stderr, "pkttype = %d\n", sa->sll_pkttype);
+ return len;
+}
+
+int
+gri_ethernet::write_packet (const void *buf, int buflen)
+{
+ int retval = send (d_fd, buf, buflen, 0);
+ if (retval < 0){
+ if (errno == EINTR)
+ return write_packet (buf, buflen);
+
+ perror ("gri_ethernet:write_packet: send");
+ return -1;
+ }
+ return retval;
+}
+
+bool
+gri_ethernet::attach_pktfilter (gri_pktfilter *pf)
+{
+ struct sock_fprog filter;
+ filter.len = pf->d_len;
+ filter.filter = pf->d_inst;
+
+ int r = setsockopt (d_fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof
(filter));
+ if (r < 0){
+ perror ("gri_ethernet:attach: SO_ATTACH_FILTER");
+ return false;
+ }
+ return true;
+}
+
Property changes on: usrp2/trunk/host/lib/gri_ethernet_pf_ring.cc
___________________________________________________________________
Name: svn:eol-style
+ native
Added: usrp2/trunk/host/lib/gri_ethernet_pf_ring.h
===================================================================
--- usrp2/trunk/host/lib/gri_ethernet_pf_ring.h (rev 0)
+++ usrp2/trunk/host/lib/gri_ethernet_pf_ring.h 2008-01-23 04:39:32 UTC (rev
7495)
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_GRI_ETHERNET_PF_RING_H
+#define INCLUDED_GRI_ETHERNET_PF_RING_H
+
+#include <string>
+#include <vector>
+
+class gri_pktfilter;
+struct pfring;
+
+/*!
+ * \brief Read and write ethernet frames.
+ *
+ * This provides a low level interface to hardware that communicates
+ * via raw (non-IP) ethernet frames.
+ */
+class gri_ethernet_pf_ring {
+ pfring *d_pfring;
+ unsigned char d_mac[6];
+
+public:
+ gri_ethernet_pf_ring ();
+ ~gri_ethernet_pf_ring ();
+
+ /*!
+ * \param ifname ethernet interface name, e.g., "eth0"
+ * \param protocol is the ethertype protocol number in network order.
+ * Use 0 to receive all protocols.
+ */
+ bool open (std::string ifname, int protocol);
+
+ bool close ();
+
+ /*!
+ * \brief attach packet filter to socket to restrict which packets read sees.
+ * \param pf the packet filter
+ */
+ bool attach_pktfilter (gri_pktfilter *pf);
+
+ /*!
+ * \brief return 6 byte string containing our MAC address
+ */
+ const unsigned char *mac () const { return d_mac; }
+
+ /*!
+ * \brief Return file descriptor associated with socket.
+ */
+ int fd () const { return d_fd; }
+
+ /*!
+ * \brief Read packet from interface.
+ *
+ * \param buf where to put the packet
+ * \param buflen maximum length of packet in bytes (should be >= 1528)
+ * \param sa returned sockaddr
+ *
+ * \returns number of bytes read or -1 if trouble.
+ *
+ * Returned packet includes 14-byte ethhdr
+ */
+ int read_packet (void *buf, int buflen, struct sockaddr_ll *sa);
+
+ /*!
+ * \brief Read packet from interface, but don't block waiting
+ *
+ * \param buf where to put the packet
+ * \param buflen maximum length of packet in bytes (should be >= 1528)
+ * \param sa returned sockaddr
+ *
+ * \returns number of bytes read, -1 if trouble or 0 if nothing available.
+ *
+ * Returned packet includes 14-byte ethhdr
+ */
+ int read_packet_dont_block (void *buf, int buflen, struct sockaddr_ll *sa);
+
+ /*
+ * \brief Write ethernet packet to interface.
+ *
+ * \param buf the packet to write
+ * \param buflen length of packet in bytes
+ *
+ * \returns number of bytes written or -1 if trouble.
+ *
+ * Packet must begin with 14-byte ethhdr, but does not include the FCS.
+ */
+ int write_packet (const void *buf, int buflen);
+};
+
+#endif /* INCLUDED_GRI_ETHERNET_PF_RING_H */
Property changes on: usrp2/trunk/host/lib/gri_ethernet_pf_ring.h
___________________________________________________________________
Name: svn:eol-style
+ native
Copied: usrp2/trunk/host/lib/gri_ethernet_pfring.cc (from rev 7455,
usrp2/trunk/host/lib/gri_ethernet.cc)
===================================================================
--- usrp2/trunk/host/lib/gri_ethernet_pfring.cc (rev 0)
+++ usrp2/trunk/host/lib/gri_ethernet_pfring.cc 2008-01-23 04:39:32 UTC (rev
7495)
@@ -0,0 +1,239 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gri_ethernet_pfring.h>
+#include <gri_pktfilter.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <features.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+#include <linux/types.h>
+#include <linux/filter.h> // packet filter
+
+#define HAVE_PCAP 1 // KLUDGE
+#include <pfring.h>
+
+
+#define get_ring() static_cast<pfring*>(d_ring_void)
+
+
+static int
+open_packet_socket (std::string ifname, int protocol)
+{
+ if (protocol == 0)
+ protocol = htons(ETH_P_ALL);
+
+ int fd = socket (PF_PACKET, SOCK_RAW, protocol);
+ if (fd == -1){
+ fprintf (stderr, "%s: socket: %s\n", ifname.c_str(), strerror (errno));
+ return -1;
+ }
+
+ // get interface index
+ struct ifreq ifr;
+ memset (&ifr, 0, sizeof(ifr));
+ strncpy (ifr.ifr_name, ifname.c_str(), sizeof (ifr.ifr_name));
+ int res = ioctl (fd, SIOCGIFINDEX, &ifr);
+ if (res != 0){
+ ::close (fd);
+ fprintf (stderr, "%s: SIOCGIFINDEX: %s\n", ifname.c_str(),
strerror(errno));
+ return -1;
+ }
+ int ifindex = ifr.ifr_ifindex;
+
+ // bind to the specified interface
+ sockaddr_ll sa;
+ memset (&sa, 0, sizeof (sa));
+ sa.sll_family = AF_PACKET;
+ sa.sll_protocol = protocol;
+ sa.sll_ifindex = ifindex;
+ res = bind (fd, (struct sockaddr *)&sa, sizeof (sa));
+ if (res != 0){
+ ::close (fd);
+ fprintf (stderr, "%s: bind: %s\n", ifname.c_str(), strerror(errno));
+ return -1;
+ }
+ return fd;
+}
+
+
+static void
+extract_mac_addr (unsigned char *mac, const unsigned char *hwaddr)
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ mac[i] = 0xff;
+
+ i = 0;
+ for (int j = 0; j < 14; j++){
+ if (hwaddr[j] != 0xff){
+ mac[i++] = hwaddr[j];
+ if (i == 6)
+ return;
+ }
+ }
+}
+
+static bool
+get_mac_addr (std::string ifname, int fd, unsigned char *mac)
+{
+ struct ifreq ifr;
+ memset (&ifr, 0, sizeof(ifr));
+ strncpy (ifr.ifr_name, ifname.c_str(), sizeof (ifr.ifr_name));
+ int res = ioctl (fd, SIOCGIFHWADDR, &ifr);
+ if (res != 0){
+ fprintf (stderr, "%s: SIOCGIFHWADDR: %s\n", ifname.c_str(),
strerror(errno));
+ return false;
+ }
+ else {
+ if (0){
+ for (unsigned i = 0; i < sizeof (ifr.ifr_hwaddr.sa_data); i++)
+ fprintf (stderr, "%02x", ifr.ifr_hwaddr.sa_data[i]);
+ fprintf (stderr, "\n");
+ }
+ }
+ extract_mac_addr (mac, (unsigned char *)ifr.ifr_hwaddr.sa_data);
+ return true;
+}
+
+
+int
+gri_ethernet_pfring::fd() const
+{
+ return get_ring()->fd;
+}
+
+
+gri_ethernet_pfring::gri_ethernet_pfring ()
+ : d_wr_fd(-1), d_ring_void(0)
+{
+ memset(d_mac, 0, sizeof (d_mac));
+}
+
+gri_ethernet_pfring::~gri_ethernet_pfring ()
+{
+ close();
+}
+
+bool
+gri_ethernet_pfring::open (std::string ifname, int protocol)
+{
+ if (get_ring()){
+ fprintf (stderr, "gri_ethernet_pfring: already open\n");
+ return false;
+ }
+
+ // not promisc, not reentrant
+ d_ring_void = pfring_open(const_cast<char *>(ifname.c_str()), 0, 0);
+ if (!d_ring_void)
+ return false;
+
+ get_mac_addr (ifname, fd(), d_mac);
+
+ if (d_wr_fd != -1){
+ fprintf (stderr, "gri_ethernet: already open\n");
+ return false;
+ }
+ if ((d_wr_fd = open_packet_socket (ifname, protocol)) == -1){
+ return false;
+ }
+
+ return true;
+}
+
+bool
+gri_ethernet_pfring::close ()
+{
+ pfring_close(get_ring());
+ if (d_wr_fd != -1){
+ ::close(d_wr_fd);
+ d_wr_fd = -1;
+ }
+ return true;
+}
+
+int
+gri_ethernet_pfring::read_packet (void *buf, int buflen)
+{
+ struct pfring_pkthdr hdr;
+ int r = pfring_recv(get_ring(), (char *) buf, buflen, &hdr, 1);
+ if (r != 1)
+ return -1;
+
+ if (hdr.caplen != hdr.len){
+ printf("hdr.caplen = %4d, hdr.len = %4d\n", hdr.caplen, hdr.len);
+ }
+
+ return hdr.caplen;
+}
+
+int
+gri_ethernet_pfring::read_packet_dont_block (void *buf, int buflen)
+{
+ struct pfring_pkthdr hdr;
+ int r = pfring_recv(get_ring(), (char *) buf, buflen, &hdr, 0);
+ if (r != 1)
+ return 0;
+
+ if (hdr.caplen != hdr.len){
+ printf("hdr.caplen = %4d, hdr.len = %4d\n", hdr.caplen, hdr.len);
+ }
+
+ return hdr.caplen;
+}
+
+int
+gri_ethernet_pfring::write_packet (const void *buf, int buflen)
+{
+ int retval = send (d_wr_fd, buf, buflen, 0);
+ if (retval < 0){
+ if (errno == EINTR)
+ return write_packet (buf, buflen);
+
+ perror ("gri_ethernet_pfring:write_packet: send");
+ return -1;
+ }
+ return retval;
+}
+
+bool
+gri_ethernet_pfring::attach_pktfilter (gri_pktfilter *pf)
+{
+ struct sock_fprog filter;
+ filter.len = pf->d_len;
+ filter.filter = pf->d_inst;
+
+ int r = setsockopt (fd(), SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof
(filter));
+ if (r < 0){
+ perror ("gri_ethernet_pfring:attach: SO_ATTACH_FILTER");
+ return false;
+ }
+ return true;
+}
+
Copied: usrp2/trunk/host/lib/gri_ethernet_pfring.h (from rev 7455,
usrp2/trunk/host/lib/gri_ethernet.h)
===================================================================
--- usrp2/trunk/host/lib/gri_ethernet_pfring.h (rev 0)
+++ usrp2/trunk/host/lib/gri_ethernet_pfring.h 2008-01-23 04:39:32 UTC (rev
7495)
@@ -0,0 +1,105 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_GRI_ETHERNET_PFRING_H
+#define INCLUDED_GRI_ETHERNET_PFRING_H
+
+#include <string>
+#include <vector>
+
+class gri_pktfilter;
+
+/*!
+ * \brief Read and write ethernet frames.
+ *
+ * This provides a low level interface to hardware that communicates
+ * via raw (non-IP) ethernet frames.
+ */
+class gri_ethernet_pfring {
+ unsigned char d_mac[6];
+ int d_wr_fd;
+
+public:
+ void *d_ring_void; // kludge to work around bad hygiene in pfring.h
+
+ gri_ethernet_pfring ();
+ ~gri_ethernet_pfring ();
+
+ /*!
+ * \param ifname ethernet interface name, e.g., "eth0"
+ * \param protocol is the ethertype protocol number in network order.
+ * Use 0 to receive all protocols.
+ */
+ bool open (std::string ifname, int protocol);
+
+ bool close ();
+
+ /*!
+ * \brief attach packet filter to socket to restrict which packets read sees.
+ * \param pf the packet filter
+ */
+ bool attach_pktfilter (gri_pktfilter *pf);
+
+ /*!
+ * \brief return 6 byte string containing our MAC address
+ */
+ const unsigned char *mac () const { return d_mac; }
+
+ /*!
+ * \brief Return file descriptor associated with socket.
+ */
+ int fd () const;
+
+ /*!
+ * \brief Read packet from interface.
+ *
+ * \param buf where to put the packet
+ * \param buflen maximum length of packet in bytes (should be >= 1528)
+ *
+ * \returns number of bytes read or -1 if trouble.
+ *
+ * Returned packet includes 14-byte ethhdr
+ */
+ int read_packet (void *buf, int buflen);
+
+ /*!
+ * \brief Read packet from interface, but don't block waiting
+ *
+ * \param buf where to put the packet
+ * \param buflen maximum length of packet in bytes (should be >= 1528)
+ *
+ * \returns number of bytes read, -1 if trouble or 0 if nothing available.
+ *
+ * Returned packet includes 14-byte ethhdr
+ */
+ int read_packet_dont_block (void *buf, int buflen);
+
+ /*
+ * \brief Write ethernet packet to interface.
+ *
+ * \param buf the packet to write
+ * \param buflen length of packet in bytes
+ *
+ * \returns number of bytes written or -1 if trouble.
+ *
+ * Packet must begin with 14-byte ethhdr, but does not include the FCS.
+ */
+ int write_packet (const void *buf, int buflen);
+};
+
+#endif /* INCLUDED_GRI_ETHERNET_PFRING_H */
Added: usrp2/trunk/host/lib/pfring.c
===================================================================
--- usrp2/trunk/host/lib/pfring.c (rev 0)
+++ usrp2/trunk/host/lib/pfring.c 2008-01-23 04:39:32 UTC (rev 7495)
@@ -0,0 +1,450 @@
+/*
+ *
+ * (C) 2005-07 - Luca Deri <address@hidden>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "pfring.h"
+
+// #define __USE_XOPEN2K
+#include <sys/types.h>
+#include <pthread.h>
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/sockios.h>
+
+
+// #define RING_DEBUG
+
+/* ******************************* */
+
+unsigned long long rdtsc() {
+ unsigned long long a;
+ asm volatile("rdtsc":"=A" (a));
+ return(a);
+}
+
+/* ******************************* */
+
+int pfring_set_cluster(pfring *ring, u_int clusterId) {
+ return(ring ? setsockopt(ring->fd, 0, SO_ADD_TO_CLUSTER,
+ &clusterId, sizeof(clusterId)): -1);
+}
+
+/* ******************************* */
+
+int pfring_remove_from_cluster(pfring *ring) {
+ return(ring ? setsockopt(ring->fd, 0, SO_REMOVE_FROM_CLUSTER,
+ NULL, 0) : -1);
+}
+
+/* ******************************* */
+
+int pfring_set_reflector(pfring *ring, char *reflectorDevice) {
+ return(ring ?
+ setsockopt(ring->fd, 0, SO_SET_REFLECTOR,
+ &reflectorDevice, strlen(reflectorDevice)) : -1);
+}
+
+/* ******************************* */
+
+static int set_if_promisc(const char *device, int set_promisc) {
+ int sock_fd;
+ struct ifreq ifr;
+
+ if(device == NULL) return(-3);
+
+ sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if(sock_fd <= 0) return(-1);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if(ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
+ close(sock_fd);
+ return(-2);
+ }
+
+ if(set_promisc) {
+ if((ifr.ifr_flags & IFF_PROMISC) == 0) ifr.ifr_flags |= IFF_PROMISC;
+ } else {
+ /* Remove promisc */
+ if((ifr.ifr_flags & IFF_PROMISC) != 0) ifr.ifr_flags &= ~IFF_PROMISC;
+ }
+
+ if(ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1)
+ return(-1);
+
+ close(sock_fd);
+ return(0);
+}
+
+/* **************************************************** */
+
+pfring* pfring_open(char *device_name, u_int8_t promisc, u_int8_t _reentrant) {
+ int err = 0;
+ pfring *ring = (pfring*)malloc(sizeof(pfring));
+
+ if(ring == NULL)
+ return(NULL);
+ else
+ memset(ring, 0, sizeof(pfring));
+
+ ring->reentrant = _reentrant;
+ ring->fd = socket(PF_RING, SOCK_RAW, htons(ETH_P_ALL));
+
+#ifdef RING_DEBUG
+ printf("Open RING [fd=%d]\n", ring->fd);
+#endif
+
+ if(ring->fd > 0) {
+ struct sockaddr sa;
+ int rc;
+ u_int memSlotsLen;
+
+ sa.sa_family = PF_RING;
+ snprintf(sa.sa_data, sizeof(sa.sa_data), "%s", device_name);
+ rc = bind(ring->fd, (struct sockaddr *)&sa, sizeof(sa));
+
+ if(rc == 0) {
+ ring->buffer = (char *)mmap(NULL, PAGE_SIZE,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ ring->fd, 0);
+
+ if(ring->buffer == MAP_FAILED) {
+ printf("mmap() failed");
+ free(ring);
+ return (NULL);
+ }
+
+ ring->slots_info = (FlowSlotInfo *)ring->buffer;
+ if(ring->slots_info->version != RING_FLOWSLOT_VERSION) {
+ printf("Wrong RING version: "
+ "kernel is %i, libpfring was compiled with %i\n",
+ ring->slots_info->version, RING_FLOWSLOT_VERSION);
+ free(ring);
+ return (NULL);
+ }
+ memSlotsLen = ring->slots_info->tot_mem;
+ munmap(ring->buffer, PAGE_SIZE);
+
+ ring->buffer = (char *)mmap(NULL, memSlotsLen,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED, ring->fd, 0);
+
+ if(ring->buffer == MAP_FAILED) {
+ printf("mmap() failed");
+ free(ring);
+ return (NULL);
+ }
+
+ ring->slots_info = (FlowSlotInfo *)ring->buffer;
+ ring->slots = (char *)(ring->buffer+sizeof(FlowSlotInfo));
+
+ /* Safety check */
+ if(ring->slots_info->remove_idx >= ring->slots_info->tot_slots)
+ ring->slots_info->remove_idx = 0;
+
+ ring->page_id = PAGE_SIZE, ring->slot_id = 0, ring->pkts_per_page = 0;
+
+ /* Set defaults */
+ ring->device_name = strdup(device_name);
+
+#ifdef RING_DEBUG
+ printf("RING (%s): tot_slots=%d/slot_len=%d/"
+ "insertIdx=%d/remove_idx=%d/dropped=%d\n",
+ device_name,
+ ring->slots_info->tot_slots,
+ ring->slots_info->slot_len,
+ ring->slots_info->insert_idx,
+ ring->slots_info->remove_idx,
+ ring->slots_info->tot_lost);
+#endif
+
+ if(promisc) {
+ if(set_if_promisc(device_name, 1) == 0)
+ ring->clear_promisc = 1;
+ }
+
+ } else {
+ close(ring->fd);
+ err = -1;
+ }
+ } else {
+ err = -1;
+ free(ring);
+ }
+
+ if(err == 0) {
+ if(ring->reentrant)
+ pthread_spin_init(&ring->spinlock, PTHREAD_PROCESS_PRIVATE);
+ return(ring);
+ } else
+ return(NULL);
+}
+
+/* **************************************************** */
+
+void pfring_close(pfring *ring) {
+ if(!ring) return;
+
+ if(ring->buffer != NULL) {
+ munmap(ring->buffer, ring->slots_info->tot_mem);
+ }
+
+ if(ring->clear_promisc)
+ set_if_promisc(ring->device_name, 0);
+
+ free(ring->device_name);
+ close(ring->fd);
+ if(ring->reentrant)
+ pthread_spin_destroy(&ring->spinlock);
+ free(ring);
+}
+
+/* **************************************************** */
+
+int pfring_toggle_filtering_policy(pfring *ring, u_int8_t
rules_default_accept_policy) {
+ return(ring ? setsockopt(ring->fd, 0, SO_TOGGLE_FILTER_POLICY,
+ &rules_default_accept_policy,
+ sizeof(rules_default_accept_policy)): -1);
+
+}
+
+/* **************************************************** */
+
+int pfring_version(pfring *ring, u_int32_t *version) {
+ if(ring == NULL)
+ return(-1);
+ else {
+ socklen_t len = sizeof(u_int32_t);
+ return(getsockopt(ring->fd, 0, SO_GET_RING_VERSION, version, &len));
+ }
+}
+
+/* **************************************************** */
+
+int pfring_get_filtering_rule_stats(pfring *ring, u_int16_t rule_id,
+ char* stats, u_int *stats_len) {
+ if((ring == NULL) || (*stats_len < sizeof(u_int16_t)))
+ return(-1);
+ else {
+ memcpy(stats, &rule_id, sizeof(u_int16_t));
+ return(getsockopt(ring->fd, 0,
+ SO_GET_FILTERING_RULE_STATS,
+ stats, stats_len));
+ }
+}
+
+/* **************************************************** */
+
+int pfring_get_hash_filtering_rule_stats(pfring *ring,
+ hash_filtering_rule* rule,
+ char* stats, u_int *stats_len) {
+ if(ring == NULL)
+ return(-1);
+ else {
+ char buffer[2048];
+ int rc;
+ u_int len;
+
+ memcpy(buffer, rule, sizeof(hash_filtering_rule));
+ len = sizeof(buffer);
+ rc = getsockopt(ring->fd, 0,
+ SO_GET_HASH_FILTERING_RULE_STATS,
+ buffer, &len);
+ if(rc < 0)
+ return(rc);
+ else {
+ *stats_len = min(*stats_len, rc);
+ memcpy(stats, buffer, *stats_len);
+ return(0);
+ }
+ }
+}
+
+/* **************************************************** */
+
+int pfring_add_filtering_rule(pfring *ring, filtering_rule* rule_to_add) {
+ int rc;
+
+ if((!rule_to_add) || (!ring)) return(-1);
+
+ /* Sanitize entry */
+ if(rule_to_add->core_fields.port_low > rule_to_add->core_fields.port_high)
+ rule_to_add->core_fields.port_low = rule_to_add->core_fields.port_high;
+ if(rule_to_add->core_fields.host_low > rule_to_add->core_fields.host_high)
+ rule_to_add->core_fields.host_low = rule_to_add->core_fields.host_high;
+
+ if(rule_to_add->balance_id > rule_to_add->balance_pool)
+ rule_to_add->balance_id = 0;
+
+ rc = setsockopt(ring->fd, 0, SO_ADD_FILTERING_RULE,
+ rule_to_add, sizeof(filtering_rule));
+
+ return(rc);
+}
+
+/* **************************************************** */
+
+int pfring_enable_ring(pfring *ring) {
+ char dummy;
+
+ if(!ring) return(-1);
+ return(setsockopt(ring->fd, 0, SO_ACTIVATE_RING, &dummy, sizeof(dummy)));
+}
+
+/* **************************************************** */
+
+int pfring_remove_filtering_rule(pfring *ring, u_int16_t rule_id) {
+ int rc;
+
+ rc = ring ? setsockopt(ring->fd, 0, SO_REMOVE_FILTERING_RULE,
+ &rule_id, sizeof(rule_id)): -1;
+
+ return(rc);
+}
+
+/* **************************************************** */
+
+int pfring_handle_hash_filtering_rule(pfring *ring,
+ hash_filtering_rule* rule_to_add,
+ u_char add_rule) {
+ int rc;
+
+ if((!rule_to_add) || (!ring)) return(-1);
+
+ rc = setsockopt(ring->fd, 0, add_rule ? SO_ADD_FILTERING_RULE :
SO_REMOVE_FILTERING_RULE,
+ rule_to_add, sizeof(hash_filtering_rule));
+
+ return(rc);
+}
+
+/* **************************************************** */
+
+int pfring_set_sampling_rate(pfring *ring, u_int32_t rate /* 1 = no sampling
*/) {
+ int rc;
+
+ rc = ring ? setsockopt(ring->fd, 0, SO_SET_SAMPLING_RATE,
+ &rate, sizeof(rate)): -1;
+
+ return(rc);
+}
+
+/* ******************************* */
+
+int pfring_stats(pfring *ring, pfring_stat *stats) {
+ if(ring && stats) {
+ stats->recv = ring->slots_info->tot_read;
+ stats->drop = ring->slots_info->tot_lost;
+ return(1);
+ } else
+ return(0);
+}
+
+/* **************************************************** */
+
+int pfring_recv(pfring *ring, char* buffer, u_int buffer_len,
+ struct pfring_pkthdr *hdr, u_char wait_for_incoming_packet) {
+ FlowSlot *slot;
+ u_int32_t queuedPkts;
+
+ if((ring == NULL) || (ring->buffer == NULL)) return(-1);
+
+ do_pfring_recv:
+ if(ring->reentrant)
+ pthread_spin_lock(&ring->spinlock);
+
+ slot =
(FlowSlot*)&ring->slots[ring->slots_info->remove_idx*ring->slots_info->slot_len];
+
+ if(ring->slots_info->tot_insert >= ring->slots_info->tot_read)
+ queuedPkts = ring->slots_info->tot_insert - ring->slots_info->tot_read;
+ else
+ queuedPkts = ring->slots_info->tot_slots + ring->slots_info->tot_insert -
ring->slots_info->tot_read;
+
+ if(queuedPkts && (slot->slot_state == 1 /* There's a packet to read */)) {
+ char *bucket = (char*)&slot->bucket;
+ struct pfring_pkthdr *_hdr = (struct pfring_pkthdr*)bucket;
+ int bktLen = _hdr->caplen+_hdr->parsed_header_len;
+
+ if(bktLen > buffer_len) bktLen = buffer_len-1;
+
+ if(buffer) {
+ memcpy(buffer, &bucket[sizeof(struct pfring_pkthdr)], bktLen);
+ bucket[bktLen] = '\0';
+ }
+
+ if(ring->slots_info->remove_idx >= (ring->slots_info->tot_slots-1)) {
+ ring->slots_info->remove_idx = 0;
+ ring->page_id = PAGE_SIZE, ring->slot_id = 0, ring->pkts_per_page = 0;
+ } else {
+ ring->slots_info->remove_idx++;
+ ring->pkts_per_page++, ring->slot_id += ring->slots_info->slot_len;
+ }
+
+ if(hdr) memcpy(hdr, _hdr, sizeof(struct pfring_pkthdr));
+
+ ring->slots_info->tot_read++;
+ slot->slot_state = 0; /* Empty slot */
+ if(ring->reentrant) pthread_spin_unlock(&ring->spinlock);
+ return(1);
+ } else if(wait_for_incoming_packet) {
+ struct pollfd pfd;
+ int rc;
+
+ if(ring->reentrant) pthread_spin_unlock(&ring->spinlock);
+
+ /* Sleep when nothing is happening */
+ pfd.fd = ring->fd;
+ pfd.events = POLLIN|POLLERR;
+ pfd.revents = 0;
+
+#ifdef RING_DEBUG
+ printf("==>> poll [remove_idx=%u][insert_idx=%u][loss=%d][queuedPkts=%u]"
+ "[slot_state=%d][tot_insert=%u][tot_read=%u]\n",
+ ring->slots_info->remove_idx,
+ ring->slots_info->insert_idx,
+ ring->slots_info->tot_lost,
+ queuedPkts, slot->slot_state,
+ ring->slots_info->tot_insert,
+ ring->slots_info->tot_read);
+#endif
+
+ errno = 0;
+
+ rc = poll(&pfd, 1, -1);
+
+ ring->num_poll_calls++;
+
+ if(rc == -1)
+ return(-1);
+ else
+ goto do_pfring_recv;
+ }
+
+ return(-1); /* Not reached */
+}
Property changes on: usrp2/trunk/host/lib/pfring.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: usrp2/trunk/host/lib/pfring.h
===================================================================
--- usrp2/trunk/host/lib/pfring.h (rev 0)
+++ usrp2/trunk/host/lib/pfring.h 2008-01-23 04:39:32 UTC (rev 7495)
@@ -0,0 +1,143 @@
+/*
+ *
+ * (C) 2005-07 - Luca Deri <address@hidden>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PFRING_H_
+#define _PFRING_H_
+
+#include <sys/types.h>
+
+#ifndef __USE_XOPEN2K
+typedef volatile int pthread_spinlock_t;
+extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared)
__THROW;
+
+/* Destroy the spinlock LOCK. */
+extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW;
+
+/* Wait until spinlock LOCK is retrieved. */
+extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW;
+
+/* Release spinlock LOCK. */
+extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW;
+#endif
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+
+#if 0
+//#ifndef HAVE_PCAP
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/sockios.h>
+#endif
+
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+
+#include <ring.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <time.h>
+#include <string.h>
+#include <pthread.h>
+
+
+#define PAGE_SIZE 4096
+
+#define POLL_SLEEP_STEP 10 /* ns = 0.1 ms */
+#define POLL_SLEEP_MIN POLL_SLEEP_STEP
+#define POLL_SLEEP_MAX 1000 /* ns */
+#define POLL_QUEUE_MIN_LEN 500 /* # packets */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef SAFE_RING_MODE
+ static char staticBucket[2048];
+#endif
+
+ /* ********************************* */
+
+ typedef struct {
+ char *buffer, *slots, *device_name;
+ int fd;
+ FlowSlotInfo *slots_info;
+ u_int page_id, slot_id, pkts_per_page;
+ u_int poll_sleep;
+ u_int8_t clear_promisc, reentrant;
+ u_long num_poll_calls;
+ pthread_spinlock_t spinlock;
+ } pfring;
+
+ typedef struct {
+ u_int64_t recv, drop;
+ } pfring_stat;
+
+ /* NOTE: keep 'struct pfring_pkthdr' in sync with 'struct pcap_pkthdr'
(ring.h) */
+ struct pfring_pkthdr {
+ struct timeval ts; /* time stamp */
+ u_int32_t caplen; /* length of portion present */
+ u_int32_t len; /* length this packet (off wire) */
+ struct pkt_parsing_info parsed_pkt; /* packet parsing info */
+ u_int16_t parsed_header_len; /* Extra parsing data before packet */
+ };
+
+ /* ********************************* */
+
+ int pfring_set_cluster(pfring *ring, u_int clusterId);
+ int pfring_remove_from_cluster(pfring *ring);
+ int pfring_set_reflector(pfring *ring, char *reflectorDevice);
+ pfring* pfring_open(char *device_name, u_int8_t promisc, u_int8_t reentrant);
+ void pfring_close(pfring *ring);
+ int pfring_stats(pfring *ring, pfring_stat *stats);
+ int pfring_recv(pfring *ring, char* buffer, u_int buffer_len,
+ struct pfring_pkthdr *hdr, u_char wait_for_incoming_packet);
+ int pfring_get_filtering_rule_stats(pfring *ring, u_int16_t rule_id,
+ char* stats, u_int *stats_len);
+ int pfring_get_hash_filtering_rule_stats(pfring *ring,
+ hash_filtering_rule* rule,
+ char* stats, u_int *stats_len);
+ int pfring_add_filtering_rule(pfring *ring, filtering_rule* rule_to_add);
+ int pfring_handle_hash_filtering_rule(pfring *ring,
+ hash_filtering_rule* rule_to_add,
+ u_char add_rule);
+ int pfring_enable_ring(pfring *ring);
+ int pfring_remove_filtering_rule(pfring *ring, u_int16_t rule_id);
+ int pfring_toggle_filtering_policy(pfring *ring, u_int8_t
rules_default_accept_policy);
+ int pfring_version(pfring *ring, u_int32_t *version);
+ int pfring_set_sampling_rate(pfring *ring, u_int32_t rate /* 1 = no sampling
*/);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PFRING_H_ */
Property changes on: usrp2/trunk/host/lib/pfring.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: usrp2/trunk/host/lib/ring.h
===================================================================
--- usrp2/trunk/host/lib/ring.h (rev 0)
+++ usrp2/trunk/host/lib/ring.h 2008-01-23 04:39:32 UTC (rev 7495)
@@ -0,0 +1,284 @@
+/*
+ * Definitions for packet ring
+ *
+ * 2004-07 Luca Deri <address@hidden>
+ */
+#ifndef __RING_H
+#define __RING_H
+
+#define INCLUDE_MAC_INFO
+
+#ifdef INCLUDE_MAC_INFO
+#define SKB_DISPLACEMENT 14 /* Include MAC address information */
+#else
+#define SKB_DISPLACEMENT 0 /* Do NOT include MAC address information */
+#endif
+
+#define RING_MAGIC
+#define RING_MAGIC_VALUE 0x88
+#define RING_FLOWSLOT_VERSION 9
+
+/* Versioning */
+#define RING_VERSION "3.7.4"
+#define RING_VERSION_NUM 0x030704
+
+/* Set */
+#define SO_ADD_TO_CLUSTER 99
+#define SO_REMOVE_FROM_CLUSTER 100
+#define SO_SET_REFLECTOR 101
+#define SO_SET_STRING 102
+#define SO_ADD_FILTERING_RULE 103
+#define SO_REMOVE_FILTERING_RULE 104
+#define SO_TOGGLE_FILTER_POLICY 105
+#define SO_SET_SAMPLING_RATE 106
+#define SO_ACTIVATE_RING 107
+
+/* Get */
+#define SO_GET_RING_VERSION 110
+#define SO_GET_FILTERING_RULE_STATS 111
+#define SO_GET_HASH_FILTERING_RULE_STATS 112
+
+/* *********************************** */
+
+#define NO_VLAN ((u_int16_t)-1)
+
+struct pkt_parsing_info {
+ /* core fields (also used by NetFlow) */
+ u_int16_t eth_type; /* Ethernet type */
+ u_int16_t vlan_id; /* VLAN Id or NO_VLAN */
+ u_int8_t l3_proto, ipv4_tos; /* Layer 3 protocol/TOS */
+ u_int32_t ipv4_src, ipv4_dst; /* IPv4 src/dst IP addresses */
+ u_int16_t l4_src_port, l4_dst_port; /* Layer 4 src/dst ports */
+ u_int8_t tcp_flags; /* TCP flags (0 if not available) */
+ /* Offsets of L3/L4/payload elements */
+ u_int16_t eth_offset, vlan_offset, l3_offset, l4_offset, payload_offset;
+};
+
+#ifndef HAVE_PCAP
+/* NOTE: keep 'struct pfring_pkthdr' in sync with 'struct pcap_pkthdr'
(ring.h) */
+struct pcap_pkthdr {
+ struct timeval ts; /* time stamp */
+ u_int32_t caplen; /* length of portion present */
+ u_int32_t len; /* length this packet (off wire) */
+ struct pkt_parsing_info parsed_pkt; /* packet parsing info */
+ u_int16_t parsed_header_len; /* Extra parsing data before packet */
+};
+#endif
+
+/* *********************************** */
+
+#define MAX_PLUGIN_ID 128
+
+/* ************************************************* */
+
+typedef struct {
+ u_int8_t proto; /* Use 0 for 'any' protocol */
+ u_int16_t vlan_id; /* Use '0' for any vlan */
+ u_int32_t host_low, host_high; /* User '0' for any host. This is applied
to both source
+ and destination. */
+ u_int16_t port_low, port_high; /* All ports between port_low...port_high
+ 0 means 'any' port. This is applied to
both source
+ and destination. This means that
+ (proto, sip, sport, dip, dport) matches
the rule if
+ one in "sip & sport", "sip & dport"
"dip & sport"
+ match. */
+} filtering_rule_core_fields;
+
+/* ************************************************* */
+
+typedef struct {
+ char payload_pattern[32]; /* If strlen(payload_pattern) > 0, the
packet payload
+ must match the specified pattern */
+ u_int16_t filter_plugin_id; /* If > 0 identifies a plugin to which the
datastructure
+ below will be passed for matching */
+ char filter_plugin_data[64]; /* Opaque datastructure that is
interpreted by the
+ specified plugin and that specifies a
filtering
+ criteria to be checked for match.
Usually this data
+ is re-casted to a more meaningful
datastructure
+ */
+} filtering_rule_extended_fields;
+
+/* ************************************************* */
+
+typedef struct {
+ /* Plugin Action */
+ u_int16_t plugin_id; /* ('0'=no plugin) id of the plugin associated with
this rule */
+} filtering_rule_plugin_action;
+
+typedef enum {
+ forward_packet_and_stop_rule_evaluation = 0,
+ dont_forward_packet_and_stop_rule_evaluation,
+ execute_action_and_continue_rule_evaluation
+} rule_action_behaviour;
+
+typedef struct {
+ u_int16_t rule_id; /* Rules are processed in order from
lowest to higest id */
+ rule_action_behaviour rule_action; /* What to do in case of match */
+ u_int8_t balance_id, balance_pool; /* If balance_pool > 0, then pass the
packet above only if the
+ (hash(proto, sip, sport, dip, dport) %
balance_pool)
+ = balance_id */
+ filtering_rule_core_fields core_fields;
+ filtering_rule_extended_fields extended_fields;
+ filtering_rule_plugin_action plugin_action;
+} filtering_rule;
+
+/* *********************************** */
+
+#define DEFAULT_RING_HASH_SIZE 4096
+
+/*
+ * The hashtable contains only perfect matches: no
+ * wildacards or so are accepted.
+*/
+typedef struct {
+ u_int16_t vlan_id;
+ u_int8_t proto;
+ u_int32_t host_peer_a, host_peer_b;
+ u_int16_t port_peer_a, port_peer_b;
+
+ rule_action_behaviour rule_action; /* What to do in case of match */
+ filtering_rule_plugin_action plugin_action;
+} hash_filtering_rule;
+
+/* ************************************************* */
+
+typedef struct _filtering_hash_bucket {
+ hash_filtering_rule rule;
+ void *plugin_data_ptr; /* ptr to a *continuous*
memory area
+ allocated by the plugin */
+ u_int16_t plugin_data_ptr_len;
+ struct _filtering_hash_bucket *next;
+} filtering_hash_bucket;
+
+/* ************************************************* */
+
+#ifdef __KERNEL__
+
+typedef struct {
+ filtering_rule rule;
+#ifdef CONFIG_TEXTSEARCH
+ struct ts_config *pattern;
+#endif
+ struct list_head list;
+
+ /* Plugin action */
+ void *plugin_data_ptr; /* ptr to a *continuous* memory area allocated by the
plugin */
+} filtering_rule_element;
+
+struct parse_buffer {
+ void *mem;
+ u_int16_t mem_len;
+};
+
+/* Plugins */
+/* Execute an action (e.g. update rule stats) */
+typedef int (*plugin_handle_skb)(filtering_rule_element *rule, /* In
case the match is on the list */
+ filtering_hash_bucket *hash_bucket, /* In case
the match is on the hash */
+ struct pcap_pkthdr *hdr,
+ struct sk_buff *skb,
+ u_int16_t filter_plugin_id,
+ struct parse_buffer
*filter_rule_memory_storage);
+/* Return 1/0 in case of match/no match for the given skb */
+typedef int (*plugin_filter_skb)(filtering_rule_element *rule,
+ struct pcap_pkthdr *hdr,
+ struct sk_buff *skb,
+ struct parse_buffer
**filter_rule_memory_storage);
+/* Get stats about the rule */
+typedef int (*plugin_get_stats)(filtering_rule_element *element,
+ u_char* stats_buffer, u_int stats_buffer_len);
+
+struct pfring_plugin_registration {
+ u_int16_t plugin_id;
+ plugin_filter_skb pfring_plugin_filter_skb; /* Filter skb: 1=match, 0=no
match */
+ plugin_handle_skb pfring_plugin_handle_skb;
+ plugin_get_stats pfring_plugin_get_stats;
+};
+
+typedef int (*register_pfring_plugin)(struct pfring_plugin_registration *reg);
+typedef int (*unregister_pfring_plugin)(u_int16_t pfring_plugin_id);
+
+extern register_pfring_plugin get_register_pfring_plugin(void);
+extern unregister_pfring_plugin get_unregister_pfring_plugin(void);
+extern void set_register_pfring_plugin(register_pfring_plugin the_handler);
+extern void set_unregister_pfring_plugin(unregister_pfring_plugin the_handler);
+
+extern int do_register_pfring_plugin(struct pfring_plugin_registration *reg);
+extern int do_unregister_pfring_plugin(u_int16_t pfring_plugin_id);
+
+#endif
+
+/* *********************************** */
+
+enum cluster_type {
+ cluster_per_flow = 0,
+ cluster_round_robin
+};
+
+/* *********************************** */
+
+#define RING_MIN_SLOT_SIZE (60+sizeof(struct pcap_pkthdr))
+#define RING_MAX_SLOT_SIZE (1514+sizeof(struct pcap_pkthdr))
+
+#ifndef min
+#define min(a,b) ((a < b) ? a : b)
+#endif
+
+/* *********************************** */
+
+typedef struct flowSlotInfo {
+ u_int16_t version, sample_rate;
+ u_int32_t tot_slots, slot_len, data_len, tot_mem;
+
+ u_int64_t tot_pkts, tot_lost;
+ u_int64_t tot_insert, tot_read;
+ u_int32_t insert_idx, remove_idx;
+} FlowSlotInfo;
+
+/* *********************************** */
+
+typedef struct flowSlot {
+#ifdef RING_MAGIC
+ u_char magic; /* It must alwasy be zero */
+#endif
+ u_char slot_state; /* 0=empty, 1=full */
+ u_char bucket; /* bucket[bucketLen] */
+} FlowSlot;
+
+/* *********************************** */
+
+#ifdef __KERNEL__
+
+FlowSlotInfo* getRingPtr(void);
+int allocateRing(char *deviceName, u_int numSlots,
+ u_int bucketLen, u_int sampleRate);
+unsigned int pollRing(struct file *fp, struct poll_table_struct * wait);
+void deallocateRing(void);
+
+/* ************************* */
+
+typedef int (*handle_ring_skb)(struct sk_buff *skb, u_char recv_packet, u_char
real_skb);
+extern handle_ring_skb get_skb_ring_handler(void);
+extern void set_skb_ring_handler(handle_ring_skb the_handler);
+extern void do_skb_ring_handler(struct sk_buff *skb,
+ u_char recv_packet, u_char real_skb);
+
+typedef int (*handle_ring_buffer)(struct net_device *dev,
+ char *data, int len);
+extern handle_ring_buffer get_buffer_ring_handler(void);
+extern void set_buffer_ring_handler(handle_ring_buffer the_handler);
+extern int do_buffer_ring_handler(struct net_device *dev,
+ char *data, int len);
+
+#endif /* __KERNEL__ */
+
+/* *********************************** */
+
+#define PF_RING 27 /* Packet Ring */
+#define SOCK_RING PF_RING
+
+/* ioctl() */
+#define SIORINGPOLL 0x8888
+
+/* *********************************** */
+
+#endif /* __RING_H */
Property changes on: usrp2/trunk/host/lib/ring.h
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: usrp2/trunk/host/lib/usrp2_basic.cc
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic.cc 2008-01-22 23:16:10 UTC (rev 7494)
+++ usrp2/trunk/host/lib/usrp2_basic.cc 2008-01-23 04:39:32 UTC (rev 7495)
@@ -21,6 +21,7 @@
#endif
#include "usrp2_basic.h"
#include "gri_ethernet.h"
+#include "gri_ethernet_pfring.h" // FIXME
#include "gri_pktfilter.h"
#include <iostream>
#include <math.h>
@@ -40,7 +41,7 @@
usrp2_basic::usrp2_basic()
- : d_ethernet(new gri_ethernet()), d_pf(0)
+ : d_ethernet(new GRI_ETHERNET()), d_pf(0)
{
assert(sizeof(u2_eth_samples_t) == (size_t) MAX_PKTLEN);
}
@@ -60,7 +61,7 @@
if (d_pf)
delete d_pf;
- if (0){
+ if (1){
d_pf = gri_pktfilter::make_ethertype_inbound(U2_ETHERTYPE,
d_ethernet->mac());
if (!d_ethernet->attach_pktfilter(d_pf))
return false;
@@ -128,7 +129,7 @@
while(1){
memset(pktbuf, 0, sizeof(pktbuf));
- int len = d_ethernet->read_packet_dont_block(pktbuf, sizeof(pktbuf), 0);
+ int len = d_ethernet->read_packet_dont_block(pktbuf, sizeof(pktbuf));
if (len < 0){
perror("usrp2_basic: read_packet_dont_block");
return result;
@@ -310,7 +311,7 @@
usrp2_basic::read_raw_samples(const u2_mac_addr_t &which,
u2_eth_samples_t *pkt)
{
- int len = d_ethernet->read_packet(pkt, sizeof(*pkt), 0);
+ int len = d_ethernet->read_packet(pkt, sizeof(*pkt));
// printf("read_packet = %d\n", len);
if (len <= 0)
Modified: usrp2/trunk/host/lib/usrp2_basic.h
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic.h 2008-01-22 23:16:10 UTC (rev 7494)
+++ usrp2/trunk/host/lib/usrp2_basic.h 2008-01-23 04:39:32 UTC (rev 7495)
@@ -25,11 +25,14 @@
#include "usrp2_eth_packet.h"
class gri_ethernet;
+class gri_ethernet_pfring;
class gri_pktfilter;
+#define GRI_ETHERNET gri_ethernet
+
class usrp2_basic : public boost::noncopyable
{
- gri_ethernet *d_ethernet;
+ GRI_ETHERNET *d_ethernet;
gri_pktfilter *d_pf;
public:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r7495 - in usrp2/trunk/host: apps lib,
eb <=