summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-05-31 11:18:36 +0200
committerDaniel Borkmann <dborkman@redhat.com>2013-05-31 11:20:01 +0200
commit2f39b007d5382d01fc424e22b8e1a3681c2bc8cf (patch)
treeb2d7b6bec9932c6bbfec6af8aa016cbd372adf72
parented4e3c64dc80bb775f9ecfdd2165297e34e2fb0c (diff)
ring: implement setup of tpacket v3 ring
Implement ring setup routines and structures for TPACKET_V3. Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
-rw-r--r--ring.h18
-rw-r--r--ring_rx.c10
-rw-r--r--ring_rx.h5
3 files changed, 30 insertions, 3 deletions
diff --git a/ring.h b/ring.h
index f618a35..7590223 100644
--- a/ring.h
+++ b/ring.h
@@ -45,6 +45,7 @@ struct ring {
union {
struct tpacket_req layout;
struct tpacket_req3 layout3;
+ uint8_t raw;
};
};
@@ -113,6 +114,18 @@ static inline void __set_sockopt_tpacket(int sock, int val)
panic("Cannot set tpacketv2!\n");
}
+static inline int __get_sockopt_tpacket(int sock)
+{
+ int val, ret;
+ socklen_t len = sizeof(val);
+
+ ret = getsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, &len);
+ if (ret)
+ panic("Cannot set tpacketv2!\n");
+
+ return val;
+}
+
static inline void set_sockopt_tpacket_v2(int sock)
{
__set_sockopt_tpacket(sock, TPACKET_V2);
@@ -123,4 +136,9 @@ static inline void set_sockopt_tpacket_v3(int sock)
__set_sockopt_tpacket(sock, TPACKET_V3);
}
+static inline int get_sockopt_tpacket(int sock)
+{
+ return __get_sockopt_tpacket(sock);
+}
+
#endif /* RING_H */
diff --git a/ring_rx.c b/ring_rx.c
index fc735cc..a3d8e4d 100644
--- a/ring_rx.c
+++ b/ring_rx.c
@@ -57,6 +57,10 @@ void setup_rx_ring_layout(int sock, struct ring *ring, unsigned int size,
sizeof(struct tpacket_req) !=
offsetof(struct tpacket_req3, tp_retire_blk_tov));
+ ring->layout3.tp_retire_blk_tov = 0;
+ ring->layout3.tp_sizeof_priv = 0;
+ ring->layout3.tp_feature_req_word = 0;
+
set_sockopt_tpacket_v3(sock);
} else {
set_sockopt_tpacket_v2(sock);
@@ -68,10 +72,11 @@ void setup_rx_ring_layout(int sock, struct ring *ring, unsigned int size,
void create_rx_ring(int sock, struct ring *ring, int verbose)
{
int ret;
+ bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
retry:
- ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->layout,
- sizeof(ring->layout));
+ ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->raw,
+ v3 ? sizeof(ring->layout3) : sizeof(ring->layout));
if (errno == ENOMEM && ring->layout.tp_block_nr > 1) {
ring->layout.tp_block_nr >>= 1;
ring->layout.tp_frame_nr = ring->layout.tp_block_size /
@@ -79,7 +84,6 @@ retry:
ring->layout.tp_block_nr;
goto retry;
}
-
if (ret < 0)
panic("Cannot allocate RX_RING!\n");
diff --git a/ring_rx.h b/ring_rx.h
index b1114a6..0a2701f 100644
--- a/ring_rx.h
+++ b/ring_rx.h
@@ -23,6 +23,11 @@ static inline int user_may_pull_from_rx(struct tpacket2_hdr *hdr)
return ((hdr->tp_status & TP_STATUS_USER) == TP_STATUS_USER);
}
+static inline int user_may_pull_from_rx_block(struct block_desc *pbd)
+{
+ return ((pbd->h1.block_status & TP_STATUS_USER) == TP_STATUS_USER);
+}
+
static inline void kernel_may_pull_from_rx(struct tpacket2_hdr *hdr)
{
hdr->tp_status = TP_STATUS_KERNEL;