commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r8540 - in usrp2/trunk/host-ng: apps include/usrp2 lib


From: jcorgan
Subject: [Commit-gnuradio] r8540 - in usrp2/trunk/host-ng: apps include/usrp2 lib
Date: Sun, 1 Jun 2008 13:24:00 -0600 (MDT)

Author: jcorgan
Date: 2008-06-01 13:23:57 -0600 (Sun, 01 Jun 2008)
New Revision: 8540

Added:
   usrp2/trunk/host-ng/lib/ethernet.cc
   usrp2/trunk/host-ng/lib/ethernet.h
   usrp2/trunk/host-ng/lib/find.cc
   usrp2/trunk/host-ng/lib/pktfilter.cc
   usrp2/trunk/host-ng/lib/pktfilter.h
Modified:
   usrp2/trunk/host-ng/apps/test_usrp2.cc
   usrp2/trunk/host-ng/include/usrp2/usrp2.h
   usrp2/trunk/host-ng/lib/Makefile.am
Log:
Work in progress, ported ethernet and pktfilter class to ng.

Modified: usrp2/trunk/host-ng/apps/test_usrp2.cc
===================================================================
--- usrp2/trunk/host-ng/apps/test_usrp2.cc      2008-06-01 07:32:34 UTC (rev 
8539)
+++ usrp2/trunk/host-ng/apps/test_usrp2.cc      2008-06-01 19:23:57 UTC (rev 
8540)
@@ -26,8 +26,11 @@
 int
 main(int argc, char **argv)
 {
-  usrp2::usrp2::sptr u2 = usrp2::usrp2::make("eth0");
-  std::cout << u2->foo(1) << std::endl;
+  usrp2::props_vector_t u2s = usrp2::find("eth0");
+  std::cout << u2s.size() << std::endl;
+
+  //usrp2::usrp2::sptr u2 = usrp2::usrp2::make("eth0");
+  //std::cout << u2->foo(1) << std::endl;
   
   return 0;
 }

Modified: usrp2/trunk/host-ng/include/usrp2/usrp2.h
===================================================================
--- usrp2/trunk/host-ng/include/usrp2/usrp2.h   2008-06-01 07:32:34 UTC (rev 
8539)
+++ usrp2/trunk/host-ng/include/usrp2/usrp2.h   2008-06-01 19:23:57 UTC (rev 
8540)
@@ -21,9 +21,26 @@
 
 #include <boost/shared_ptr.hpp>
 #include <boost/utility.hpp>
