netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: Jan Engelhardt <jengelh@computergmbh.de>
Cc: Netfilter Developer Mailing List <netfilter-devel@lists.netfilter.org>
Subject: Re: xt_time 20070915
Date: Tue, 18 Sep 2007 11:53:57 +0200	[thread overview]
Message-ID: <46EFA035.6060409@trash.net> (raw)
In-Reply-To: <Pine.LNX.4.64.0709171616070.4516@fbirervta.pbzchgretzou.qr>

Jan Engelhardt wrote:
> On Sep 17 2007 15:54, Patrick McHardy wrote:
> 
>>>+++ linux-2.6.23/include/linux/netfilter/xt_time.h
>>>@@ -0,0 +1,13 @@
>>>+#ifndef _XT_TIME_H
>>>+#define _XT_TIME_H 1
>>>+
>>>+struct xt_time_info {
>>>+	time_t date_start;
>>>+	time_t date_stop;
>>
>>This is an arch-dependant type and must not be used within the
>>iptables ABI.
> 
> 
> So what would you suggest? time_t will only work for 30 more years,
> then we'll have to change it. So what is your pick for ABI-complete
> time_t, uint64 or uint32?


Both is fine, I intend to replace the interface by something netlink
based before 30 years are gone :) But if you want to be safe, use an
aligned_u64.

>>>+	u_int32_t monthdays_match;
>>>+	u_int16_t time_start;
>>>+	u_int16_t time_stop;
>>>+	u_int8_t weekdays_match;
>>
>>No inversion?
> 
> 
> Inversion is a funny thing with xt_time because (almost) all possible
> times are _finite_.
> 
> Consider xt_connlimit and --connlimit x. The set of possible values
> for x is infinite (assuming we were not limited by 32/64-bit CPUs).
> 
> Along comes xt_time. The set of possible values for --weekdays
> is finite, there are exactly seven days for any given week. Since
> this is the case, the negation of any set/bitmap of weekdays can
> again be represented as a bitmap. So the inversion is done in
> libxt_time.c (iptables).  !(Fri..Sun) == (Mon..Thu)
> 
> The same applies to time_start. Got a noon match that matches
> from 10:00 to 15:00? Its inversion is (simply put) 15:00 to
> 10:00.


Mhh .. but do we have to handle this in the kernel? Instead
of:

+	if (info->time_start < info->time_stop) {
+		...
+	} else {
+		...
+	}

you could switch the times in userspace and use inversion.
But its not important, if you prefer this way thats also
fine with me.

>>Some explanation what the above is doing would be appreciated.
> 
> 
> /*
>  * Each network packet has a (nano)seconds-since-the-epoch (SSTE) timestamp.
>  * Since we match against days and daytime, the SSTE value needs to be
>  * computed back into human-readable dates.
>  */
> static void localtime(struct xtm *r, time_t time)
> {
> 	unsigned int year, i, w;
> 
> 	time -= 60 * sys_tz.tz_minuteswest;
> 
> 	/* Each day has 86400s, so finding the hour/minute is actually easy. */
> 	w  = time % 86400;
> 	w /= 60;
> 	r->minute = w % 60;
> 	r->hour   = w / 60;
> 
> 	/*
> 	 * Here comes the rest (weekday, monthday). First, divide the SSTE
> 	 * by seconds-per-day to get the number of _days_ since the epoch.
> 	 */
> 	w = time / 86400;
> 
> 	/* 1970-01-01 (w=0) was a Thursday (4). */
> 	r->weekday = (4 + w) % 7;
> 
> 	/*
> 	 * In each year, a certain number of days-since-the-epoch have passed.
> 	 * Find the year that is closest to said days.
> 	 *
> 	 * Consider, for example, w=21612 (2029-03-04). Loop will abort on
> 	 * dse[i] <= w, which happens when dse[i] == 21550. This implies
> 	 * year == 2009. w will then be 62.
> 	 */
> 	for (i = 0, year = DSE_FIRST; days_since_epoch[i] > w;
> 	    ++i, --year)
> 		/* just loop */;
> 
> 	w -= days_since_epoch[i];
> 
> 	/*
> 	 * By now we have the current year, and the day of the year.
> 	 * r->yearday = w;
> 	 *
> 	 * On to finding the month (like above). In each month, a certain
> 	 * number of days-since-New Year have passed, and find the closest
> 	 * one.
> 	 *
> 	 * Consider w=62 (in a non-leap year). Loop will abort on
> 	 * dsy[i] < w, which happens when dsy[i] == 31+28 (i == 2).
> 	 * Concludes i == 2, i.e. 3rd month => March.
> 	 *
> 	 * (A different approach to use would be to subtract a monthlength
> 	 * from w repeatedly while counting.)
> 	 */
> 	if (is_leap(year)) {
> 		for (i = ARRAY_SIZE(days_since_leapyear) - 1;
> 		    i > 0 && days_since_year[i] > w; --i)
> 			/* just loop */;
> 	} else {
> 		for (i = ARRAY_SIZE(days_since_year) - 1;
> 		    i > 0 && days_since_year[i] > w; --i)
> 			/* just loop */;
> 	}
> 
> 	r->month    = i + 1;
> 	r->monthday = w - days_since_year[i] + 1;
> 	return;
> }


