* netdev-2.6.git updated, ipw wireless drivers merged
From: Jeff Garzik @ 2005-05-28 2:13 UTC (permalink / raw)
To: Netdev; +Cc: James Ketrenos, Andrew Morton, Linux Kernel
The ipw 2100/2200 wireless drivers were merged into the netdev-2.6.git
repository, under the 'we18-ieee80211' branch.
There is also the we18-ieee80211-wifi branch, which lumps HostAP on top
of that.
(if you need info on git, read http://lkml.org/lkml/2005/5/26/11)
Also, Andrew: I fixed that compilation error you mentioned a week or so
ago.
^ permalink raw reply
* Re: PATCH: rtnetlink explicit flags setting
From: jamal @ 2005-05-28 1:48 UTC (permalink / raw)
To: Thomas Graf; +Cc: David S. Miller, netdev
In-Reply-To: <20050528012810.GN15391@postel.suug.ch>
On Sat, 2005-28-05 at 03:28 +0200, Thomas Graf wrote:
> * jamal <1117242749.6251.15.camel@localhost.localdomain> 2005-05-27 21:12
> > > Yet unconverted
> > > are: netfilter, net/sched/ tcp_diag, xfrm, kernel/audit.
> > >
> >
> > I didnt find any issues with these as far as PID extrapolation.
>
> I should have written, yet unchecked.
>
I did check netfilter, net/sched/ tcp_diag, xfrm and they do things
right.
> > > Do not apply these patches yet, they're way too intrusive
> >
> > Do you mean the two patches? Those looked fine to me;
>
> Yes, those two patches. My part comes directly out of my fingers
> and is only compile tested. I didn't even run them yet.
>
Hrm - you should probably have said that in the patch text ;->
I did test the one i sent - basic things and by code inspection saw
little risk as well. Perhaps we should push mine then you can add on top
of it.
> > i.e its mostly the patch i posted this morning with the new Macros, no?
>
> I went through all users of NLMSG_PUT in the modules you touched and
> checked if they properly set NLM_F_MULTI and used the new macro when
> appropriate.
>
> Anyways, I want to be careful with this, there might be userspace
> apps which rely on pid being filled in from siocb->scm->creds or
> userspace apps which don't expect the NLM_F_MULTI flag even when
> they should so we should check with all parties involved.
>
I dont see any issues with my original patch or for that matter yours
except for now that you are saying you havent compiled it even ;->.
All dumps MUST set NLM_F_MULTI - thats the main change really.
All non-dump paths may set NLM_F_MULTI, and from that angle, if theres
any bugs in the old code they are maintained ;->
So how about we push my original patch instead?
cheers,
jamal
^ permalink raw reply
* Re: [PATCH 3/4] [NEIGH] neighbour table configuration and statistics via rtnetlink
From: jamal @ 2005-05-28 1:42 UTC (permalink / raw)
To: Thomas Graf; +Cc: David S. Miller, netdev
In-Reply-To: <20050527163516.GB15391@postel.suug.ch>
On Fri, 2005-27-05 at 18:35 +0200, Thomas Graf wrote:
> I do NOT agree on moving gc_ into this architecture as well,
> it doesn't belong there.
Well, you do realize they are part of the in_dev ? ;->
> Nitpicking for a bit, although inet6_dev and in_device hold
> reference to the their arp respectively ndisc parameter set,
> the sysctl interface does not use this reference but stores
> the ifindex of the netdevice, _which_ is correct I think
> because parameter sets are _not_ limited to inetdevs in terms
> of architecture but only in terms of current use.
>
I see a little main service header with ifindex always no different than
IFA or IFLINK etc followed by appropriate TLVs which are nested.
Unfortunately i still cant find the patch - i started with a different
approach; my immediate interest was to get events when someone made
in_device changes. BTW, this is going to be one of the main challenges
since there are many paths to configure these things.
> > The deafult can be overriden by devX. So they dont need to sync.
> > But this is a separate topic
>
> I was not talking about in-sync but rather that gc_* only
> appears in default/ but not in devX/. What I expect is that
> every default parameter can be overwritten in devX which
> is not true for gc_*. Which is the reason why I implemented
> them outside of the NDTPA_PARMS nested TLV.
>
Well, if you look at the structure there is no reason they should really
be separate; infact theres a comment:
-----------
struct neigh_parms parms;
/* HACK. gc_* shoul follow parms without a gap! */
int gc_interval;
int gc_thresh1;
int gc_thresh2;
----------
To me the abstraction is pretty clear. I would agree that the way
parameters configurable from user space and some of the methods may not
be the best in terms of neighbor tables organization.
> I understand your architecture and if we follow this thought
> we'd have a "default" netdevice which repesents all default
> settings.
>From looking at the code, the default stuff seems to be "hardcoded".
Example in the definition arp_tbl.
> I do agree with this architecture but the problematic
> question remains: Do we want parameters in "default" which are
> not available in devX? I think this question is what it gets
> down to in the end. If we say, yes we do want this, then we
> can implement all generic settings, such as tcp_, using this
> scheme as well. I don't disagree with this completely but I
> find it not very intuitive from a user perspective.
The model like i said is clean. There are some issues i have qualms with
- such as IP address arrangements and tight integration with netdevices
- but those can addressed at a later time.
cheers,
jamal
^ permalink raw reply
* Re: PATCH: rtnetlink explicit flags setting
From: Thomas Graf @ 2005-05-28 1:28 UTC (permalink / raw)
To: jamal; +Cc: David S. Miller, netdev
In-Reply-To: <1117242749.6251.15.camel@localhost.localdomain>
* jamal <1117242749.6251.15.camel@localhost.localdomain> 2005-05-27 21:12
> > Yet unconverted
> > are: netfilter, net/sched/ tcp_diag, xfrm, kernel/audit.
> >
>
> I didnt find any issues with these as far as PID extrapolation.
I should have written, yet unchecked.
> > I also fixed some uses of NL_CREDS() to fetch the pid for
> > message generation which is wrong. Various dumping procedures
> > did not set the multi flag at all, I fixed all of them.
> >
> > Do not apply these patches yet, they're way too intrusive
>
> Do you mean the two patches? Those looked fine to me;
Yes, those two patches. My part comes directly out of my fingers
and is only compile tested. I didn't even run them yet.
> i.e its mostly the patch i posted this morning with the new Macros, no?
I went through all users of NLMSG_PUT in the modules you touched and
checked if they properly set NLM_F_MULTI and used the new macro when
appropriate.
Anyways, I want to be careful with this, there might be userspace
apps which rely on pid being filled in from siocb->scm->creds or
userspace apps which don't expect the NLM_F_MULTI flag even when
they should so we should check with all parties involved.
^ permalink raw reply
* Re: PATCH: rtnetlink explicit flags setting
From: jamal @ 2005-05-28 1:12 UTC (permalink / raw)
To: Thomas Graf; +Cc: David S. Miller, netdev
In-Reply-To: <20050527165935.GC15391@postel.suug.ch>
On Fri, 2005-27-05 at 18:59 +0200, Thomas Graf wrote:
> I took your patch, converted it to use NLMSG_NEW and finished
> converting all the modules that you started.
Thats the patchset 1/2 and 2/2, correct?
> Yet unconverted
> are: netfilter, net/sched/ tcp_diag, xfrm, kernel/audit.
>
I didnt find any issues with these as far as PID extrapolation.
> I also fixed some uses of NL_CREDS() to fetch the pid for
> message generation which is wrong. Various dumping procedures
> did not set the multi flag at all, I fixed all of them.
>
> Do not apply these patches yet, they're way too intrusive
Do you mean the two patches? Those looked fine to me;
i.e its mostly the patch i posted this morning with the new Macros, no?
cheers,
jamal
^ permalink raw reply
* Re: [PATCH 2/2] [NETLINK] Correctly set NLM_F_MULTI without checking the pid
From: jamal @ 2005-05-28 1:06 UTC (permalink / raw)
To: Thomas Graf; +Cc: David S. Miller, netdev
In-Reply-To: <20050527170135.GE15391@postel.suug.ch>
Ok, looks good. Dave please apply this one instead of the one i posted
this morning - it incorporates the name change as well.
Incase its not clear - 1/2 in this patch set is also fine.
cheers,
jamal
On Fri, 2005-27-05 at 19:01 +0200, Thomas Graf wrote:
> This patch rectifies some rtnetlink message builders that derive the
> flags from the pid. It is now explicit like the other cases
> which get it right. Also fixes half a dozen dumpers which did not
> set NLM_F_MULTI at all.
>
> Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
> Signed-off-by: Thomas Graf <tgraf@suug.ch>
>
^ permalink raw reply
* Re: RFC: NAPI packet weighting patch
From: jamal @ 2005-05-28 0:56 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Mitch Williams, netdev, Robert.Olsson, Ronciak, John,
Venkatesan, Ganesh, Brandeburg, Jesse
In-Reply-To: <20050527140132.1435132d@dxpl.pdx.osdl.net>
On Fri, 2005-27-05 at 14:01 -0700, Stephen Hemminger wrote:
>
> Why not just allow adjusting dev->weight via sysfs?
I think that should be good enough - and i thought your patch already
did this.
Adding a shift to the weight in a _weighted_ RR algorithm does sound
odd.
cheers,
jamal
^ permalink raw reply
* Re: [IPSEC] Add XFRMA_SA/XFRMA_POLICY for delete notification
From: jamal @ 2005-05-28 0:30 UTC (permalink / raw)
To: Herbert Xu; +Cc: David S. Miller, Patrick McHardy, netdev
In-Reply-To: <20050527233741.GA9157@gondor.apana.org.au>
On Sat, 2005-28-05 at 09:37 +1000, Herbert Xu wrote:
> Hi Dave:
>
> This is the patch that I reverted due to Jamal's objection to it.
> I still think it's the right way to go which is why I'm submitting
> it. As it is, all the xfrm event notifications sent by the kernel
> except the ones for SA/policy deletion are symmetric in the sense
> that if they were sent straight back to the kernel in that same
> form they would be accepted and perform the same action that
> triggered the initial events. As far as I know this is true for
> non-xfrm netlink notifications as well, including deletion events.
>
I have no objection to this patch going forth. I think i have
sufficiently expressed my dislike - but we gotta make progress;->
cheers,
jamal
^ permalink raw reply
* Re: [0/10] [IPSEC] IPsec event notification
From: Herbert Xu @ 2005-05-28 0:10 UTC (permalink / raw)
To: David S. Miller; +Cc: hadi, kaber, netdev
In-Reply-To: <20050527.134139.32345929.davem@davemloft.net>
On Fri, May 27, 2005 at 01:41:39PM -0700, David S. Miller wrote:
>
> Pulled, thanks Herbert.
Thanks Dave. Any objections to asking Andrew to start pulling your
net-2.6.13 tree or is he doing that already?
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH] r8169: support restricting speed+duplex in autonegotiation
From: Ben Greear @ 2005-05-27 23:59 UTC (permalink / raw)
To: Richard Dawe; +Cc: Francois Romieu, Linux netdev
In-Reply-To: <4297A0F7.5070209@phekda.gotadsl.co.uk>
Richard Dawe wrote:
> Hello.
>
> Attached is a patch for drivers/net/r8169.c against Linux 2.6.11 that
> allows adjustment of the speed and duplex advertised via
> autonegotiation. Example usage:
>
> ethtool -s eth0 autoneg on speed 10 duplex half
>
> Also attached is a test script which tries various combinations of
> autoneg, speed and duplex. There is also a log of the test run attache.d
> While the test ran I had an ssh session running "while true; do sleep 1;
> date; done". The ssh session did not drop. Note that I don't have GigE,
> so that part of the test was bogus.
>
> I also tried various speed tests, to check that the speed and duplex
> were actually changed. They were.
>
> Bye, Rich
>
> r8169: Allow adjustment of speed and duplex advertised via autonegotiation
>
> Signed-off-by: Richard Dawe <rich@phekda.gotadsl.co.uk>
>
>
> ------------------------------------------------------------------------
>
> --- r8169.c.orig 2005-05-27 21:12:21.000000000 +0100
> +++ r8169.c 2005-05-27 22:14:59.000000000 +0100
> @@ -407,7 +407,9 @@ struct rtl8169_private {
> #ifdef CONFIG_R8169_VLAN
> struct vlan_group *vlgrp;
> #endif
> - int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
> + int (*set_speed)(struct net_device *,
> + u8 autoneg, u16 speed, u8 duplex,
> + u32 advertising);
> void (*get_settings)(struct net_device *, struct ethtool_cmd *);
> void (*phy_reset_enable)(void __iomem *);
> unsigned int (*phy_reset_pending)(void __iomem *);
> @@ -549,7 +551,9 @@ static void rtl8169_check_link_status(st
> spin_unlock_irqrestore(&tp->lock, flags);
> }
>
> -static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
> +static void rtl8169_link_option(int idx,
> + u8 *autoneg, u16 *speed, u8 *duplex,
> + u32 *advertising)
> {
> struct {
> u16 speed;
> @@ -579,6 +583,23 @@ static void rtl8169_link_option(int idx,
> *autoneg = p->autoneg;
> *speed = p->speed;
> *duplex = p->duplex;
> +
> + if (p->media == _10_Half)
> + *advertising = ADVERTISED_10baseT_Half;
> + if (p->media == _10_Full)
> + *advertising = ADVERTISED_10baseT_Full;
> + if (p->media == _100_Half)
> + *advertising = ADVERTISED_100baseT_Half;
> + if (p->media == _100_Full)
> + *advertising = ADVERTISED_100baseT_Full;
> + if (p->media == _1000_Full)
> + *advertising = ADVERTISED_1000baseT_Full;
> + if (p->media == 0xff)
> + *advertising = ADVERTISED_10baseT_Half |
> + ADVERTISED_10baseT_Full |
> + ADVERTISED_100baseT_Half |
> + ADVERTISED_100baseT_Full |
> + ADVERTISED_1000baseT_Full;
> }
So, is there no way to advert just 100Mbps-half and -full ?
Seems like you should be able to set each flag by itself and
create a bit-mask of the particular flags that you want...
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [IPSEC] Add XFRMA_SA/XFRMA_POLICY for delete notification
From: Herbert Xu @ 2005-05-27 23:37 UTC (permalink / raw)
To: David S. Miller, jamal, Patrick McHardy, netdev
[-- Attachment #1: Type: text/plain, Size: 2351 bytes --]
Hi Dave:
This is the patch that I reverted due to Jamal's objection to it.
I still think it's the right way to go which is why I'm submitting
it. As it is, all the xfrm event notifications sent by the kernel
except the ones for SA/policy deletion are symmetric in the sense
that if they were sent straight back to the kernel in that same
form they would be accepted and perform the same action that
triggered the initial events. As far as I know this is true for
non-xfrm netlink notifications as well, including deletion events.
What is different between xfrm and and other netlink notifications
is that requests such as route/address deletion use the same format
as route/address addition, while the SA/policy deletion format is
certainly not the same as SA/policy addition.
Based on these observations, I think we should change the IPsec
deletion notifications to use the same format as the IPsec deletion
requests that triggered them in the first place. Of course, we
can do this in a way without losing information such as the SA/policy
that was actually deleted.
The objection to this change is that it creates an inconsistency
between xfrm deletion and non-xfrm deletion event formats. However,
my view is that this is an inconsistency that is already present
between xfrm deleteion and non-xfrm deletion request formats. By
doing this we in fact improve the consistency in the sense that all
netlink event notifications, xfrm or non-xfrm are now of the same
format as their corresponding requests.
One thing to note is that whatever we decide here we'll probably be
stuck with it for a long time since this is part of the xfrm netlink
ABI.
Here is the original changelog:
This patch changes the format of the XFRM_MSG_DELSA and
XFRM_MSG_DELPOLICY notification so that the main message
sent is of the same format as that received by the kernel
if the original message was via netlink. This also means
that we won't lose the byid information carried in km_event.
Since this user interface is introduced by Jamal's patch
we can still afford to change it.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p1.patch --]
[-- Type: text/plain, Size: 3149 bytes --]
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -174,6 +174,8 @@ enum xfrm_attr_type_t {
XFRMA_ALG_COMP, /* struct xfrm_algo */
XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */
XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */
+ XFRMA_SA,
+ XFRMA_POLICY,
__XFRMA_MAX
#define XFRMA_MAX (__XFRMA_MAX - 1)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1159,7 +1159,7 @@ nlmsg_failure:
static int inline xfrm_sa_len(struct xfrm_state *x)
{
- int l = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
+ int l = 0;
if (x->aalg)
l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8);
if (x->ealg)
@@ -1175,20 +1175,39 @@ static int inline xfrm_sa_len(struct xfr
static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
{
struct xfrm_usersa_info *p;
+ struct xfrm_usersa_id *id;
struct nlmsghdr *nlh;
struct sk_buff *skb;
unsigned char *b;
int len = xfrm_sa_len(x);
+ int headlen;
+
+ headlen = sizeof(*p);
+ if (c->event == XFRM_MSG_DELSA) {
+ len += RTA_SPACE(headlen);
+ headlen = sizeof(*id);
+ }
+ len += NLMSG_SPACE(headlen);
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
b = skb->tail;
- nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, sizeof(*p));
+ nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
nlh->nlmsg_flags = 0;
p = NLMSG_DATA(nlh);
+ if (c->event == XFRM_MSG_DELSA) {
+ id = NLMSG_DATA(nlh);
+ memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
+ id->spi = x->id.spi;
+ id->family = x->props.family;
+ id->proto = x->id.proto;
+
+ p = RTA_DATA(__RTA_PUT(skb, XFRMA_SA, sizeof(*p)));
+ }
+
copy_to_user_state(x, p);
if (x->aalg)
@@ -1389,20 +1408,39 @@ static int xfrm_exp_policy_notify(struct
static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
{
struct xfrm_userpolicy_info *p;
+ struct xfrm_userpolicy_id *id;
struct nlmsghdr *nlh;
struct sk_buff *skb;
unsigned char *b;
int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
- len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_info));
+ int headlen;
+
+ headlen = sizeof(*p);
+ if (c->event == XFRM_MSG_DELPOLICY) {
+ len += RTA_SPACE(headlen);
+ headlen = sizeof(*id);
+ }
+ len += NLMSG_SPACE(headlen);
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
b = skb->tail;
- nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, sizeof(*p));
+ nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
p = NLMSG_DATA(nlh);
+ if (c->event == XFRM_MSG_DELPOLICY) {
+ id = NLMSG_DATA(nlh);
+ memset(id, 0, sizeof(*id));
+ id->dir = dir;
+ if (c->data.byid)
+ id->index = xp->index;
+ else
+ memcpy(&id->sel, &xp->selector, sizeof(id->sel));
+
+ p = RTA_DATA(__RTA_PUT(skb, XFRMA_POLICY, sizeof(*p)));
+ }
nlh->nlmsg_flags = 0;
@@ -1415,6 +1453,7 @@ static int xfrm_notify_policy(struct xfr
return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
nlmsg_failure:
+rtattr_failure:
kfree_skb(skb);
return -1;
}
^ permalink raw reply
* Re: [PATCH] e1000: NUMA aware allocation of descriptors V2
From: Andrew Morton @ 2005-05-27 23:25 UTC (permalink / raw)
To: Christoph Lameter; +Cc: ganesh.venkatesan, davem, linux-kernel, netdev, shai
In-Reply-To: <Pine.LNX.4.62.0505271450200.25909@graphe.net>
Christoph Lameter <christoph@lameter.com> wrote:
>
> NUMA awareness for the e1000 driver. Allocate tx and rx descriptors
> on the node of the device.
>
> It is safe to replace vmalloc by kmalloc node since only the descriptors
> are allocated in a NUMA aware way. These will not be so large that the
> use of vmalloc becomes necesssary.
Really? That's probably OK with the default number of tx descriptors, but
that number can be made arbitrarily large with a module parameter.
Could you please work this with the e1000 developers?
^ permalink raw reply
* [PATCH 5/5] [PKT_SCHED] textsearch ematch
From: Thomas Graf @ 2005-05-27 22:49 UTC (permalink / raw)
To: netdev; +Cc: Jamal Hadi Salim
In-Reply-To: <20050527224725.GG15391@postel.suug.ch>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
commit 5d28d54b48451e7833295be68b7e4b6fcc2b5375
tree cc252d153b4b21f347aab71bbfe04c0bf2a3a8a2
parent 4fdcfba0bf99efed709bc8ebaeda0d5ed7e9cc67
author Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 23:45:15 +0200
committer Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 23:45:15 +0200
include/linux/pkt_cls.h | 1
include/linux/tc_ematch/tc_em_text.h | 19 ++++
net/sched/Kconfig | 11 ++
net/sched/Makefile | 1
net/sched/em_text.c | 142 +++++++++++++++++++++++++++++++++++
5 files changed, 174 insertions(+)
Index: include/linux/pkt_cls.h
===================================================================
--- 13ce1cd98014267f2a353b96e813c1e70bbe9c3b/include/linux/pkt_cls.h (mode:100644)
+++ cc252d153b4b21f347aab71bbfe04c0bf2a3a8a2/include/linux/pkt_cls.h (mode:100644)
@@ -408,6 +408,7 @@
TCF_EM_NBYTE,
TCF_EM_U32,
TCF_EM_META,
+ TCF_EM_TEXT,
__TCF_EM_MAX
};
Index: include/linux/tc_ematch/tc_em_text.h
===================================================================
--- /dev/null (tree:13ce1cd98014267f2a353b96e813c1e70bbe9c3b)
+++ cc252d153b4b21f347aab71bbfe04c0bf2a3a8a2/include/linux/tc_ematch/tc_em_text.h (mode:100644)
@@ -0,0 +1,19 @@
+#ifndef __LINUX_TC_EM_TEXT_H
+#define __LINUX_TC_EM_TEXT_H
+
+#include <linux/pkt_cls.h>
+
+#define TC_EM_TEXT_ALGOSIZ 16
+
+struct tcf_em_text
+{
+ char algo[TC_EM_TEXT_ALGOSIZ];
+ __u16 from_offset;
+ __u16 to_offset;
+ __u16 pattern_len;
+ __u8 from_layer:4;
+ __u8 to_layer:4;
+ __u8 pad;
+};
+
+#endif
Index: net/sched/Kconfig
===================================================================
--- 13ce1cd98014267f2a353b96e813c1e70bbe9c3b/net/sched/Kconfig (mode:100644)
+++ cc252d153b4b21f347aab71bbfe04c0bf2a3a8a2/net/sched/Kconfig (mode:100644)
@@ -449,6 +449,17 @@
To compile this code as a module, choose M here: the
module will be called em_meta.
+config NET_EMATCH_TEXT
+ tristate "Textsearch"
+ depends on NET_EMATCH
+ ---help---
+ Say Y here if you want to be ablt to classify packets based on
+ textsearch comparisons. Please select the appropriate textsearch
+ algorithms in the Library section.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_text.
+
config NET_CLS_ACT
bool "Packet ACTION"
depends on EXPERIMENTAL && NET_CLS && NET_QOS
Index: net/sched/Makefile
===================================================================
--- 13ce1cd98014267f2a353b96e813c1e70bbe9c3b/net/sched/Makefile (mode:100644)
+++ cc252d153b4b21f347aab71bbfe04c0bf2a3a8a2/net/sched/Makefile (mode:100644)
@@ -40,3 +40,4 @@
obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o
obj-$(CONFIG_NET_EMATCH_META) += em_meta.o
+obj-$(CONFIG_NET_EMATCH_TEXT) += em_text.o
Index: net/sched/em_text.c
===================================================================
--- /dev/null (tree:13ce1cd98014267f2a353b96e813c1e70bbe9c3b)
+++ cc252d153b4b21f347aab71bbfe04c0bf2a3a8a2/net/sched/em_text.c (mode:100644)
@@ -0,0 +1,142 @@
+/*
+ * net/sched/em_text.c Textsearch ematch
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/textsearch.h>
+#include <linux/tc_ematch/tc_em_text.h>
+#include <net/pkt_cls.h>
+
+struct text_match
+{
+ u16 from_offset;
+ u16 to_offset;
+ u8 from_layer;
+ u8 to_layer;
+ struct ts_config *config;
+};
+
+static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m,
+ struct tcf_pkt_info *info)
+{
+ struct text_match *tm = (struct text_match *) m->data;
+ int from, to;
+ struct ts_state state;
+
+ from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data;
+ from += tm->from_offset;
+ to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data;
+ to += tm->to_offset;
+
+ if (skb_find_text(skb, from, to, tm->config, &state) < 0)
+ return 0;
+
+ return 1;
+}
+
+static int em_text_change(struct tcf_proto *tp, void *data, int len,
+ struct tcf_ematch *m)
+{
+ struct text_match *tm;
+ struct tcf_em_text *conf = data;
+ struct ts_config *ts_conf;
+
+ if (len < sizeof(*conf) ||
+ len < (sizeof(*conf) + conf->pattern_len))
+ return -EINVAL;
+
+ if (conf->from_layer > conf->to_layer)
+ return -EINVAL;
+
+ if (conf->from_layer == conf->to_layer &&
+ conf->from_offset > conf->to_offset)
+ return -EINVAL;
+
+ ts_conf = textsearch_prepare(conf->algo, (char *) conf + sizeof(*conf),
+ conf->pattern_len, GFP_KERNEL, 1);
+ if (IS_ERR(ts_conf))
+ return PTR_ERR(ts_conf);
+
+ tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+ if (tm == NULL) {
+ textsearch_destroy(ts_conf);
+ return -ENOBUFS;
+ }
+
+ tm->from_offset = conf->from_offset;
+ tm->to_offset = conf->to_offset;
+ tm->from_layer = conf->from_layer;
+ tm->to_layer = conf->to_layer;
+ tm->config = ts_conf;
+
+ m->datalen = sizeof(*tm);
+ m->data = (unsigned long) tm;
+
+ return 0;
+}
+
+static void em_text_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
+{
+ struct text_match *tm = (struct text_match *) m->data;
+ textsearch_destroy(tm->config);
+}
+
+static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m)
+{
+ struct text_match *tm = (struct text_match *) m->data;
+ struct tcf_em_text conf;
+
+ strncpy(conf.algo, tm->config->ops->name, sizeof(conf.algo) - 1);
+ conf.from_offset = tm->from_offset;
+ conf.to_offset = tm->to_offset;
+ conf.from_layer = tm->from_layer;
+ conf.to_layer = tm->to_layer;
+ conf.pattern_len = textsearch_get_pattern_len(tm->config);
+ conf.pad = 0;
+
+ RTA_PUT_NOHDR(skb, sizeof(conf), &conf);
+ RTA_PUT_NOHDR(skb, conf.pattern_len,
+ textsearch_get_pattern(tm->config));
+ return 0;
+
+rtattr_failure:
+ return -1;
+}
+
+static struct tcf_ematch_ops em_text_ops = {
+ .kind = TCF_EM_TEXT,
+ .change = em_text_change,
+ .match = em_text_match,
+ .destroy = em_text_destroy,
+ .dump = em_text_dump,
+ .owner = THIS_MODULE,
+ .link = LIST_HEAD_INIT(em_text_ops.link)
+};
+
+static int __init init_em_text(void)
+{
+ return tcf_em_register(&em_text_ops);
+}
+
+static void __exit exit_em_text(void)
+{
+ tcf_em_unregister(&em_text_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_text);
+module_exit(exit_em_text);
^ permalink raw reply
* [PATCH 4/5] [NET] Add skb_find_text() to search for a text pattern in skbs
From: Thomas Graf @ 2005-05-27 22:48 UTC (permalink / raw)
To: netdev; +Cc: Jamal Hadi Salim
In-Reply-To: <20050527224725.GG15391@postel.suug.ch>
Adds the function skb_find_text() to search for text patterns
in both, linear and non-linear skbs.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
commit 4fdcfba0bf99efed709bc8ebaeda0d5ed7e9cc67
tree 13ce1cd98014267f2a353b96e813c1e70bbe9c3b
parent 81553cdea2a7ff762cb44aeced743d3a77efd2d7
author Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 23:44:50 +0200
committer Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 23:44:50 +0200
include/linux/skbuff.h | 4 ++
net/core/skbuff.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
Index: include/linux/skbuff.h
===================================================================
--- 266c4ad512e5ae71bd7cd88c94bfb18fb2f761d6/include/linux/skbuff.h (mode:100644)
+++ 13ce1cd98014267f2a353b96e813c1e70bbe9c3b/include/linux/skbuff.h (mode:100644)
@@ -28,6 +28,7 @@
#include <linux/poll.h>
#include <linux/net.h>
#include <net/checksum.h>
+#include <linux/textsearch.h>
#define HAVE_ALLOC_SKB /* For the drivers to know */
#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
@@ -1187,6 +1188,9 @@
extern void skb_split(struct sk_buff *skb,
struct sk_buff *skb1, const u32 len);
+extern int skb_find_text(struct sk_buff *skb, int from, int to,
+ struct ts_config *config, struct ts_state *state);
+
static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
int len, void *buffer)
{
Index: net/core/skbuff.c
===================================================================
--- 266c4ad512e5ae71bd7cd88c94bfb18fb2f761d6/net/core/skbuff.c (mode:100644)
+++ 13ce1cd98014267f2a353b96e813c1e70bbe9c3b/net/core/skbuff.c (mode:100644)
@@ -1506,6 +1506,88 @@
skb_split_no_header(skb, skb1, len, pos);
}
+static int get_skb_text(int offset, unsigned char **text,
+ struct ts_config *conf, struct ts_state *state)
+{
+ /* args[0]: lower limit
+ * args[1]: upper limit
+ * args[2]: skb
+ * args[3]: fragment index
+ * args[4]: current fragment data buffer
+ * args[5]: octets consumed up to previous fragment */
+ int from = state->args[0], to = state->args[1];
+ struct sk_buff *skb = (struct sk_buff *) state->args[2];
+ int limit = min_t(int, skb_headlen(skb), to);
+ int real_offset = offset + from;
+ skb_frag_t *f;
+
+ if (!skb_is_nonlinear(skb)) {
+ if (real_offset < limit) {
+linear:
+ *text = skb->data + real_offset;
+ return limit - real_offset;
+ }
+
+ return 0;
+ }
+
+ if (real_offset < limit)
+ goto linear;
+
+next_fragment:
+ f = &skb_shinfo(skb)->frags[state->args[3]];
+ limit = min_t(int, f->size + state->args[5], to);
+
+ if (!state->args[4])
+ state->args[4] = (long) kmap_skb_frag(f);
+
+ if (real_offset < limit) {
+ *text = (unsigned char *) state->args[4] + f->page_offset +
+ (real_offset - (int) state->args[5]);
+ return limit - real_offset;
+ }
+
+ kunmap_skb_frag((void *) state->args[4]);
+ state->args[3]++;
+ state->args[4] = (long) NULL;
+ state->args[5] += f->size;
+
+ if (state->args[3] >= skb_shinfo(skb)->nr_frags)
+ return 0;
+
+ goto next_fragment;
+}
+
+static void get_skb_text_finish(struct ts_config *conf, struct ts_state *state)
+{
+ if (state->args[4])
+ kunmap_skb_frag((void *) state->args[4]);
+}
+
+/**
+ * skb_find_text - Find a text pattern in skb data
+ * @skb: the buffer to look in
+ * @from: search offset
+ * @to: search limit
+ * @config: textsearch configuration
+ * @state: empty textsearch state variable
+ */
+int skb_find_text(struct sk_buff *skb, int from, int to,
+ struct ts_config *config, struct ts_state *state)
+{
+ config->get_text = get_skb_text;
+ config->finish = get_skb_text_finish;
+ state->args[0] = from;
+ state->args[1] = to;
+ state->args[2] = (long) skb;
+ state->args[3] = 0;
+ state->args[4] = 0;
+ state->args[5] = skb_headlen(skb);
+
+ return textsearch_find(config, state);
+}
+
+
void __init skb_init(void)
{
skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1544,3 +1626,4 @@
EXPORT_SYMBOL(skb_unlink);
EXPORT_SYMBOL(skb_append);
EXPORT_SYMBOL(skb_split);
+EXPORT_SYMBOL(skb_find_text);
^ permalink raw reply
* [PATCH 3/5] [LIB] Naive regular expression string-matching algorithm
From: Thomas Graf @ 2005-05-27 22:48 UTC (permalink / raw)
To: netdev; +Cc: Jamal Hadi Salim
In-Reply-To: <20050527224725.GG15391@postel.suug.ch>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
commit 81553cdea2a7ff762cb44aeced743d3a77efd2d7
tree 266c4ad512e5ae71bd7cd88c94bfb18fb2f761d6
parent 5b70ca8eab4c7d7ef884582d9713cdbffa0f4cd4
author Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 23:44:24 +0200
committer Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 23:44:24 +0200
include/linux/textsearch_regexp.h | 47 ++++++
lib/Kconfig | 9 +
lib/Makefile | 1
lib/ts_regexp.c | 272 ++++++++++++++++++++++++++++++++++++++
4 files changed, 329 insertions(+)
Index: include/linux/textsearch_regexp.h
===================================================================
--- /dev/null (tree:4d90ca82120da7b308b9a6bf11a1069473ca5d30)
+++ 266c4ad512e5ae71bd7cd88c94bfb18fb2f761d6/include/linux/textsearch_regexp.h (mode:100644)
@@ -0,0 +1,47 @@
+#ifndef __LINUX_TEXTSEARCH_REGEXP_H
+#define __LINUX_TEXTSEARCH_REGEXP_H
+
+#include <linux/types.h>
+
+enum {
+ TS_RE_SPECIFIC, /* specific character */
+ TS_RE_WILDCARD, /* any character */
+ TS_RE_DIGIT, /* isdigit() */
+ TS_RE_XDIGIT, /* isxdigit() */
+ TS_RE_PRINT, /* isprint() */
+ TS_RE_ALPHA, /* isalpha() */
+ TS_RE_ALNUM, /* isalnum() */
+ TS_RE_ASCII, /* isascii() */
+ TS_RE_CNTRL, /* iscntrl() */
+ TS_RE_GRAPH, /* isgraph() */
+ TS_RE_LOWER, /* islower() */
+ TS_RE_UPPER, /* isupper() */
+ TS_RE_PUNCT, /* ispunct() */
+ TS_RE_SPACE, /* isspace() */
+ __TS_RE_TYPE_MAX,
+};
+#define TS_RE_TYPE_MAX (__TS_RE_TYPE_MAX - 1)
+
+enum {
+ TS_RE_SINGLE, /* 1 occurrence */
+ TS_RE_PERHAPS, /* 1 or 0 occurrence */
+ TS_RE_ANY, /* 0..n occurrences */
+ TS_RE_MULTI, /* 1..n occurrences */
+ __TS_RE_RECUR_MAX,
+};
+#define TS_RE_RECUR_MAX (__TS_RE_RECUR_MAX - 1)
+
+/**
+ * struct ts_regexp_token - regular expression token
+ * @type: type of token
+ * @recur: number of recurrences
+ * @value: character value for TS_RE_SPECIFIC
+ */
+struct ts_regexp_token
+{
+ __u16 type;
+ __u8 recur;
+ __u8 value;
+};
+
+#endif
Index: lib/Kconfig
===================================================================
--- 4d90ca82120da7b308b9a6bf11a1069473ca5d30/lib/Kconfig (mode:100644)
+++ 266c4ad512e5ae71bd7cd88c94bfb18fb2f761d6/lib/Kconfig (mode:100644)
@@ -68,6 +68,15 @@
To compile this code as a module, choose M here: the
module will be called ts_kmp.
+config TEXTSEARCH_REGEXP
+ tristate "Regular Expression"
+ help
+ Say Y here if you want to be able to search text using a
+ naive and limited regular expression textsearch algorithm.
+
+ To compile this code as a module, choose M here: the
+ module will be called ts_regexp.
+
endmenu
endmenu
Index: lib/Makefile
===================================================================
--- 4d90ca82120da7b308b9a6bf11a1069473ca5d30/lib/Makefile (mode:100644)
+++ 266c4ad512e5ae71bd7cd88c94bfb18fb2f761d6/lib/Makefile (mode:100644)
@@ -34,6 +34,7 @@
obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
+obj-$(CONFIG_TEXTSEARCH_REGEXP) += ts_regexp.o
hostprogs-y := gen_crc32table
clean-files := crc32table.h
Index: lib/ts_regexp.c
===================================================================
--- /dev/null (tree:4d90ca82120da7b308b9a6bf11a1069473ca5d30)
+++ 266c4ad512e5ae71bd7cd88c94bfb18fb2f761d6/lib/ts_regexp.c (mode:100644)
@@ -0,0 +1,272 @@
+/*
+ * lib/ts_regexp.c Naive and very limited regular expression
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/textsearch.h>
+#include <linux/textsearch_regexp.h>
+
+struct ts_regexp
+{
+ int ntokens;
+ struct ts_regexp_token tokens[0];
+};
+
+/* other values derived from ctype.h */
+#define _A 0x100 /* ascii */
+#define _W 0x200 /* wildcard */
+
+/* Map to _ctype flags and some magic numbers */
+static u16 token_map[TS_RE_TYPE_MAX+1] = {
+ [TS_RE_SPECIFIC] = 0,
+ [TS_RE_WILDCARD] = _W,
+ [TS_RE_CNTRL] = _C,
+ [TS_RE_LOWER] = _L,
+ [TS_RE_UPPER] = _U,
+ [TS_RE_PUNCT] = _P,
+ [TS_RE_SPACE] = _S,
+ [TS_RE_DIGIT] = _D,
+ [TS_RE_XDIGIT] = _D | _X,
+ [TS_RE_ALPHA] = _U | _L,
+ [TS_RE_ALNUM] = _U | _L | _D,
+ [TS_RE_PRINT] = _P | _U | _L | _D | _SP,
+ [TS_RE_GRAPH] = _P | _U | _L | _D,
+ [TS_RE_ASCII] = _A,
+};
+
+static u16 token_lookup_tbl[256] = {
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 0- 3 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 4- 7 */
+_W|_A|_C, _W|_A|_C|_S, _W|_A|_C|_S, _W|_A|_C|_S, /* 8- 11 */
+_W|_A|_C|_S, _W|_A|_C|_S, _W|_A|_C, _W|_A|_C, /* 12- 15 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 16- 19 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 20- 23 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 24- 27 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 28- 31 */
+_W|_A|_S|_SP, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 32- 35 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 36- 39 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 40- 43 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 44- 47 */
+_W|_A|_D, _W|_A|_D, _W|_A|_D, _W|_A|_D, /* 48- 51 */
+_W|_A|_D, _W|_A|_D, _W|_A|_D, _W|_A|_D, /* 52- 55 */
+_W|_A|_D, _W|_A|_D, _W|_A|_P, _W|_A|_P, /* 56- 59 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 60- 63 */
+_W|_A|_P, _W|_A|_U|_X, _W|_A|_U|_X, _W|_A|_U|_X, /* 64- 67 */
+_W|_A|_U|_X, _W|_A|_U|_X, _W|_A|_U|_X, _W|_A|_U, /* 68- 71 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_U, /* 72- 75 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_U, /* 76- 79 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_U, /* 80- 83 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_U, /* 84- 87 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_P, /* 88- 91 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 92- 95 */
+_W|_A|_P, _W|_A|_L|_X, _W|_A|_L|_X, _W|_A|_L|_X, /* 96- 99 */
+_W|_A|_L|_X, _W|_A|_L|_X, _W|_A|_L|_X, _W|_A|_L, /* 100-103 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_L, /* 104-107 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_L, /* 108-111 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_L, /* 112-115 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_L, /* 116-119 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_P, /* 120-123 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_C, /* 124-127 */
+_W, _W, _W, _W, /* 128-131 */
+_W, _W, _W, _W, /* 132-135 */
+_W, _W, _W, _W, /* 136-139 */
+_W, _W, _W, _W, /* 140-143 */
+_W, _W, _W, _W, /* 144-147 */
+_W, _W, _W, _W, /* 148-151 */
+_W, _W, _W, _W, /* 152-155 */
+_W, _W, _W, _W, /* 156-159 */
+_W|_S|_SP, _W|_P, _W|_P, _W|_P, /* 160-163 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 164-167 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 168-171 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 172-175 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 176-179 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 180-183 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 184-187 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 188-191 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 192-195 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 196-199 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 200-203 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 204-207 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 208-211 */
+_W|_U, _W|_U, _W|_U, _W|_P, /* 212-215 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 216-219 */
+_W|_U, _W|_U, _W|_U, _W|_L, /* 220-223 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 224-227 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 228-231 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 232-235 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 236-239 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 240-243 */
+_W|_L, _W|_L, _W|_L, _W|_P, /* 244-247 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 248-251 */
+_W|_L, _W|_L, _W|_L, _W|_L}; /* 252-255 */
+
+static inline int match_token(struct ts_regexp_token *t, u8 d)
+{
+ if (t->type)
+ return (token_lookup_tbl[d] & t->type) != 0;
+ else
+ return t->value == d;
+}
+
+static int regexp_find(struct ts_config *conf, struct ts_state *state)
+{
+ struct ts_regexp *regexp = ts_config_priv(conf);
+ int i, q, consumed = state->offset;
+ int match_start = state->offset;
+ struct ts_regexp_token *t = NULL, *next;
+ size_t text_len = 0;
+ unsigned char *text;
+
+#define GET_TEXT() \
+ ({ i = 0; conf->get_text(consumed, &text, conf, state); })
+
+#define end_of_text() (i >= text_len && !GET_TEXT())
+#define more_text() (i < text_len || GET_TEXT())
+
+#define NEXT_CHAR() do { i++; consumed++; } while (0)
+
+ for (i = 0, q = 0; q < regexp->ntokens; q++) {
+ t = ®exp->tokens[q];
+
+ if (likely(q < (regexp->ntokens - 1)))
+ next = ®exp->tokens[q+1];
+ else
+ next = NULL;
+
+ switch (t->recur) {
+ case TS_RE_SINGLE:
+ if (unlikely(end_of_text()))
+ goto no_match;
+
+ if (!match_token(t, text[i]))
+ goto no_match;
+ break;
+
+ case TS_RE_PERHAPS:
+ if (likely(more_text()))
+ if (match_token(t, text[i]))
+ break;
+ continue;
+
+ case TS_RE_MULTI:
+ if (unlikely(end_of_text()))
+ goto no_match;
+
+ if (!match_token(t, text[i]))
+ goto no_match;
+
+ NEXT_CHAR();
+ /* fall through */
+
+ case TS_RE_ANY:
+ if (next == NULL)
+ goto found_match;
+
+ if (likely(more_text())) {
+ while (!match_token(next, text[i])) {
+ if (!match_token(t, text[i]))
+ goto no_match;
+ NEXT_CHAR();
+ if (unlikely(end_of_text()))
+ goto no_match;
+ }
+ }
+ continue;
+ }
+
+ NEXT_CHAR();
+ }
+
+ if (q >= (regexp->ntokens - 1))
+ goto found_match;
+
+no_match:
+ return -1;
+
+found_match:
+ state->offset = consumed + i + 1;
+ return match_start;
+}
+
+static struct ts_config *regexp_init(const unsigned char *pattern, size_t len,
+ int gfp_mask)
+{
+ int i, err = -EINVAL;
+ struct ts_config *conf;
+ struct ts_regexp *regexp;
+ struct ts_regexp_token *tokens = (struct ts_regexp_token *) pattern;
+
+ if (len % sizeof(struct ts_regexp_token))
+ goto errout;
+
+ for (i = 0; i < len / sizeof(struct ts_regexp_token); i++) {
+ struct ts_regexp_token *t = &tokens[i];
+
+ if (t->type > TS_RE_TYPE_MAX ||
+ t->type > TS_RE_RECUR_MAX)
+ goto errout;
+
+ t->type = token_map[t->type];
+ }
+
+ conf = alloc_ts_config(len, gfp_mask);
+ if (IS_ERR(conf))
+ return conf;
+
+ regexp = ts_config_priv(conf);
+ regexp->ntokens = len / sizeof(struct ts_regexp_token);
+ memcpy(regexp->tokens, pattern, len);
+
+ return conf;
+
+errout:
+ return ERR_PTR(err);
+}
+
+static unsigned char *regexp_get_pattern(struct ts_config *conf)
+{
+ struct ts_regexp *regexp = ts_config_priv(conf);
+ return (unsigned char *) regexp->tokens;
+}
+
+static unsigned int regexp_get_pattern_len(struct ts_config *conf)
+{
+ struct ts_regexp *regexp = ts_config_priv(conf);
+ return regexp->ntokens * sizeof(struct ts_regexp_token);
+}
+
+static struct ts_ops regexp_ops = {
+ .name = "regexp",
+ .find = regexp_find,
+ .init = regexp_init,
+ .get_pattern = regexp_get_pattern,
+ .get_pattern_len = regexp_get_pattern_len,
+ .owner = THIS_MODULE,
+ .list = LIST_HEAD_INIT(regexp_ops.list)
+};
+
+static int __init init_regexp(void)
+{
+ return textsearch_register(®exp_ops);
+}
+
+static void __exit exit_regexp(void)
+{
+ textsearch_unregister(®exp_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_regexp);
+module_exit(exit_regexp);
^ permalink raw reply
* [PATCH 2/5] [LIB] Knuth-Morris-Pratt string-matching algorithm
From: Thomas Graf @ 2005-05-27 22:48 UTC (permalink / raw)
To: netdev; +Cc: Jamal Hadi Salim
In-Reply-To: <20050527224725.GG15391@postel.suug.ch>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
commit 5b70ca8eab4c7d7ef884582d9713cdbffa0f4cd4
tree 4d90ca82120da7b308b9a6bf11a1069473ca5d30
parent bf7ae763f13d767bd039703b3ab4f5954561df39
author Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 23:44:02 +0200
committer Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 23:44:02 +0200
lib/Kconfig | 13 +++++
lib/Makefile | 2
lib/ts_kmp.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+)
Index: lib/Kconfig
===================================================================
--- ab065819ea6e966aa3db4f1c5935c421dd689d2e/lib/Kconfig (mode:100644)
+++ 4d90ca82120da7b308b9a6bf11a1069473ca5d30/lib/Kconfig (mode:100644)
@@ -57,5 +57,18 @@
config REED_SOLOMON_DEC16
boolean
+menu "Textsearch facility"
+
+config TEXTSEARCH_KMP
+ tristate "Knuth-Morris-Pratt"
+ help
+ Say Y here if you want to be able to search text using the
+ Knuth-Morris-Pratt textsearch algorithm.
+
+ To compile this code as a module, choose M here: the
+ module will be called ts_kmp.
+
+endmenu
+
endmenu
Index: lib/Makefile
===================================================================
--- ab065819ea6e966aa3db4f1c5935c421dd689d2e/lib/Makefile (mode:100644)
+++ 4d90ca82120da7b308b9a6bf11a1069473ca5d30/lib/Makefile (mode:100644)
@@ -33,6 +33,8 @@
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
+obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
Index: lib/ts_kmp.c
===================================================================
--- /dev/null (tree:ab065819ea6e966aa3db4f1c5935c421dd689d2e)
+++ 4d90ca82120da7b308b9a6bf11a1069473ca5d30/lib/ts_kmp.c (mode:100644)
@@ -0,0 +1,145 @@
+/*
+ * lib/ts_kmp.c Knuth-Morris-Pratt text search implementation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ *
+ * Implements a linear-time string-matching algorithm due to Knuth,
+ * Morris, and Pratt [0]. Their algorithm avoids the explicit
+ * computation of the transition function DELTA altogether. Its
+ * matching time is O(n), for n being length(text), using just an
+ * auxiliary function PI[1..m], for m being length(pattern),
+ * precomputed from the pattern in time O(m). The array PI allows
+ * the transition function DELTA to be computed efficiently
+ * "on the fly" as needed. Roughly speaking, for any state
+ * "q" = 0,1,...,m and any character "a" in SIGMA, the value
+ * PI["q"] contains the information that is independent of "a" and
+ * is needed to compute DELTA("q", "a") [1]. Since the array PI
+ * has only m entries, whereas DELTA has O(m|SIGMA|) entries, we
+ * save a factor of |SIGMA| in the preprocessing time by computing
+ * PI rather than DELTA.
+ *
+ * [0] Cormen, Leiserson, Rivest, Stein
+ * Introdcution to Algorithms, 2nd Edition, MIT Press
+ * [1] See finite automation theory
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/textsearch.h>
+
+struct ts_kmp
+{
+ int pattern_len;
+ unsigned char * pattern;
+ unsigned int prefix_tbl[0];
+};
+
+static int kmp_find(struct ts_config *conf, struct ts_state *state)
+{
+ struct ts_kmp *kmp = ts_config_priv(conf);
+ int i, q = 0, consumed = state->offset;
+ unsigned char *text;
+ size_t text_len;
+
+ for (;;) {
+ text_len = conf->get_text(consumed, &text, conf, state);
+
+ if (text_len == 0)
+ break;
+
+ for (i = 0; i < text_len; i++) {
+ while (q > 0 && kmp->pattern[q] != text[i])
+ q = kmp->prefix_tbl[q - 1];
+ if (kmp->pattern[q] == text[i])
+ q++;
+ if (q == kmp->pattern_len) {
+ state->offset = consumed + i + 1;
+ return state->offset - kmp->pattern_len;
+ }
+ }
+
+ consumed += text_len;
+ }
+
+ return -1;
+
+}
+
+static inline void compute_prefix_tbl(const unsigned char *pattern, size_t len,
+ unsigned int *prefix_tbl)
+{
+ unsigned int k, q;
+
+ for (k = 0, q = 1; q < len; q++) {
+ while (k > 0 && pattern[k] != pattern[q])
+ k = prefix_tbl[k-1];
+ if (pattern[k] == pattern[q])
+ k++;
+ prefix_tbl[q] = k;
+ }
+}
+
+static struct ts_config *kmp_init(const unsigned char *pattern, size_t len,
+ int gfp_mask)
+{
+ struct ts_config *conf;
+ struct ts_kmp *kmp;
+ size_t prefix_tbl_len = len * sizeof(unsigned int);
+ size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len;
+
+ conf = alloc_ts_config(priv_size, gfp_mask);
+ if (IS_ERR(conf))
+ return conf;
+
+ kmp = ts_config_priv(conf);
+ kmp->pattern_len = len;
+ compute_prefix_tbl(pattern, len, kmp->prefix_tbl);
+ kmp->pattern = (unsigned char *) kmp->prefix_tbl + prefix_tbl_len;
+ memcpy(kmp->pattern, pattern, len);
+
+ return conf;
+}
+
+static unsigned char *kmp_get_pattern(struct ts_config *conf)
+{
+ struct ts_kmp *kmp = ts_config_priv(conf);
+ return kmp->pattern;
+}
+
+static unsigned int kmp_get_pattern_len(struct ts_config *conf)
+{
+ struct ts_kmp *kmp = ts_config_priv(conf);
+ return kmp->pattern_len;
+}
+
+static struct ts_ops kmp_ops = {
+ .name = "kmp",
+ .find = kmp_find,
+ .init = kmp_init,
+ .get_pattern = kmp_get_pattern,
+ .get_pattern_len = kmp_get_pattern_len,
+ .owner = THIS_MODULE,
+ .list = LIST_HEAD_INIT(kmp_ops.list)
+};
+
+static int __init init_kmp(void)
+{
+ return textsearch_register(&kmp_ops);
+}
+
+static void __exit exit_kmp(void)
+{
+ textsearch_unregister(&kmp_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_kmp);
+module_exit(exit_kmp);
^ permalink raw reply
* [PATCH 1/5] [LIB] textsearch infrastructure
From: Thomas Graf @ 2005-05-27 22:47 UTC (permalink / raw)
To: netdev; +Cc: Jamal Hadi Salim
In-Reply-To: <20050527224725.GG15391@postel.suug.ch>
Before a textsearch can be performed, a configuration must be created
by calling textsearch_prepare() specyfing the searching algorithm and
the pattern to match. The returned configuration may then be used for
an arbitary amount of times and even in parallel as long as you
provide a separate struct ts_state variable for every instance.
The actual search is performed by either calling textsearch_find_-
continuous() for linear text or by providing an own get_text()
implementation and calling textsearch_find(). Both functions will
returns the position of the first matching occurrence of the patern.
Subsequent matches may be retrived via textsearch_next() irrespective
of the linearity of the text.
Once you're done using a configuration you must give back the
allocted resources by calling textsearch_destroy().
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
commit bf7ae763f13d767bd039703b3ab4f5954561df39
tree ab065819ea6e966aa3db4f1c5935c421dd689d2e
parent fde09d4989b6c7b5183ffb3ec2076ff53dd6fa78
author Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 20:18:48 +0200
committer Thomas Graf <tgraf@suug.ch> Fri, 27 May 2005 20:18:48 +0200
include/linux/textsearch.h | 196 ++++++++++++++++++++++++++++++++++++
lib/Makefile | 2
lib/textsearch.c | 241 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 438 insertions(+), 1 deletion(-)
Index: include/linux/textsearch.h
===================================================================
--- /dev/null (tree:b032d0d440d93aac252e656bd41df32ff5461e3a)
+++ ab065819ea6e966aa3db4f1c5935c421dd689d2e/include/linux/textsearch.h (mode:100644)
@@ -0,0 +1,196 @@
+#ifndef __LINUX_TEXTSEARCH_H
+#define __LINUX_TEXTSEARCH_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+struct ts_config;
+
+/**
+ * struct ts_state - textsearch state
+ * @offset: offset for next match
+ * @args: for persistant variables of get_text()
+ */
+struct ts_state
+{
+ int offset;
+ long args[6];
+};
+
+/**
+ * struct ts_ops - textsearch operations
+ * @name: name of search algorithm
+ * @init: called upon initialization to prepare a search
+ * @find: does the actual matching on a prepared configuration
+ * @destroy: called upon destroyage of a configuration
+ * @owner: reference to algorithm module if existent
+ * @list: operations list we are on
+ */
+struct ts_ops
+{
+ const char *name;
+ struct ts_config * (*init)(const unsigned char *, size_t, int);
+ int (*find)(struct ts_config *,
+ struct ts_state *);
+ void (*destroy)(struct ts_config *);
+ unsigned char * (*get_pattern)(struct ts_config *);
+ unsigned int (*get_pattern_len)(struct ts_config *);
+ struct module *owner;
+ struct list_head list;
+};
+
+/**
+ * struct ts_config - textsearch configuration
+ * @ops: textsearch operations
+ * @get_text: callback to fetch text to search in
+ * @len: length of pattern
+ */
+struct ts_config
+{
+ struct ts_ops *ops;
+
+ /**
+ * get_text - return next chunk of text
+ * @offset: Number of bytes consumed by the matcher
+ * @dst: destination buffer
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Gets called repeatedly until 0 is returned.Must assign a pointer
+ * to the start of the next chunk of text to *dst and return the
+ * length of the chunk or 0 if at the end. offset==0 indicates
+ * a new search. May store/read persistant values in state->args[].
+ */
+ int (*get_text)(int offset, unsigned char **dst,
+ struct ts_config *conf,
+ struct ts_state *state);
+
+ /**
+ * finish - called when the matching has been completed successful
+ * or not.
+ * @conf: search configuration
+ * @state: search state
+ */
+ void (*finish)(struct ts_config *conf,
+ struct ts_state *state);
+};
+
+/**
+ * textsearch_next - continue search for a pattern in a text
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Continues a search looking for more occurrences of the pattern.
+ * You must call textsearch_find() to search the first occurrence
+ * in order to reset the state.
+ *
+ * Returns the position of next occurance of the pattern or a
+ * negative number if no match was found.
+ */
+static inline int textsearch_next(struct ts_config *conf,
+ struct ts_state *state)
+{
+ int ret = conf->ops->find(conf, state);
+
+ if (conf->finish)
+ conf->finish(conf, state);
+
+ return ret;
+}
+
+/**
+ * textsearch_find - search for a pattern in a text
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Peforms the actual search on the prepared configuration.
+ *
+ * Returns the position of first occurrence of the pattern or a
+ * negative number if no match was found.
+ */
+static inline int textsearch_find(struct ts_config *conf,
+ struct ts_state *state)
+{
+ state->offset = 0;
+ return textsearch_next(conf, state);
+}
+
+/**
+ * textsearch_destroy - destroy a textsearch configuration
+ * @conf: search configuration
+ *
+ * Releases all references of the configuration and frees
+ * up the memory.
+ */
+static inline void textsearch_destroy(struct ts_config *conf)
+{
+ if (conf->ops) {
+ if (conf->ops->destroy)
+ conf->ops->destroy(conf);
+ module_put(conf->ops->owner);
+ }
+
+ kfree(conf);
+}
+
+/**
+ * textsearch_get_pattern - return pattern of a textsearch configuration
+ * @conf: textsearch configuration
+ */
+static inline unsigned char *textsearch_get_pattern(struct ts_config *conf)
+{
+ return conf->ops->get_pattern(conf);
+}
+
+/**
+ * textsearch_get_pattern_len - return pattern length of a textsearch configuration
+ * @conf: textsearch configuration
+ */
+static inline unsigned int textsearch_get_pattern_len(struct ts_config *conf)
+{
+ return conf->ops->get_pattern_len(conf);
+}
+
+/**
+ * alloc_ts_config - allocate a textsearch configuration
+ * @payload: size of additional module specific data required
+ * @gfp_mask: allocation mask
+ *
+ * Returns a empty textsearch configuration or a ERR_PTR().
+ */
+static inline struct ts_config *alloc_ts_config(size_t payload, int gfp_mask)
+{
+ struct ts_config *conf;
+
+ conf = kmalloc(sizeof(*conf) + payload, gfp_mask);
+ if (conf == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ memset(conf, 0, sizeof(*conf) + payload);
+ return conf;
+}
+
+/**
+ * ts_config_priv - returns private part of a textsearch configuration
+ * @conf: textsearch configuration
+ */
+static inline void *ts_config_priv(struct ts_config *conf)
+{
+ return ((unsigned char *) conf + sizeof(struct ts_config));
+}
+
+extern int textsearch_register(struct ts_ops *);
+extern int textsearch_unregister(struct ts_ops *);
+extern struct ts_config *textsearch_prepare(const char *, const unsigned char *,
+ size_t, int, int);
+extern int textsearch_find_continuous(struct ts_config *, struct ts_state *,
+ const unsigned char *, size_t);
+
+#endif /* __KERNEL__ */
+
+#endif
Index: lib/Makefile
===================================================================
--- b032d0d440d93aac252e656bd41df32ff5461e3a/lib/Makefile (mode:100644)
+++ ab065819ea6e966aa3db4f1c5935c421dd689d2e/lib/Makefile (mode:100644)
@@ -6,7 +6,7 @@
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
kobject.o kref.o idr.o div64.o int_sqrt.o \
bitmap.o extable.o kobject_uevent.o prio_tree.o sha1.o \
- halfmd4.o
+ halfmd4.o textsearch.o
obj-y += sort.o parser.o
Index: lib/textsearch.c
===================================================================
--- /dev/null (tree:b032d0d440d93aac252e656bd41df32ff5461e3a)
+++ ab065819ea6e966aa3db4f1c5935c421dd689d2e/lib/textsearch.c (mode:100644)
@@ -0,0 +1,241 @@
+/*
+ * lib/textsearch.c Generic text search interface
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ *
+ * The textsearch infrastructure provides text searching facitilies for both
+ * linear and non-linear data.
+ *
+ * Before a textsearch can be performed, a configuration must be created
+ * by calling textsearch_prepare() specyfing the searching algorithm and
+ * the pattern to match. The returned configuration may then be used for
+ * an arbitary amount of times and even in parallel as long as you
+ * provide a separate struct ts_state variable for every instance.
+ *
+ * The actual search is performed by either calling textsearch_find_-
+ * continuous() for linear text or by providing an own get_text()
+ * implementation and calling textsearch_find(). Both functions will
+ * returns the position of the first matching occurrence of the patern.
+ * Subsequent matches may be retrived via textsearch_next() irrespective
+ * of the linearity of the text.
+ *
+ * Once you're done using a configuration you must give back the
+ * allocted resources by calling textsearch_destroy().
+ *
+ * Example:
+ * int pos;
+ * struct ts_config *conf;
+ * struct ts_state state;
+ * conar char *pattern = "chicken";
+ * const char *example = "We dance the funky chicken";
+ *
+ * conf = textsearch_prepare("kmp", pattern, strlen(pattern), GFP_KERNEL, 1);
+ * if (IS_ERR(conf)) {
+ * err = PTR_ERR(conf);
+ * goto errout;
+ * }
+ *
+ * pos = textsearch_find_continuous(conf, &state, example, strlen(example));
+ * if (pos >= 0)
+ * panic("Oh my god, dancing chickens at %d\n", pos);
+ *
+ * textsearch_destroy(conf);
+ *
+ * ==========================================================================
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/err.h>
+#include <linux/textsearch.h>
+
+static LIST_HEAD(ts_ops);
+static DEFINE_RWLOCK(ts_mod_lock);
+
+static inline struct ts_ops *lookup_ts_algo(const char *name)
+{
+ struct ts_ops *o;
+
+ read_lock(&ts_mod_lock);
+ list_for_each_entry(o, &ts_ops, list) {
+ if (!strcmp(name, o->name)) {
+ if (!try_module_get(o->owner))
+ o = NULL;
+ read_unlock(&ts_mod_lock);
+ return o;
+ }
+ }
+ read_unlock(&ts_mod_lock);
+
+ return NULL;
+}
+
+/**
+ * textsearch_register - register a textsearch module
+ * @ops: operations lookup table
+ *
+ * This function must be called by textsearch modules to announce
+ * their presence. The given @ops must have %name set to a unique
+ * identifier and the callbacks find() and init() must be implemented.
+ *
+ * Returns -EEXISTS if another module has already registered with
+ * same name.
+ */
+int textsearch_register(struct ts_ops *ops)
+{
+ int err = -EEXIST;
+ struct ts_ops *o;
+
+ if (ops->name == NULL || ops->find == NULL || ops->init == NULL ||
+ ops->get_pattern == NULL || ops->get_pattern_len == NULL)
+ return -EINVAL;
+
+ write_lock(&ts_mod_lock);
+ list_for_each_entry(o, &ts_ops, list)
+ if (!strcmp(ops->name, o->name))
+ goto errout;
+
+ list_add_tail(&ops->list, &ts_ops);
+ err = 0;
+errout:
+ write_unlock(&ts_mod_lock);
+ return err;
+}
+
+/**
+ * textsearch_unregister - unregister a textsearch module
+ * @ops: operations lookup table
+ *
+ * This function must be called by textsearch modules to announce
+ * their disappearance for examples when the module gets unloaded.
+ * The @ops parameter must be the same as the one during the
+ * registration.
+ *
+ * Returns -ENOENT if no matching textsearch registration was found.
+ */
+int textsearch_unregister(struct ts_ops *ops)
+{
+ int err = 0;
+ struct ts_ops *o;
+
+ write_lock(&ts_mod_lock);
+ list_for_each_entry(o, &ts_ops, list) {
+ if (o == ops) {
+ list_del(&o->list);
+ goto out;
+ }
+ }
+
+ err = -ENOENT;
+out:
+ write_unlock(&ts_mod_lock);
+ return err;
+}
+
+static inline int get_linear_text(int offset, unsigned char **text,
+ struct ts_config *conf,
+ struct ts_state *state)
+{
+ unsigned char *string = (unsigned char *) state->args[0];
+ size_t len = state->args[1];
+
+ if (offset < len) {
+ *text = string + offset;
+ return len - offset;
+ } else
+ return 0;
+}
+
+/**
+ * textsearch_find_continuous - search a pattern in continuous/linear text
+ * @conf: search configuration
+ * @state: search state
+ * @text: text to search in
+ * @len: length of text
+ *
+ * A simplified version of textsearch_find() for continuous/linear text.
+ * Call textsearch_next() to retrieve subsequent matches.
+ *
+ * Returns the position of first occurrence of the pattern or a
+ * negative number if no match was found.
+ */
+int textsearch_find_continuous(struct ts_config *conf, struct ts_state *state,
+ const unsigned char *text, size_t len)
+{
+ conf->get_text = get_linear_text;
+ state->args[0] = (long) text;
+ state->args[1] = len;
+
+ return textsearch_find(conf, state);
+}
+
+/**
+ * textsearch_prepare - Prepare a text search
+ * @algo: name of search algorithm
+ * @pattern: pattern data
+ * @len: length of pattern
+ * @gfp_mask: allocation mask
+ * @autoload: bool indicating whether to autoload modules
+ *
+ * Looks up the search algorithm module and creates a new textsearch
+ * configuration for the specified pattern. Upon completion all
+ * necessary refcnts are held and the configuration must be put back
+ * using textsearch_put() after usage.
+ *
+ * Note: The format of the pattern may not be compatible between
+ * the various search algorithms.
+ *
+ * Returns a new textsearch configuration according to the specified
+ * parameters or a ERR_PTR().
+ */
+struct ts_config *textsearch_prepare(const char *algo,
+ const unsigned char *pattern, size_t len,
+ int gfp_mask, int autoload)
+{
+ int err = -ENOENT;
+ struct ts_config *conf;
+ struct ts_ops *ops;
+
+ ops = lookup_ts_algo(algo);
+#ifdef CONFIG_KMOD
+ /* Why not always autoload you may ask. Some users may be
+ * in a situation where requesting a module may deadlock,
+ * especially when the module is located on a NFS mount. */
+ if (ops == NULL && autoload) {
+ request_module("ts_%s", algo);
+ ops = lookup_ts_algo(algo);
+ }
+#endif
+
+ if (ops == NULL)
+ goto errout;
+
+ conf = ops->init(pattern, len, gfp_mask);
+ if (IS_ERR(conf)) {
+ err = PTR_ERR(conf);
+ goto errout;
+ }
+
+ conf->ops = ops;
+ return conf;
+
+errout:
+ if (ops)
+ module_put(ops->owner);
+
+ return ERR_PTR(err);
+}
+
+EXPORT_SYMBOL(textsearch_register);
+EXPORT_SYMBOL(textsearch_unregister);
+EXPORT_SYMBOL(textsearch_prepare);
+EXPORT_SYMBOL(textsearch_find_continuous);
^ permalink raw reply
* [RFC] textsearch infrastructure et al v2
From: Thomas Graf @ 2005-05-27 22:47 UTC (permalink / raw)
To: netdev; +Cc: Jamal Hadi Salim
Dave, I'm going through another RFC round to hopefully get
some comments on the notes below.
I'm not yet satistifed with the core infrastructure wrt to
non-linear data, especially for complex cases such as non
linear skbs. The current way can be easly described as:
search_occurrance()
search-algorithm()
while get-next-segment()
process-segment()
So basically we save the state of the segment fetching
instead of saving the state of the search algorithm which
would be way too complex for things like regular expression
string matching.
In the case of non linear skbs this would lead to:
1) start of search algorithm
2) first call to get_text(), return skb->data
3) processing of the text segment, return if match found
4) second call to get_text(), map and return first fragment
5) processing ...
6) third call to get_text(), unmap first fragment, map and
return second fragment
7) processing ...
n) etc.
Assuming that the most common case is to have no fragments
at all or if we only process a very limited number of
fragments (due to restricted search area) this should be
quite fast. However, the complexity of get_text() for the
skb case including the map/unmap of the fragment interrupts
the search flow quite a bit which hurts performance.
In order to address this issue I'm having second thoughts
about whether to allow the textsearch user to provide an
array of text segments including their size, i.e. the skb
fragments could be maped in prior and the algorithm could
scan through it like nothing. ;-> However, this has one
essential drawback, we might map fragments which we'll
never use so this can be slower in the end.
Any other ideas around?
^ permalink raw reply
* Re: [patch 2.6.12-rc5] tg3: add bcm5752 entry to pci.ids
From: Dave Jones @ 2005-05-27 22:46 UTC (permalink / raw)
To: David S. Miller; +Cc: mchan, linville, linux-kernel, netdev, jgarzik
In-Reply-To: <20050527.134032.78491984.davem@davemloft.net>
On Fri, May 27, 2005 at 01:40:32PM -0700, David S. Miller wrote:
> From: "Michael Chan" <mchan@broadcom.com>
> Date: Fri, 27 May 2005 12:24:19 -0700
>
> > So in the future, do we need to patch this file or just let sourceforge
> > take care of it?
>
> I think the proper procedure is to send it to sourceforge.
> But there is some latency in the changes making it back
> into the kernel.
The latest diff vs mainline is always available at http://www.codemonkey.org.uk/projects/pci/
(Comedy aside, I dont even remember which box is running the cronjob that
generates those files any more, good that its still ticking :-)
Greg did a sync up a while ago, but didn't seem too enthusiastic about
doing it regularly, due to the fact that /proc/pci is aparently going away.
Dave
^ permalink raw reply
* [PATCH] r8169: support restricting speed+duplex in autonegotiation
From: Richard Dawe @ 2005-05-27 22:36 UTC (permalink / raw)
To: Francois Romieu; +Cc: Linux netdev
[-- Attachment #1: Type: text/plain, Size: 796 bytes --]
Hello.
Attached is a patch for drivers/net/r8169.c against Linux 2.6.11 that
allows adjustment of the speed and duplex advertised via
autonegotiation. Example usage:
ethtool -s eth0 autoneg on speed 10 duplex half
Also attached is a test script which tries various combinations of
autoneg, speed and duplex. There is also a log of the test run attache.d
While the test ran I had an ssh session running "while true; do sleep 1;
date; done". The ssh session did not drop. Note that I don't have GigE,
so that part of the test was bogus.
I also tried various speed tests, to check that the speed and duplex
were actually changed. They were.
Bye, Rich
r8169: Allow adjustment of speed and duplex advertised via autonegotiation
Signed-off-by: Richard Dawe <rich@phekda.gotadsl.co.uk>
[-- Attachment #2: r8169-ethtool-autoneg.diff --]
[-- Type: text/plain, Size: 5904 bytes --]
--- r8169.c.orig 2005-05-27 21:12:21.000000000 +0100
+++ r8169.c 2005-05-27 22:14:59.000000000 +0100
@@ -407,7 +407,9 @@ struct rtl8169_private {
#ifdef CONFIG_R8169_VLAN
struct vlan_group *vlgrp;
#endif
- int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
+ int (*set_speed)(struct net_device *,
+ u8 autoneg, u16 speed, u8 duplex,
+ u32 advertising);
void (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(void __iomem *);
unsigned int (*phy_reset_pending)(void __iomem *);
@@ -549,7 +551,9 @@ static void rtl8169_check_link_status(st
spin_unlock_irqrestore(&tp->lock, flags);
}
-static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
+static void rtl8169_link_option(int idx,
+ u8 *autoneg, u16 *speed, u8 *duplex,
+ u32 *advertising)
{
struct {
u16 speed;
@@ -579,6 +583,23 @@ static void rtl8169_link_option(int idx,
*autoneg = p->autoneg;
*speed = p->speed;
*duplex = p->duplex;
+
+ if (p->media == _10_Half)
+ *advertising = ADVERTISED_10baseT_Half;
+ if (p->media == _10_Full)
+ *advertising = ADVERTISED_10baseT_Full;
+ if (p->media == _100_Half)
+ *advertising = ADVERTISED_100baseT_Half;
+ if (p->media == _100_Full)
+ *advertising = ADVERTISED_100baseT_Full;
+ if (p->media == _1000_Full)
+ *advertising = ADVERTISED_1000baseT_Full;
+ if (p->media == 0xff)
+ *advertising = ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Full;
}
static void rtl8169_get_drvinfo(struct net_device *dev,
@@ -597,7 +618,8 @@ static int rtl8169_get_regs_len(struct n
}
static int rtl8169_set_speed_tbi(struct net_device *dev,
- u8 autoneg, u16 speed, u8 duplex)
+ u8 autoneg, u16 speed, u8 duplex,
+ u32 advertising)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
@@ -608,7 +630,8 @@ static int rtl8169_set_speed_tbi(struct
if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
(duplex == DUPLEX_FULL)) {
RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
- } else if (autoneg == AUTONEG_ENABLE)
+ } else if ((autoneg == AUTONEG_ENABLE) &&
+ (advertising & ADVERTISED_1000baseT_Full))
RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
else {
printk(KERN_WARNING PFX
@@ -621,11 +644,13 @@ static int rtl8169_set_speed_tbi(struct
}
static int rtl8169_set_speed_xmii(struct net_device *dev,
- u8 autoneg, u16 speed, u8 duplex)
+ u8 autoneg, u16 speed, u8 duplex,
+ u32 advertising)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
int auto_nego, giga_ctrl;
+ int ret = 0;
auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);
auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full |
@@ -634,9 +659,16 @@ static int rtl8169_set_speed_xmii(struct
giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null);
if (autoneg == AUTONEG_ENABLE) {
- auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full |
- PHY_Cap_100_Half | PHY_Cap_100_Full);
- giga_ctrl |= PHY_Cap_1000_Full;
+ if (advertising & ADVERTISED_10baseT_Half)
+ auto_nego |= PHY_Cap_10_Half;
+ if (advertising & ADVERTISED_10baseT_Full)
+ auto_nego |= PHY_Cap_10_Full;
+ if (advertising & ADVERTISED_100baseT_Half)
+ auto_nego |= PHY_Cap_100_Half;
+ if (advertising & ADVERTISED_100baseT_Full)
+ auto_nego |= PHY_Cap_100_Full;
+ if (advertising & ADVERTISED_1000baseT_Full)
+ giga_ctrl |= PHY_Cap_1000_Full;
} else {
if (speed == SPEED_10)
auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full;
@@ -649,23 +681,28 @@ static int rtl8169_set_speed_xmii(struct
auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
}
- tp->phy_auto_nego_reg = auto_nego;
- tp->phy_1000_ctrl_reg = giga_ctrl;
+ if (ret == 0)
+ {
+ tp->phy_auto_nego_reg = auto_nego;
+ tp->phy_1000_ctrl_reg = giga_ctrl;
+
+ mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego);
+ mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl);
+ mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego |
+ PHY_Restart_Auto_Nego);
+ }
- mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego);
- mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl);
- mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego |
- PHY_Restart_Auto_Nego);
- return 0;
+ return ret;
}
static int rtl8169_set_speed(struct net_device *dev,
- u8 autoneg, u16 speed, u8 duplex)
+ u8 autoneg, u16 speed, u8 duplex,
+ u32 advertising)
{
struct rtl8169_private *tp = netdev_priv(dev);
int ret;
- ret = tp->set_speed(dev, autoneg, speed, duplex);
+ ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
if (netif_running(dev) && (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))
mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
@@ -680,7 +717,9 @@ static int rtl8169_set_settings(struct n
int ret;
spin_lock_irqsave(&tp->lock, flags);
- ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);
+ ret = rtl8169_set_speed(dev,
+ cmd->autoneg, cmd->speed, cmd->duplex,
+ cmd->advertising);
spin_unlock_irqrestore(&tp->lock, flags);
return ret;
@@ -1311,6 +1350,7 @@ rtl8169_init_one(struct pci_dev *pdev, c
static int printed_version = 0;
u8 autoneg, duplex;
u16 speed;
+ u32 advertising;
int i, rc;
assert(pdev != NULL);
@@ -1423,9 +1463,9 @@ rtl8169_init_one(struct pci_dev *pdev, c
mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
}
- rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
+ rtl8169_link_option(board_idx, &autoneg, &speed, &duplex, &advertising);
- rtl8169_set_speed(dev, autoneg, speed, duplex);
+ rtl8169_set_speed(dev, autoneg, speed, duplex, advertising);
if (RTL_R8(PHYstatus) & TBI_Enable)
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
[-- Attachment #3: test.sh --]
[-- Type: application/x-sh, Size: 506 bytes --]
[-- Attachment #4: test.log --]
[-- Type: text/plain, Size: 6348 bytes --]
+ for i in on off
+ ethtool -s eth0 autoneg on speed 10 duplex half
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half
Advertised auto-negotiation: Yes
Speed: 10Mb/s
Duplex: Half
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ ethtool -s eth0 autoneg on speed 10 duplex full
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Full
Advertised auto-negotiation: Yes
Speed: 10Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ ethtool -s eth0 autoneg on speed 100 duplex half
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 100baseT/Half
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Half
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ ethtool -s eth0 autoneg on speed 100 duplex full
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 100baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ ethtool -s eth0 autoneg on speed 1000 duplex full
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 1000baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Half
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: no
+ sleep 10
+ ethtool -s eth0 autoneg on
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ for i in on off
+ ethtool -s eth0 autoneg off speed 10 duplex half
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half
Advertised auto-negotiation: Yes
Speed: 10Mb/s
Duplex: Half
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ ethtool -s eth0 autoneg off speed 10 duplex full
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
Advertised auto-negotiation: Yes
Speed: 10Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ ethtool -s eth0 autoneg off speed 100 duplex half
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 100baseT/Half
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Half
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ ethtool -s eth0 autoneg off speed 100 duplex full
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 100baseT/Half 100baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
+ ethtool -s eth0 autoneg off speed 1000 duplex full
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 1000baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Half
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: no
+ sleep 10
+ ethtool -s eth0 autoneg on
+ sleep 10
+ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Link detected: yes
+ sleep 10
^ permalink raw reply
* [PATCH] e1000: NUMA aware allocation of descriptors V2
From: Christoph Lameter @ 2005-05-27 21:52 UTC (permalink / raw)
To: Andrew Morton; +Cc: Ganesh Venkatesan, davem, linux-kernel, netdev, shai
In-Reply-To: <20050518134250.3ee2703f.akpm@osdl.org>
NUMA awareness for the e1000 driver. Allocate tx and rx descriptors
on the node of the device.
It is safe to replace vmalloc by kmalloc node since only the descriptors
are allocated in a NUMA aware way. These will not be so large that the
use of vmalloc becomes necesssary.
The patch includes a modification to slab.h to revert from inline functions
for kmalloc_node/kmem_cache_alloc_node to a macro so that an undefined variable
may be specified. Is that ok? If so then I probably need to spin a separate
patch just for slab.h.
V1-V2:
- Patch against 2.6.12-rc5-mm1
- Do not defined netdev->node for non NUMA case
- Change kmem_cache_alloc_node and kmalloc_node to fall back to macro
definitions for the non numa case so that an undefined variable can be
specified.
References to earlier discussions:
http://marc.theaimsgroup.com/?t=111638151000001&r=1&w=2
Note that i386 pci_alloc_coherent also needs to be made NUMA aware.
Signed-off-by: Christoph Lameter <christoph@lameter.com>
Signed-off-by: Justin M. Forbes <jmforbes@linuxtx.org>
Signed-off-by: Shai Fultheim <shai@scalex86.org>
Index: linux-2.6.12-rc5/drivers/net/e1000/e1000_main.c
===================================================================
--- linux-2.6.12-rc5.orig/drivers/net/e1000/e1000_main.c 2005-05-27 21:22:39.000000000 +0000
+++ linux-2.6.12-rc5/drivers/net/e1000/e1000_main.c 2005-05-27 21:25:28.000000000 +0000
@@ -567,7 +567,9 @@
netdev->mem_start = mmio_start;
netdev->mem_end = mmio_start + mmio_len;
netdev->base_addr = adapter->hw.io_base;
-
+#ifdef CONFIG_NUMA
+ netdev->node = pcibus_to_node(pdev->bus);
+#endif
adapter->bd_number = cards_found;
/* setup the private structure */
@@ -971,7 +973,9 @@
int size;
size = sizeof(struct e1000_buffer) * txdr->count;
- txdr->buffer_info = vmalloc(size);
+
+ txdr->buffer_info = kmalloc_node(size, GFP_KERNEL, adapter->netdev->node );
+
if(!txdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the transmit descriptor ring\n");
@@ -987,7 +991,7 @@
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
if(!txdr->desc) {
setup_tx_desc_die:
- vfree(txdr->buffer_info);
+ kfree(txdr->buffer_info);
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
@@ -1015,7 +1019,7 @@
DPRINTK(PROBE, ERR,
"Unable to allocate aligned memory "
"for the transmit descriptor ring\n");
- vfree(txdr->buffer_info);
+ kfree(txdr->buffer_info);
return -ENOMEM;
} else {
/* Free old allocation, new allocation was successful */
@@ -1123,7 +1127,8 @@
int size, desc_len;
size = sizeof(struct e1000_buffer) * rxdr->count;
- rxdr->buffer_info = vmalloc(size);
+ rxdr->buffer_info = kmalloc_node(size, GFP_KERNEL, adapter->netdev->node);
+
if(!rxdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
@@ -1134,7 +1139,7 @@
size = sizeof(struct e1000_ps_page) * rxdr->count;
rxdr->ps_page = kmalloc(size, GFP_KERNEL);
if(!rxdr->ps_page) {
- vfree(rxdr->buffer_info);
+ kfree(rxdr->buffer_info);
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
@@ -1144,7 +1149,7 @@
size = sizeof(struct e1000_ps_page_dma) * rxdr->count;
rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL);
if(!rxdr->ps_page_dma) {
- vfree(rxdr->buffer_info);
+ kfree(rxdr->buffer_info);
kfree(rxdr->ps_page);
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
@@ -1166,7 +1171,7 @@
if(!rxdr->desc) {
setup_rx_desc_die:
- vfree(rxdr->buffer_info);
+ kfree(rxdr->buffer_info);
kfree(rxdr->ps_page);
kfree(rxdr->ps_page_dma);
DPRINTK(PROBE, ERR,
@@ -1196,7 +1201,7 @@
DPRINTK(PROBE, ERR,
"Unable to allocate aligned memory "
"for the receive descriptor ring\n");
- vfree(rxdr->buffer_info);
+ kfree(rxdr->buffer_info);
kfree(rxdr->ps_page);
kfree(rxdr->ps_page_dma);
return -ENOMEM;
@@ -1393,7 +1398,7 @@
e1000_clean_tx_ring(adapter);
- vfree(adapter->tx_ring.buffer_info);
+ kfree(adapter->tx_ring.buffer_info);
adapter->tx_ring.buffer_info = NULL;
pci_free_consistent(pdev, adapter->tx_ring.size,
@@ -1473,7 +1478,7 @@
e1000_clean_rx_ring(adapter);
- vfree(rx_ring->buffer_info);
+ kfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
kfree(rx_ring->ps_page);
rx_ring->ps_page = NULL;
Index: linux-2.6.12-rc5/include/linux/netdevice.h
===================================================================
--- linux-2.6.12-rc5.orig/include/linux/netdevice.h 2005-05-27 21:22:39.000000000 +0000
+++ linux-2.6.12-rc5/include/linux/netdevice.h 2005-05-27 21:22:43.000000000 +0000
@@ -279,7 +279,9 @@
unsigned long mem_start; /* shared mem start */
unsigned long base_addr; /* device I/O address */
unsigned int irq; /* device IRQ number */
-
+#ifdef CONFIG_NUMA
+ unsigned int node; /* device node number */
+#endif
/*
* Some hardware also needs these fields, but they are not
* part of the usual set specified in Space.c.
Index: linux-2.6.12-rc5/include/linux/slab.h
===================================================================
--- linux-2.6.12-rc5.orig/include/linux/slab.h 2005-05-25 03:31:20.000000000 +0000
+++ linux-2.6.12-rc5/include/linux/slab.h 2005-05-27 21:30:42.000000000 +0000
@@ -106,14 +106,12 @@
extern void *kmem_cache_alloc_node(kmem_cache_t *, int flags, int node);
extern void *kmalloc_node(size_t size, int flags, int node);
#else
-static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node)
-{
- return kmem_cache_alloc(cachep, flags);
-}
-static inline void *kmalloc_node(size_t size, int flags, int node)
-{
- return kmalloc(size, flags);
-}
+/*
+ * The definitions are macros here to allow the use of an undefined variable
+ * for the node. The variable may only be defined if CONFIG_NUMA is set.
+ */
+#define kmem_cache_alloc_node(__cachep, __flags, __node) kmem_cache_alloc(__cachep, __flags)
+#define kmalloc_node(__size, __flags, __node) kmalloc(__size, __flags)
#endif
extern int FASTCALL(kmem_cache_reap(int));
^ permalink raw reply
* Re: [PATCH] NUMA aware allocation of transmit and receive buffers for e1000
From: Christoph Lameter @ 2005-05-27 21:15 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Andi Kleen, netdev, akpm, shai
In-Reply-To: <428AF378.5020109@cosmosbay.com>
On Wed, 18 May 2005, Eric Dumazet wrote:
> Related question, is pci_alloc_consistent() already NUMA aware ?
Nope. It also ultimately acquires memory via vmalloc.
pci_alloc_consistent will also need some rework to allocate memory
consistent (well the name is coherent right?) with the node that the
device is on. Second case of a need for a node aware vmalloc?
^ permalink raw reply
* Re: RFC: NAPI packet weighting patch
From: Stephen Hemminger @ 2005-05-27 21:01 UTC (permalink / raw)
To: Mitch Williams
Cc: netdev, hadi, Robert.Olsson, Ronciak, John, Venkatesan, Ganesh,
Brandeburg, Jesse
In-Reply-To: <Pine.CYG.4.58.0505271305590.2148@mawilli1-desk2.amr.corp.intel.com>
On Fri, 27 May 2005 13:27:04 -0700
Mitch Williams <mitch.a.williams@intel.com> wrote:
>
> Stephen, Robert, and Jamal all replied to my original message, and all
> said approximately the same thing: "Why don't you just reduce the weight
> in the driver? It does the same thing."
>
> To which I reply, respectfully, I know that. And no it doesn't, not
> exactly.
>
> My primary reason for adding this setting is to allow for runtime tweaking
> -- just like max_backlog has right now. Driver weight is a compile-time
> setting, and has to be changed for every driver that you run.
>
> This setting allows you to scale the weight of all your drivers, at
> runtime, in one place. It's complimentary to Stephen's max_weight idea --
> his patch affects how long you spend in any individual softirq; my patch
> affects how long you spend in any driver's individual NAPI poll routine,
> as well as how long the softirq lasts.
>
Why not just allow adjusting dev->weight via sysfs?
^ permalink raw reply
* Re: [0/10] [IPSEC] IPsec event notification
From: David S. Miller @ 2005-05-27 20:41 UTC (permalink / raw)
To: herbert; +Cc: hadi, kaber, netdev
In-Reply-To: <20050527110730.GA4424@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Fri, 27 May 2005 21:07:30 +1000
> Would it be possible for you to pull the tree at
>
> rsync://rsync.kernel.org/pub/scm/linux/kernel/git/herbert/ipsec-2.6.git/
>
> into your net-2.6.13 tree?
Pulled, thanks Herbert.
^ permalink raw reply
* Re: [patch 2.6.12-rc5] tg3: add bcm5752 entry to pci.ids
From: David S. Miller @ 2005-05-27 20:41 UTC (permalink / raw)
To: jgarzik; +Cc: mchan, linville, linux-kernel, netdev
In-Reply-To: <429785B5.6020705@pobox.com>
From: Jeff Garzik <jgarzik@pobox.com>
Date: Fri, 27 May 2005 16:40:21 -0400
> pci.ids is only used in one location -- deprecated /proc/pci -- and will
> be removed in the next year or so, I imagine. Further, pci.ids is
> periodically sync'd en masse from sourceforge into the kernel by janitors.
Good point.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox