summaryrefslogtreecommitdiff
path: root/ring.h
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
committerDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
commit1a9fbac03c684f29cff9ac44875bd9504a89f54e (patch)
tree1b2e40dbe5dc1899ef5b62c4325c9b94c9c450fc /ring.h
all: import netsniff-ng 0.5.8-rc0 source
We decided to get rid of the old Git history and start a new one for several reasons: *) Allow / enforce only high-quality commits (which was not the case for many commits in the history), have a policy that is more close to the one from the Linux kernel. With high quality commits, we mean code that is logically split into commits and commit messages that are signed-off and have a proper subject and message body. We do not allow automatic Github merges anymore, since they are total bullshit. However, we will either cherry-pick your patches or pull them manually. *) The old archive was about ~27MB for no particular good reason. This basically derived from the bad decision that also some PDF files where stored there. From this moment onwards, no binary objects are allowed to be stored in this repository anymore. The old archive is not wiped away from the Internet. You will still be able to find it, e.g. on git.cryptoism.org etc. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Diffstat (limited to 'ring.h')
-rw-r--r--ring.h174
1 files changed, 174 insertions, 0 deletions
diff --git a/ring.h b/ring.h
new file mode 100644
index 0000000..75f4d26
--- /dev/null
+++ b/ring.h
@@ -0,0 +1,174 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Copyright 2009, 2010 Daniel Borkmann.
+ * Subject to the GPL, version 2.
+ */
+
+#ifndef RING_H
+#define RING_H
+
+/*
+ * "I love the smell of 10GbE in the morning. Smells like ... victory."
+ * - W. Richard Stevens, "Secret Teachings of the UNIX Environment"
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <linux/if_packet.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <poll.h>
+#include <sys/poll.h>
+
+#include "xutils.h"
+#include "built_in.h"
+#include "die.h"
+
+#ifndef PACKET_FANOUT
+# define PACKET_FANOUT 18
+# define PACKET_FANOUT_POLICY_HASH 0
+# define PACKET_FANOUT_POLICY_LB 1
+# define PACKET_FANOUT_POLICY_DEFAULT PACKET_FANOUT_HASH
+#endif
+
+struct frame_map {
+ struct tpacket2_hdr tp_h __aligned_tpacket;
+ struct sockaddr_ll s_ll __align_tpacket(sizeof(struct tpacket2_hdr));
+};
+
+struct ring {
+ struct iovec *frames;
+ uint8_t *mm_space;
+ size_t mm_len;
+ struct tpacket_req layout;
+ struct sockaddr_ll s_ll;
+};
+
+static inline void next_rnd_slot(unsigned int *it, struct ring *ring)
+{
+ *it = rand() % ring->layout.tp_frame_nr;
+}
+
+#define RING_SIZE_FALLBACK (1 << 26)
+
+static inline unsigned int ring_size(char *ifname, unsigned int size)
+{
+ if (size > 0)
+ return size;
+
+ /*
+ * Device bitrate in bytes times two as ring size.
+ * Fallback => ~ 64,00 MB
+ * 10 MBit => ~ 2,38 MB
+ * 54 MBit => ~ 12,88 MB
+ * 100 MBit => ~ 23,84 MB
+ * 300 MBit => ~ 71,52 MB
+ * 1.000 MBit => ~ 238,42 MB
+ * 10.000 MBit => ~ 2.384.18 MB
+ */
+ size = device_bitrate(ifname);
+ size = (size * 1000000) / 8;
+ size = size * 2;
+ if (size == 0)
+ size = RING_SIZE_FALLBACK;
+
+ return round_up_cacheline(size);
+}
+
+static inline unsigned int ring_frame_size(struct ring *ring)
+{
+ return ring->layout.tp_frame_size;
+}
+
+static inline void tpacket_hdr_clone(struct tpacket2_hdr *thdrd,
+ struct tpacket2_hdr *thdrs)
+{
+ thdrd->tp_sec = thdrs->tp_sec;
+ thdrd->tp_nsec = thdrs->tp_nsec;
+ thdrd->tp_snaplen = thdrs->tp_snaplen;
+ thdrd->tp_len = thdrs->tp_len;
+}
+
+#ifndef POLLRDNORM
+# define POLLRDNORM 0x0040
+#endif
+#ifndef POLLWRNORM
+# define POLLWRNORM 0x0100
+#endif
+#ifndef POLLRDHUP
+# define POLLRDHUP 0x2000
+#endif
+
+#define POLL_NEXT_PKT 0
+#define POLL_MOVE_OUT 1
+
+static inline void prepare_polling(int sock, struct pollfd *pfd)
+{
+ memset(pfd, 0, sizeof(*pfd));
+ pfd->fd = sock;
+ pfd->revents = 0;
+ pfd->events = POLLIN | POLLRDNORM | POLLERR;
+}
+
+static inline void set_sockopt_fanout(int sock, unsigned int fanout_id,
+ unsigned int fanout_type)
+{
+ unsigned int fanout_arg = (fanout_id | (fanout_type << 16));
+ int ret = setsockopt(sock, SOL_PACKET, PACKET_FANOUT, &fanout_arg,
+ sizeof(fanout_arg));
+ if (ret)
+ panic("No packet fanout support!\n");
+}
+
+static inline void set_sockopt_tpacket(int sock)
+{
+ int ret, val = TPACKET_V2;
+
+ ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
+ if (ret)
+ panic("Cannot set tpacketv2!\n");
+}
+
+#ifdef __WITH_HARDWARE_TIMESTAMPING
+# include <linux/net_tstamp.h>
+
+static inline void set_sockopt_hwtimestamp(int sock, const char *dev)
+{
+ int timesource, ret;
+ struct hwtstamp_config hwconfig;
+ struct ifreq ifr;
+
+ if (!strncmp("any", dev, strlen("any")))
+ return;
+
+ memset(&hwconfig, 0, sizeof(hwconfig));
+ hwconfig.tx_type = HWTSTAMP_TX_ON;
+ hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
+ ifr.ifr_data = &hwconfig;
+
+ ret = ioctl(sock, SIOCSHWTSTAMP, &ifr);
+ if (ret < 0) {
+ if (errno == EOPNOTSUPP)
+ return;
+ panic("Cannot set timestamping: %s\n", strerror(errno));
+ }
+
+ timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ ret = setsockopt(sock, SOL_PACKET, PACKET_TIMESTAMP, &timesource,
+ sizeof(timesource));
+ if (ret)
+ panic("Cannot set timestamping: %s!\n", strerror(errno));
+}
+#else
+static inline void set_sockopt_hwtimestamp(int sock, const char *dev)
+{
+ return;
+}
+#endif
+#endif /* RING_H */