From: Alessandro Vesely <vesely@tana.it>
To: nowhere <nowhere@hakkenden.ath.cx>
Cc: netfilter@vger.kernel.org
Subject: Re: NFQUEUE the plot is growing...
Date: Thu, 12 May 2011 20:03:25 +0200 [thread overview]
Message-ID: <4DCC20ED.4080203@tana.it> (raw)
In-Reply-To: <1305193207.9902.8.camel@compot-mob>
[-- Attachment #1: Type: text/plain, Size: 1720 bytes --]
On 12/May/11 11:40, nowhere wrote:
>> It seems enough to avoid delaying the call to nfq_set_verdict for the
>> first packet of a burst. For a shot in the dark, packets seem to get
>> lost if they arrive between the first one and the corresponding call
>> to nfq_set_verdict. Indeed, setting a fixed real_delay of 0.2, with
>> ping -i 0.2 it looses no packets, with ping -i 0.19 it looses just the
>> second one, with ping -i 0.09 icmp_reqs #2 and #3.
>>
>> No error is returned, whether NETLINK_NO_ENOBUFS is set or not.
>
> Well, seems like this is the case. If nfqueue becomes empty, first
> enqueued packet must not be delayed.
I retract, possibly I've been too hasty blaming nfnetlink queue. I
made a simple variation of nfqnl_test.c --which I attach. It just
accepts the previous packet id. The "last" packet is obviously always
lost. Because of this bug(?), I also loose the second packet of a
sequence of pings, no matter the speed.
However, if I "ping -c 1" using two terminal windows, I correctly
receive all odd ids in one window and even ones in the other (except
last pkt). In this case, I delay every packet. Also, if I run a
sequence from a window, and, immediately after it starts, run a single
ping using the other window, then both the single ping and the
sequence (except last pkt) go correctly through.
I don't understand how come the kernel+filter system can distinguish
between a second packet coming as part of a sequence and a second
packet coming asynchronously, given that packets are not inspected.
Nice puzzle, isn't it?
NB, I used iptables -t mangle -A POSTROUTING -p icmp -d 172.25.197.158
-j NFQUEUE --queue-num 13, as in
http://www.spinics.net/lists/netfilter/msg50829.html
[-- Attachment #2: main2.c --]
[-- Type: text/plain, Size: 3505 bytes --]
/*
$ ping -c 8 172.25.197.158
PING 172.25.197.158 (172.25.197.158) 56(84) bytes of data.
64 bytes from 172.25.197.158: icmp_req=1 ttl=128 time=1010 ms
64 bytes from 172.25.197.158: icmp_req=3 ttl=128 time=1000 ms
64 bytes from 172.25.197.158: icmp_req=4 ttl=128 time=1000 ms
64 bytes from 172.25.197.158: icmp_req=5 ttl=128 time=999 ms
64 bytes from 172.25.197.158: icmp_req=6 ttl=128 time=1000 ms
64 bytes from 172.25.197.158: icmp_req=7 ttl=128 time=1010 ms
--- 172.25.197.158 ping statistics ---
8 packets transmitted, 6 received, 25% packet loss, time 7020ms
rtt min/avg/max/mdev = 999.452/1003.574/1010.633/4.883 ms, pipe 2
# grep -E ^ *13 /proc/net/netfilter/nfnetlink_queue
13 13584 1 1 0 0 0 8 1
^queue_num,
^peer_pid,
^queue_total,
^copy_mode,
^copy_range,
^queue_dropped,
^queue_user_dropped,
^id_sequence,
^1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/netfilter.h> /* for NF_ACCEPT */
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <errno.h>
struct packet_data
{
u_int32_t id, good;
};
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nu,
struct nfq_data *nfa, void *data)
{
struct packet_data *pd = (struct packet_data*)data;
struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa);
if (pd && ph)
{
if (pd->good) // since last time
nfq_set_verdict(qh, pd->id, NF_ACCEPT, 0, NULL);
pd->id = ntohl(ph->packet_id);
pd->good = 1;
printf("received packet %d\n", pd->id);
}
return 0;
(void)nu;
}
int main()
{
struct nfq_handle *h;
struct nfq_q_handle *qh;
struct packet_data pd;
int fd;
int rv;
char buf[4096] __attribute__ ((aligned));
printf("opening library handle\n");
h = nfq_open();
if (!h) {
fprintf(stderr, "error during nfq_open()\n");
exit(1);
}
printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
if (nfq_unbind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_unbind_pf()\n");
exit(1);
}
printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
if (nfq_bind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_bind_pf()\n");
exit(1);
}
pd.good = 0;
qh = nfq_create_queue(h, 13 /* <--queue number here */, &cb, &pd);
if (!qh) {
fprintf(stderr, "error during nfq_create_queue()\n");
exit(1);
}
if (nfq_set_mode(qh, NFQNL_COPY_META, 0) < 0) {
fprintf(stderr, "can't set packet_copy mode\n");
exit(1);
}
fd = nfq_fd(h);
for (;;) {
if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
nfq_handle_packet(h, buf, rv);
continue;
}
/* if the computer is slower than the network the buffer
* may fill up. Depending on the application, this error
* may be ignored */
if (errno == ENOBUFS) {
printf("pkt lost!!\n");
continue;
}
printf("recv failed: errno=%d (%s)\n",
errno, strerror(errno));
}
printf("unbinding from queue 0\n");
nfq_destroy_queue(qh);
#ifdef INSANE
/* normally, applications SHOULD NOT issue this command, since
* it detaches other programs/sockets from AF_INET, too ! */
printf("unbinding from AF_INET\n");
nfq_unbind_pf(h, AF_INET);
#endif
printf("closing library handle\n");
nfq_close(h);
exit(0);
}
next prev parent reply other threads:[~2011-05-12 18:03 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-04 6:14 libnetfilter_queue question nowhere
2011-05-04 18:13 ` Alessandro Vesely
2011-05-04 18:32 ` Nikolay S.
2011-05-05 9:12 ` Alessandro Vesely
2011-05-05 9:24 ` nowhere
2011-05-11 17:27 ` NFQUEUE looses packets between arrival and verdict Alessandro Vesely
2011-05-11 22:56 ` Ed W
2011-05-12 9:40 ` nowhere
2011-05-12 18:03 ` Alessandro Vesely [this message]
2011-05-13 18:25 ` NFQUEUE the plot is growing Nikolay S.
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4DCC20ED.4080203@tana.it \
--to=vesely@tana.it \
--cc=netfilter@vger.kernel.org \
--cc=nowhere@hakkenden.ath.cx \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.