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.
next prev 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).