To/FromDevice patch for Solaris

David Scott Page page at cs.utexas.edu
Sun May 12 13:36:40 EDT 2002


Hi,

Enclosed is a patch to click.To/FromDevice that enables userlevel click
to operate on solaris-sparc.

On the FromDevice side, Solaris uses PCAP, and shares with the
existing FROMDEVICE_PCAP implementation.  On the ToDevice side,
Solaris is able to write to the PCAP (FromDevice) file, and can mostly
share implementation with the TODEVICE_LINUX implementation (which
also writes to its FromDevice file).

I also attempted to clean up the logic, including some changes to code
in the computation path for other platforms, which I have not tested.

Finally, there is a hack to fix an alignment problem on Sun machines
(look for __sparc in fromdevice.cc). You might have a more click-ish
way to fix it.

--
Scott Page

------------------------------------ 8< --------------------------------------
diff -Naur click-20020507/elements/userlevel/fromdevice.cc click-20020507a/elements/userlevel/fromdevice.cc
--- click-20020507/elements/userlevel/fromdevice.cc	Thu Apr 25 23:08:11 2002
+++ click-20020507a/elements/userlevel/fromdevice.cc	Sun May 12 16:49:45 2002
@@ -192,21 +192,21 @@
     return errh->error("%s", ebuf);
 
   // nonblocking I/O on the packet socket so we can poll
-  int fd = pcap_fileno(_pcap);
-  fcntl(fd, F_SETFL, O_NONBLOCK);
+  int pcap_fd = fd();
+  fcntl(pcap_fd, F_SETFL, O_NONBLOCK);
 
 #ifdef BIOCSSEESENT
   {
     int no = 0;
-    if (ioctl(fd, BIOCSSEESENT, &no) != 0)
+    if (ioctl(pcap_fd, BIOCSSEESENT, &no) != 0)
       return errh->error("FromDevice: BIOCSEESENT failed");
   }
 #endif
 
-#ifdef BIOCIMMEDIATE
+#if defined( BIOCIMMEDIATE ) && ! defined( __sun ) // pcap/bpf ioctl, not in DLPI/bufmod
   {
     int yes = 1;
-    if (ioctl(fd, BIOCIMMEDIATE, &yes) != 0)
+    if (ioctl(pcap_fd, BIOCIMMEDIATE, &yes) != 0)
       return errh->error("FromDevice: BIOCIMMEDIATE failed");
   }
 #endif
@@ -227,7 +227,7 @@
     return errh->error("%s: %s", ifname, pcap_geterr(_pcap));
   }
 
-  add_select(fd, SELECT_READ);
+  add_select(pcap_fd, SELECT_READ);
 
   _datalink = pcap_datalink(_pcap);
   if (_force_ip && !fake_pcap_dlt_force_ipable(_datalink))
@@ -262,20 +262,22 @@
 void
 FromDevice::cleanup(CleanupStage)
 {
-#if FROMDEVICE_PCAP
-  if (_pcap)
-    pcap_close(_pcap);
-  _pcap = 0;
-#endif
 #if FROMDEVICE_LINUX
-  if (_was_promisc >= 0)
-    set_promiscuous(_fd, _ifname, _was_promisc);
   if (_fd >= 0) {
-    close(_fd);
     remove_select(_fd, SELECT_READ);
+    if (_was_promisc >= 0)
+	set_promiscuous(_fd, _ifname, _was_promisc);
+    close(_fd);
     _fd = -1;
   }
 #endif
+#if FROMDEVICE_PCAP
+  if (_pcap) {
+      remove_select(fd(), SELECT_READ);
+      pcap_close(_pcap);
+      _pcap = 0;
+  }
+#endif
 }
 
 #if FROMDEVICE_PCAP
@@ -289,7 +291,24 @@
 
     FromDevice *fd = (FromDevice *) clientdata;
     int length = pkthdr->caplen;
+#if defined( __sparc )
+    // Packet::make(data,length) allocates new buffer to install
+    // DEFAULT_HEADROOM (28 bytes). Thus data winds up on a 4 byte
+    // boundary, irrespective of its original alignment. We assume we
+    // want a two byte offset from a four byte boundary (DLT_EN10B).
+    //
+    // Furthermore, note that pcap-dlpi on Solaris uses bufmod by
+    // default, hence while pcap-dlpi.pcap_read() is careful to load
+    // the initial read from the stream head into a buffer aligned
+    // appropriately for the network interface type, (I believe)
+    // subsequent packets in the batched read will be copied from the
+    // Stream's byte sequence into the pcap-dlpi user-level buffer at
+    // arbitrary alignments.
+    Packet *p = Packet::make( data - 2, length + 2 ) ;
+    p->pull(2); 
+#else
     Packet *p = Packet::make(data, length);
