commit-gnuradio
[Top][All Lists]
Advanced

[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:





reply via email to

[Prev in Thread] Current Thread [Next in Thread]