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