+#include <vector>
 
 namespace usrp2 {
 
+/*!
+ * Structure to hold properties of USRP2 hardware devices.
+ *
+ */
+struct props
+{
+  std::string addr;
+  uint16_t hw_rev;
+  uint8_t fpga_md5sum[16];
+  uint8_t sw_md5sum[16];
+};
+
+typedef std::vector<props> props_vector_t;
+
+props_vector_t find(const std::string &ifc, const std::string &addr=""); 
+
 class usrp2 : boost::noncopyable
 {
 private:

Modified: usrp2/trunk/host-ng/lib/Makefile.am
===================================================================
--- usrp2/trunk/host-ng/lib/Makefile.am 2008-06-01 07:32:34 UTC (rev 8539)
+++ usrp2/trunk/host-ng/lib/Makefile.am 2008-06-01 19:23:57 UTC (rev 8540)
@@ -23,8 +23,14 @@
        libusrp2ng.la
 
 libusrp2ng_la_SOURCES = \
+       ethernet.cc \
+       find.cc \
+       pktfilter.cc \
        usrp2.cc
 
 libusrp2ng_la_LIBADD = \
        $(GR_OMNITHREAD_LIBS)
 
+# Private headers not needed for above the API development
+noinst_HEADERS = \
+       ethernet.h

Added: usrp2/trunk/host-ng/lib/ethernet.cc
===================================================================
--- usrp2/trunk/host-ng/lib/ethernet.cc                         (rev 0)
+++ usrp2/trunk/host-ng/lib/ethernet.cc 2008-06-01 19:23:57 UTC (rev 8540)
@@ -0,0 +1,206 @@
+/* -*- 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
+
+#define ETHERNET_DEBUG 1
+
+#include "ethernet.h"
+#include "pktfilter.h"
+
+#include <iostream>
+#include <unistd.h>
+#include <fcntl.h>
+#include <features.h>
+#include <net/if.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <linux/types.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>      // packet filter
+
+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;
+}
+
+ethernet::ethernet ()
+{
+  if (ETHERNET_DEBUG)
+    std::cerr << "usrp2::ethernet: constructor" << std::endl;
+    
+  d_fd = -1;
+  memset (d_mac, 0, sizeof (d_mac));
+}
+
+ethernet::~ethernet ()
+{
+  if (ETHERNET_DEBUG)
+    std::cerr << "usrp2::ethernet: destructor" << std::endl;
+    
+  close ();
+}
+
+bool
+ethernet::open (std::string ifname, int protocol)
+{
+  if (d_fd != -1){
+    fprintf (stderr, "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
+ethernet::close ()
+{
+  if (d_fd >= 0){
+    ::close (d_fd);
+    d_fd = -1;
+  }
+  return true;
+}
+
+int
+ethernet::read_packet (void *buf, int buflen)
+{
+  int len = recvfrom (d_fd, buf, buflen, 0, (sockaddr *) 0, 0);
+  return len;
+}
+
+int
+ethernet::read_packet_dont_block (void *buf, int buflen)
+{
+  int len = recvfrom (d_fd, buf, buflen, MSG_DONTWAIT, 0, 0);
+  if (len == -1 && errno == EAGAIN)
+    return 0;
+  
+  return len;
+}
+
+int
+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 ("ethernet:write_packet: send");
+    return -1;
+  }
+  return retval;
+}
+
+bool
+ethernet::attach_pktfilter (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 ("ethernet:attach:  SO_ATTACH_FILTER");
+    return false;
+  }
+  return true;
+}
+

Added: usrp2/trunk/host-ng/lib/ethernet.h
===================================================================
--- usrp2/trunk/host-ng/lib/ethernet.h                          (rev 0)
+++ usrp2/trunk/host-ng/lib/ethernet.h  2008-06-01 19:23:57 UTC (rev 8540)
@@ -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_USRP2_ETHERNET_H
+#define INCLUDED_USRP2_ETHERNET_H
+
+#include <string>
+#include <vector>
+
+class pktfilter;
+
+/*!
+ * \brief Read and write ethernet frames.
+ *
+ * This provides a low level interface to hardware that communicates
+ * via raw (non-IP) ethernet frames.
+ */
+class ethernet {
+  int          d_fd;
+  unsigned char        d_mac[6];
+
+public:
+  ethernet ();
+  ~ethernet ();
+
+  static const int MAX_PKTLEN = 1512;
+  static const int MIN_PKTLEN = 64;
+
+  /*!
+   * \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 (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)
+   *
+   * \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_USRP2_ETHERNET_H */

Added: usrp2/trunk/host-ng/lib/find.cc
===================================================================
--- usrp2/trunk/host-ng/lib/find.cc                             (rev 0)
+++ usrp2/trunk/host-ng/lib/find.cc     2008-06-01 19:23:57 UTC (rev 8540)
@@ -0,0 +1,150 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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 <usrp2_eth_packet.h>
+#include <usrp2/usrp2.h>
+#include <boost/scoped_ptr.hpp>
+#include "ethernet.h"
+#include "pktfilter.h"
+#include <iostream>
+
+#define FIND_DEBUG 1
+
+std::ostream& operator<<(std::ostream &os, const u2_mac_addr_t &x)
+{
+  char buf[128];
+
+  snprintf(buf, sizeof(buf),
+          "%02x:%02x:%02x:%02x:%02x:%02x",
+          x.addr[0],x.addr[1],x.addr[2],
+          x.addr[3],x.addr[4],x.addr[5]);
+
+  os << buf;
+  return os;
+}
+
+namespace usrp2 {
+
+props_vector_t
+find(const std::string &ifc, const std::string &addr)
+{
+  if (FIND_DEBUG) {
+    std::cerr << "Searching interface " << ifc << " for "
+              << (addr == "" ? "all USRP2s" : addr)
+             << std::endl;
+  }
+  
+  props_vector_t result;
+  struct command {
+    u2_eth_packet_t    h;
+    op_id_t            op_id;
+  };
+    
+  struct reply {
+    u2_eth_packet_t    h;
+    op_id_reply_t      op_id_reply;
+  };
+
+  std::vector<op_id_reply_t> replies;
+  std::auto_ptr<ethernet> enet(new ethernet()); 
+
+  if (!enet->open(ifc, htons(U2_ETHERTYPE)))
+    return result;
+
+  std::auto_ptr<pktfilter> pf(pktfilter::make_ethertype_inbound(U2_ETHERTYPE, 
enet->mac()));
+  if (!enet->attach_pktfilter(pf.get()))
+    return result;
+
+  static u2_mac_addr_t broadcast_mac_addr =
+    {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
+
+  uint8_t pktbuf[ethernet::MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
+
+  command *c = (command *)pktbuf;
+  c->h.ehdr.ethertype = htons(U2_ETHERTYPE);
+  c->h.ehdr.dst = broadcast_mac_addr;
+  memcpy(&c->h.ehdr.src, enet->mac(), 6);
+  c->h.thdr.flags = 0;
+  c->h.thdr.seqno = 0;
+  c->h.thdr.ack = 0;
+  u2p_set_word0(&c->h.fixed, 0, CONTROL_CHAN);
+  u2p_set_timestamp(&c->h.fixed, -1);
+  c->op_id.opcode = OP_ID;
+  c->op_id.len = sizeof(op_id_t);
+  int len = std::max((size_t) ethernet::MIN_PKTLEN, sizeof(command));
+  if (enet->write_packet(c, len) != len)
+    return result;
+
+  if (FIND_DEBUG)
+    std::cerr << "usrp2::find: broadcast ID command" << std::endl;
+    
+  /*
+   * Wait no longer than 10ms and read all packets available.
+   */
+  fd_set read_fds;
+  FD_ZERO(&read_fds);
+  FD_SET(enet->fd(), &read_fds);
+  struct timeval timeout;
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 10 * 1000; // 10 ms
+  
+  select(enet->fd()+1, &read_fds, 0, 0, &timeout);
+  while(1) {
+    memset(pktbuf, 0, sizeof(pktbuf));
+    len = enet->read_packet_dont_block(pktbuf, sizeof(pktbuf));
+    if (len < 0){
+      perror("usrp2_basic: read_packet_dont_block");
+        return result;
+    }
+    if (len == 0)
+      break;
+
+    reply *rp = (reply *)pktbuf;
+    if (u2p_chan(&rp->h.fixed) != CONTROL_CHAN)  // ignore
+      continue;
+    if (rp->op_id_reply.opcode != OP_ID_REPLY) // ignore
+      continue;
+
+
+    const uint8_t *mac = (const uint8_t *)&rp->op_id_reply.addr;
+    char addr_buf[128];
+    snprintf(addr_buf, sizeof(addr_buf), "%02x:%02x:%02x:%02x:%02x:%02x",
+            mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+    props p;
+    p.addr = std::string(addr_buf);  
+    p.hw_rev = rp->op_id_reply.hw_rev;
+    memcpy(&p.fpga_md5sum, &rp->op_id_reply.fpga_md5sum, 
sizeof(p.fpga_md5sum));
+    memcpy(&p.sw_md5sum, &rp->op_id_reply.sw_md5sum, sizeof(p.sw_md5sum));
+    
+    if (FIND_DEBUG)
+      std::cerr << "usrp2::find: response from " << p.addr << std::endl;
+
+    if ((addr == "") || (addr == p.addr))
+      result.push_back(p);
+  }
+      
+  return result;
+}
+
+}

Added: usrp2/trunk/host-ng/lib/pktfilter.cc
===================================================================
--- usrp2/trunk/host-ng/lib/pktfilter.cc                                (rev 0)
+++ usrp2/trunk/host-ng/lib/pktfilter.cc        2008-06-01 19:23:57 UTC (rev 
8540)
@@ -0,0 +1,153 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2007 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 "pktfilter.h"
+#include <iostream>
+#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 <assert.h>
+#include <linux/types.h>
+#include <linux/filter.h>      // packet filter
+
+#define PKTFILTER_DEBUG 1
+
+/*
+ * This is all based on the Berkeley Packet Filter (BPF) as implemented on 
Linux.
+ *
+ * The BPF allows you to run an interpreted program (a filter) in the
+ * kernel that sorts through the packets looking for ones you are
+ * interested in.  This eliminates the overhead of passing all of the
+ * networking packets up into user space for filtering there.
+ *
+ * For documentation on this see
+ * /usr/src/linux/Documentation/networking/filter.txt, The BSD
+ * Berkeley Packet Filter manual page, and "The BSD Packet Filter: A
+ * New Architecture for User-level Packet Capture", by Steven McCanne
+ * and Van Jacobson.
+ */
+
+pktfilter::pktfilter ()
+  : d_len (0), d_inst (0)
+{
+  if (PKTFILTER_DEBUG)
+    std::cerr << "pktfilter: constructor" << std::endl;
+}
+
+pktfilter::~pktfilter ()
+{
+  if (PKTFILTER_DEBUG)
+    std::cerr << "pktfilter: destructor" << std::endl;
+  delete [] d_inst;
+}
+
+inline static sock_filter
+make_stmt (__u16 code, __u32 k)
+{
+  sock_filter  f;
+  f.code = code;
+  f.jt = 0;
+  f.jf = 0;
+  f.k = k;
+  return f;
+}
+
+inline static sock_filter
+make_jump (__u16 code, __u32 k, __u8 jt, __u8 jf)
+{
+  sock_filter  f;
+  f.code = code;
+  f.jt = jt;
+  f.jf = jf;
+  f.k = k;
+  return f;
+}
+
+/*
+ * Return a filter that harvests packets with the specified ethertype.
+ */
+pktfilter *
+pktfilter::make_ethertype (unsigned short ethertype)
+{
+  static const int MAX_LEN = 20;
+  sock_filter  *inst = new sock_filter [MAX_LEN];
+  pktfilter    *pf = new pktfilter ();
+  
+  // nothing quite like coding in assembly without the benefit of an assembler 
;-)
+
+  // ignore packets that don't have the right ethertype
+
+  int i = 0;
+  inst[i++] = make_stmt (BPF_LD|BPF_H|BPF_ABS, 12);    // load ethertype
+  inst[i++] = make_jump (BPF_JMP|BPF_JEQ|BPF_K, ethertype, 1, 0);
+  inst[i++] = make_stmt (BPF_RET|BPF_K, 0);            // return 0 (ignore 
packet)
+  inst[i++] = make_stmt (BPF_RET|BPF_K, (unsigned) -1);        // return whole 
packet
+
+  assert (i <= MAX_LEN);
+
+  pf->d_inst = inst;
+  pf->d_len = i;
+
+  return pf;
+}
+
+/*
+ * Return a filter that harvests inbound packets with the specified ethertype.
+ * \param ethertype    the ethertype we're looking for
+ * \param our_mac      our ethernet MAC address so we can avoid pkts we sent
+ */
+pktfilter *
+pktfilter::make_ethertype_inbound (unsigned short ethertype, const unsigned 
char *our_mac)
+{
+  static const int MAX_LEN = 20;
+  sock_filter  *inst = new sock_filter [MAX_LEN];
+  pktfilter    *pf = new pktfilter ();
+  
+  __u16 smac_hi = (our_mac[0] << 8) | our_mac[1];
+  __u32 smac_lo = (our_mac[2] << 24) | (our_mac[3] << 16) | (our_mac[4] << 8) 
| our_mac[5];
+
+  // nothing quite like coding in assembly without the benefit of an assembler 
;-)
+
+  // ignore packets that have a different ethertype
+  // and packets that have a source mac address == our_mac (packets we sent)
+  
+  int i = 0;
+  inst[i++] = make_stmt (BPF_LD|BPF_H|BPF_ABS, 12);    // load ethertype
+  inst[i++] = make_jump (BPF_JMP|BPF_JEQ|BPF_K, ethertype, 0, 5);
+  inst[i++] = make_stmt (BPF_LD|BPF_W|BPF_ABS, 8);     // load low 32-bit of 
src mac
+  inst[i++] = make_jump (BPF_JMP|BPF_JEQ|BPF_K, smac_lo, 0, 2);
+  inst[i++] = make_stmt (BPF_LD|BPF_H|BPF_ABS, 6);     // load high 16-bits of 
src mac
+  inst[i++] = make_jump (BPF_JMP|BPF_JEQ|BPF_K, smac_hi, 1, 0);
+  inst[i++] = make_stmt (BPF_RET|BPF_K, (unsigned) -1);        // return whole 
packet
+  inst[i++] = make_stmt (BPF_RET|BPF_K, 0);            // return 0 (ignore 
packet)
+
+  assert (i <= MAX_LEN);
+
+  pf->d_inst = inst;
+  pf->d_len = i;
+
+  return pf;
+}

Added: usrp2/trunk/host-ng/lib/pktfilter.h
===================================================================
--- usrp2/trunk/host-ng/lib/pktfilter.h                         (rev 0)
+++ usrp2/trunk/host-ng/lib/pktfilter.h 2008-06-01 19:23:57 UTC (rev 8540)
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2007 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_USRP2_PKTFILTER_H
+#define INCLUDED_USRP2_PKTFILTER_H
+
+struct sock_filter;
+
+/*
+ * \brief Compile programs for the Berkeley Packet Filter
+ */
+class pktfilter {
+public:
+
+  unsigned              d_len;         // # of instructions
+  struct sock_filter   *d_inst;        // the instructions
+
+  pktfilter ();
+  ~pktfilter ();
+  
+  /*!
+   * \brief Return a filter that harvests packets with the specified ethertype.
+   * \param ethertype  the ethertype we're looking for.
+   */
+  static pktfilter *make_ethertype (unsigned short ethertype);
+
+  /*!
+   * \brief Return a filter that harvests inbound packets with the specified 
ethertype.
+   * \param ethertype  the ethertype we're looking for
+   * \param our_mac    our MAC address so we can avoid pkts we sent
+   */
+  static pktfilter *make_ethertype_inbound (unsigned short ethertype,
+                                               const unsigned char *our_mac);
+};
+
+#endif /* INCLUDED_USRP2_PKTFILTER_H */





reply via email to

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