+#endif
 
     // set packet type annotation
     if (p->data()[0] & 1) {
diff -Naur click-20020507/elements/userlevel/fromdevice.hh click-20020507a/elements/userlevel/fromdevice.hh
--- click-20020507/elements/userlevel/fromdevice.hh	Thu Apr 25 23:08:11 2002
+++ click-20020507a/elements/userlevel/fromdevice.hh	Sun May 12 17:20:43 2002
@@ -114,11 +114,10 @@
   void add_handlers();
   
   String ifname() const			{ return _ifname; }
-#if FROMDEVICE_PCAP
-  pcap_t *pcap() const			{ return _pcap; }  
-#endif
 #if FROMDEVICE_LINUX
-  int fd() const			{ return _fd; }
+  int fd() const			{ return _fd; }	// for ToDevice initialize
+#elif FROMDEVICE_PCAP
+  int fd() const			{ return pcap_fileno(_pcap); }
 #endif
 
   void selected(int fd);
@@ -135,8 +134,7 @@
 #if FROMDEVICE_LINUX
   int _fd;
   unsigned char *_packetbuf;
-#endif
-#if FROMDEVICE_PCAP
+#elif FROMDEVICE_PCAP
   pcap_t* _pcap;
   friend void FromDevice_get_packet(u_char*, const struct pcap_pkthdr*,
 				    const u_char*);
diff -Naur click-20020507/elements/userlevel/todevice.cc click-20020507a/elements/userlevel/todevice.cc
--- click-20020507/elements/userlevel/todevice.cc	Fri May  3 14:50:37 2002
+++ click-20020507a/elements/userlevel/todevice.cc	Sun May 12 15:55:41 2002
@@ -51,9 +51,6 @@
   : Element(1, 0), _task(this), _fd(-1), _my_fd(false), _set_error_anno(false)
 {
   MOD_INC_USE_COUNT;
-#if TODEVICE_BSD_DEV_BPF
-  _pcap = 0;
-#endif
 }
 
 ToDevice::~ToDevice()
@@ -108,8 +105,9 @@
   ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = 0;
   if (ioctl(_fd, BIOCSETIF, (caddr_t)&ifr) < 0)
     return errh->error("BIOCSETIF %s failed", ifr.ifr_name);
+  _my_fd = true ;
 
-#elif TODEVICE_LINUX
+#elif TODEVICE_LINUX  || TODEVICE_PCAP
   
   // find a FromDevice and reuse its socket if possible
   for (int ei = 0; ei < router()->nelements() && _fd < 0; ei++) {
@@ -120,18 +118,17 @@
       _my_fd = false;
     }
   }
-
   if (_fd < 0) {
+# if TODEVICE_LINUX
     _fd = FromDevice::open_packet_socket(_ifname, errh);
     _my_fd = true;
+# else
+    return errh->error("ToDevice requires an initialized FromDevice on this platform") ;
+# endif
   }
-
   if (_fd < 0) return -1;
-
 #else
-  
   return errh->error("ToDevice is not supported on this platform");
-  
 #endif
 
   // check for duplicate writers
@@ -150,16 +147,10 @@
 void
 ToDevice::cleanup(CleanupStage)
 {
-#if TODEVICE_BSD_DEV_BPF
-  if (_pcap)
-    pcap_close(_pcap);
-  _pcap = 0;
-#endif
-#if TODEVICE_LINUX
+  // XXX: duplicate writers? (see above)
   if (_fd >= 0 && _my_fd)
     close(_fd);
   _fd = -1;
-#endif
 }
 
 void
@@ -177,7 +168,6 @@
 #else
   retval = 0;
 #endif
-
   if (retval < 0) {
     click_chatter("ToDevice(%s) %s: %s", _ifname.cc(), syscall, strerror(errno));
     if (_set_error_anno) {
@@ -195,7 +185,7 @@
 void
 ToDevice::push(int, Packet *p)
 {
-  assert(p->length() >= 14);
+  assert(p->length() >= 14);	// XXX: sizeof()?
   send_packet(p);
 }
 
diff -Naur click-20020507/elements/userlevel/todevice.hh click-20020507a/elements/userlevel/todevice.hh
--- click-20020507/elements/userlevel/todevice.hh	Fri May  3 14:50:37 2002
+++ click-20020507a/elements/userlevel/todevice.hh	Sun May 12 15:50:27 2002
@@ -59,6 +59,9 @@
 # if defined(__FreeBSD__) || defined(__OpenBSD__)
 #  define TODEVICE_BSD_DEV_BPF 1
 #  define TODEVICE_WRITE 1
+# elif defined( __sun )		// PCAP opens DLPI provider stream O_RDWR
+#  define TODEVICE_PCAP 1
+#  define TODEVICE_WRITE 1
 # endif
 #endif
 
@@ -105,11 +108,6 @@
   
   bool _set_error_anno;
 
-#if TODEVICE_BSD_DEV_BPF
-  pcap_t *_pcap;
-#endif
-
-  
 };
 
 #endif



More information about the click mailing list