All of this looks pretty complicated/expansive. I wonder whether
we could omit a few of these calculations (like day, month, ..)
if the user isn't matching on them.

>>>+	s64 stamp;
>>>+
>>>+	if (skb->tstamp.tv64 == 0)
>>>+		__net_timestamp((struct sk_buff *)skb);
>>>+
>>>+	stamp = skb->tstamp.tv64;
>>>+	do_div(stamp, NSEC_PER_SEC);
>>
>>Would get_seconds() work?
> 
> 
> One might think so, but there is a race involved, for example:
> 
> [16:59:59.100000 || 1190041199.100000]
> 
> 	network code stamps the packet, with 1190040556 (we will
> 	ignore the subsecond part since xt_time does not deal with
> 	it.)
> 
> [16:59:59.200000 || 1190041199.200000]
> 
> 	It may happen that the network code, or some iptables code,
> 	or whatever other code takes time. Assume the user added an
> 	xt_complex_match.ko which takes _at least_ that many jiffies
> 	until the next second.
> 
> [17:00:00.000000 || 1190041200.000000]
> 
> 	Now it's 17:00. But the packet stamp still is 16:59:59.
> 	Consider the user had a
> 
> 	-m time --timestart 15:00 --timestop 17:00
> 
> Now what? Further consider the following hypothetical case where we
> inflate the times to show the problem -- since xt_time has only
> minute resolution:
> 
> The user has a multi-core (#Cores >= 2) machine, and xt_complex_match
> takes "a lot of time", say, 3 minutes per packet. It may sound
> unrealistic, but shows the point. Then xt_time entrance would be at
> 17:03, __way__ after the packet actually arrived at the box, and way
> after the 17:00 time boundary that was set.
> 
> Conclusion: It is not really a race, it just depends on what you
> measure time relative against, i.e. whether xt_time is relative to
> the packet timestamp or the actual processing {point in time}.


As a user I would expect that it uses the point in time at which
the packet is processed.

>>>+static bool xt_time_check(const char *tablename, const void *ip,
>>>+                          const struct xt_match *match, void *matchinfo,
>>>+                          unsigned int hook_mask)
>>>+{
>>>+	struct xt_time_info *info = matchinfo;
>>>+
>>>+	/* xt_time's granularity is a minute, hence 24*60 = 1day */
>>>+	if (info->time_start > 24 * 60 || info->time_stop >= 24 * 60) {
>>>+		printk(KERN_WARNING "ipt_time: invalid argument - start or stop time greater than 23:59h\n");
>>>+		return false;
>>>+	}
>>
>>Is there a reason for minute granularity? The data types look large
>>enough for at least second granularity (more is probably useless).
> 
> 
> Yeah I can do that. Not that I see a real benefit for the user ;^) to
> match on sub-minute times. ("Help me, my internet only works for 30
> seconds for each minute!") The more I think about it, it might be a
> really evil way to shape traffic (ha!)


Well, me neither, but if its no trouble, we can let the user
decide whether its useful or not.

  parent reply	other threads:[~2007-09-18  9:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-15 16:07 xt_time 20070915 Jan Engelhardt
2007-09-15 17:41 ` xt_time 20070915 (iptables) Jan Engelhardt
2007-09-17 13:54 ` xt_time 20070915 Patrick McHardy
2007-09-17 15:01   ` Jan Engelhardt
2007-09-17 15:13     ` Jan Engelhardt
2007-09-18  9:53     ` Patrick McHardy [this message]
2007-09-18 11:42       ` mirq-linux
2007-09-19 14:32       ` Jan Engelhardt
  -- strict thread matches above, loose matches on Subject: below --
2007-09-17 17:57 Jan Engelhardt
2007-09-17 17:57 Jan Engelhardt

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=46EFA035.6060409@trash.net \
    --to=kaber@trash.net \
    --cc=jengelh@computergmbh.de \
    --cc=netfilter-devel@lists.netfilter.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).