ematch API, u32 ematch, nbyte ematch, basic classifier
Subsystems (3)
RFC 1/1 ematch API, u32 ematch, nbyte ematch, basic classifier
Jamal et al,
I attached 4 patches of a first ematch implementation. Comments and suggestions very much appreciated. Compiles but untested.
Patch 1: ematch API
API visible to classifier:
tcf_em_tree_validate(tp, tlv, tree)
tlv: ematches TLV
tree: temporary struct tcf_ematch_tree
Validates the data in the TLV and builds the ematch tree upon the temporary variable.
tcf_em_tree_change(tp, dst, src)
dst: destination ematch tree (from classifier private data)
src: source ematch tree (temporary tree from _validate)
Replaces the ematch tree in the classifier with the temporary tree.
tcf_em_tree_destroy(tp, tree)
Destroys an ematch tree
tcf_em_tree_dump(skb, tree, tlv_type)
tlv_type: T of ematches TLV (classifier specific)
Dumps the ematch tree to the skb with given tlv_type.
tcf_em_tree_match(skb, tree, res)
res: struct tcf_result *
Macro returning 1 if no ematches are configured, otherwise the tree is evaulated and 1 is returned if the tree matches.
The complete API is also visible if ematch is not configured but will result in empty macros/structures. Those need to be improved though.
API visible to ematches:
tcf_em_register(ops)
tcf_em_unregister(ops)
ematches must at least provide the following callbacks:
change, match
Optional callbacks are: destroy, dump
kind must be set to a unique ID, i thought about declaring 1..2^16 to ematches within the mainline tree and have the rest declared as to be used for private use to avoid collisions.
Patch 2: u32 ematch
Is an ematch based on the existing u32 match but allows to specify the layer and is able to read u32 values if alignment does not allow direct access. Additionally it supports the operands, eq, lt, gt. It is a few ticks slower than the existing match but worth it. However, it does not support the neat nexthdr via hashing as u32 does which is the main problem before u32 can make proper use of it.
Patch 3: nbyte ematch
Compares n bytes at specified offset. To be used for IPv6 address matches to avoid 4 ANDed u32 matches.
Patch 4: Basic Classifier
This is the most basic classifier possible doing nothing more than executing extensions and ematches. It follows the architecture of u32 and fw by storing a filter list in tp->root. This eventually makes fw obsolete once meta ematch is available. I didn't copy the u32/fw code but rather made use of the list.h.
pskbs are completely unhandled so far as I'm still not sure how to do it properly.
Cheers
include/linux/pkt_cls.h +43 -0
@@ -319,4 +319,47 @@#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1) +struct tcf_ematch_tree_hdr +{ +__u16 nmatches; +__u16 progid; +}; + +enum +{ +TCA_EMATCH_TREE_UNSPEC , +TCA_EMATCH_TREE_HDR , +TCA_EMATCH_TREE_LIST , + __TCA_EMATCH_TREE_MAX +}; +#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1) + +struct tcf_ematch_hdr +{ +__u16 handle; +__u16 matchID; +__u16 kind; +__u8 flags; +__u8 pad;/* currently unused */ +}; + +enum +{ +TCF_EM_CONTAINER , + __TCF_EM_MAX +}; + +#define TCF_EM_REL_MASK 3 +#define TCF_EM_REL_VALID (v) \ + (!(((v) & TCF_EM_REL_MASK) == TCF_EM_REL_MASK)) +#define TCF_EM_LAST_KEY (v) (!((v) & TCF_EM_REL_MASK)) + +#define TCF_EM_REL_OBVIOUS (v, r) (TCF_EM_LAST_KEY(v) || \ + (!(r) && ((v) & TCF_EM_REL_AND)) || ((r) && ((v) & TCF_EM_REL_OR))) + +#define TCF_EM_REL_END (1<<0) +#define TCF_EM_REL_AND (1<<1) +#define TCF_EM_REL_OR (1<<2) +#define TCF_EM_INVERT (1<<3) +#endif
include/linux/rtnetlink.h +5 -0
@@ -779,6 +779,11 @@ goto rtattr_failure; \ __rta_fill(skb, attrtype, attrlen, data); }) +#define RTA_PUT_NOHDR (skb, attrlen, data) \ +({ if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \ + goto rtattr_failure; \ + memcpy(skb_put(skb, RTA_ALIGN(attrlen)), data, attrlen); }) +static inline struct rtattr *__rta_reserve (struct sk_buff *skb,int attrtype,int attrlen) {
include/net/pkt_cls.h +69 -0
75 lines not on this page · raw message
net/sched/Kconfig +6 -0
@@ -375,6 +375,12 @@ To compile this code as a module, choose M here: the module will be called cls_rsvp6. +config NET_EMATCH + bool "Extended Matches" + depends on NET_CLS + ---help--- + TODO + config NET_CLS_ACT bool "Packet ACTION" depends on EXPERIMENTAL && NET_CLS && NET_QOS
net/sched/Makefile +1 -0
@@ -33,3 +33,4 @@ obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o +obj-$(CONFIG_NET_EMATCH) += ematch.o
net/sched/ematch.c +300 -0
300 lines not on this page · raw message
include/linux/pkt_cls.h +25 -0
@@ -346,6 +346,7 @@enum {TCF_EM_CONTAINER , +TCF_EM_U32 , __TCF_EM_MAX };
@@ -362,4 +363,28 @@#define TCF_EM_REL_OR (1<<2)#define TCF_EM_INVERT (1<<3) +struct tcf_em_u32 +{ +__u32 val; +__u32 mask; +__u16 off; +__u8 align; +__u8 layer:4 ; +__u8 opnd:4 ; +}; + +enum +{ +TCF_EM_ALIGN_U8 =1 , +TCF_EM_ALIGN_U16 =2 , +TCF_EM_ALIGN_U32 =4 +}; + +enum +{ +TCF_EM_OPND_EQ , +TCF_EM_OPND_GT , +TCF_EM_OPND_LT +}; +#endif
include/net/pkt_cls.h +30 -0
@@ -218,6 +218,36 @@#endif /* CONFIG_NET_EMATCH */ +static inline u32 tcf_read_bucket (u8 *ptr,u8 align) +{ +switch (align) { +case TCF_EM_ALIGN_U8 : +return *ptr; +case TCF_EM_ALIGN_U16 : +return (*ptr <<8 ) | *(ptr+1 ); +case TCF_EM_ALIGN_U32 : +return (*ptr <<24 ) | (*(ptr+1 ) <<16 ) | + (*(ptr+2 ) <<8 ) | *(ptr+3 ); + } +return 0 ; +} + +static inline u8 *tcf_get_base_ptr (struct sk_buff *skb,u8 layer) +{ +switch (layer) { +case 0 : +return skb->data; +case 1 : +return skb->nh.raw; +case 2 : +return skb->h.raw; + } +return NULL ; +} + +#define tcf_valid_offset (skb, ptr, off, len) \ + ((ptr + off + len) < skb->tail && (ptr + off) > skb->head) +#ifdef CONFIG_NET_CLS_IND static inline int tcf_change_indev (struct tcf_proto *tp,char *indev,struct rtattr *indev_tlv)
net/sched/Kconfig +6 -0
@@ -381,6 +381,12 @@ ---help--- TODO +config NET_EMATCH_U32 + tristate "U32" + depends on NET_EMATCH + ---help--- + TODO + config NET_CLS_ACT bool "Packet ACTION" depends on EXPERIMENTAL && NET_CLS && NET_QOS
net/sched/Makefile +1 -0
@@ -34,3 +34,4 @@ obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o obj-$(CONFIG_NET_EMATCH) += ematch.o +obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o
net/sched/em_u32.c +98 -0
98 lines not on this page · raw message
include/linux/pkt_cls.h +8 -0
@@ -347,6 +347,7 @@ {TCF_EM_CONTAINER ,TCF_EM_U32 , +TCF_EM_NBYTE , __TCF_EM_MAX };
@@ -387,4 +388,11 @@TCF_EM_OPND_LT }; +struct tcf_em_nbyte +{ +__u16 off; +__u16 len:12 ; +__u8 layer:4 ; +}; +#endif
net/sched/Kconfig +6 -0
@@ -387,6 +387,12 @@ ---help--- TODO +config NET_EMATCH_NBYTE + tristate "N-Byte" + depends on NET_EMATCH + ---help--- + TODO + config NET_CLS_ACT bool "Packet ACTION" depends on EXPERIMENTAL && NET_CLS && NET_QOS
net/sched/Makefile +1 -0
@@ -35,3 +35,4 @@ obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o obj-$(CONFIG_NET_EMATCH) += ematch.o obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o +obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
net/sched/em_nbyte.c +95 -0
95 lines not on this page · raw message
include/linux/pkt_cls.h +14 -0
@@ -319,6 +319,20 @@#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1) +/* Basic filter */ + +enum +{ +TCA_BASIC_UNSPEC , +TCA_BASIC_CLASSID , +TCA_BASIC_EMATCHES , +TCA_BASIC_ACT , +TCA_BASIC_POLICE , + __TCA_BASIC_MAX +}; + +#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1) +struct tcf_ematch_tree_hdr {__u16 nmatches;
net/sched/Kconfig +6 -0
@@ -269,6 +269,12 @@ Documentation and software is at <http://diffserv.sourceforge.net/>. +config NET_CLS_BASIC + tristate "Basic classifier" + depends on NET_CLS + ---help--- + TODO + config NET_CLS_TCINDEX tristate "TC index classifier" depends on NET_CLS
net/sched/Makefile +1 -0
@@ -33,6 +33,7 @@ obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o +obj-$(CONFIG_NET_CLS_BASIC) += cls_basic.o obj-$(CONFIG_NET_EMATCH) += ematch.o obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
net/sched/cls_basic.c +300 -0
300 lines not on this page · raw message
Quoted 7 lines · Thomas Graf
Jamal et al,
I attached 4 patches of a first ematch implementation. Comments and suggestions very much appreciated. Compiles but untested.
Patch 1: ematch API
Quoted 8 lines
API visible to classifier:
tcf_em_tree_validate(tp, tlv, tree)
tlv: ematches TLV
tree: temporary structtcf_ematch_treeValidates the data in the TLV and builds the ematch tree upon the temporary variable.
struct tcf_ematch_hdr
{
__u16 handle;
__u16 matchID;
__u16 kind;
__u8 flags;
__u8 pad; /* currently unused */
};you need both matchID and handle?
struct tcf_ematch
{
struct tcf_ematch_hdr hdr;
struct tcf_ematch_ops * ops;
unsigned long data;
};Both tcf_ematch_ops and tcf_ematch_hdr have kind;
Is data length stored somewhere?
Noticed indev still hanging there ;-> shouldnt that die by this patch?
Quoted 6 lines
tcf_em_tree_change(tp, dst, src)
dst: destination ematch tree (from classifier private data)
src: source ematch tree (temporary tree from_validate)Replaces the ematch tree in the classifier with the temporary tree.
Seems to assume some owner of the ematch other than mother classifier. Recall the idea of ownership by classifier we discussed earlier which should be default if the ematch doesnt implement a ->change()
BTW, Is the assumption i can have a u32:
match
ematch
match
match
ematch
now gone? I couldnt tell.
Quoted 7 lines
tcf_em_tree_destroy(tp, tree)
Destroys an ematch tree
tcf_em_tree_dump(skb, tree, tlv_type)
tlv_type: T of ematches TLV (classifier specific)Dumps the ematch tree to the skb with given
tlv_type.
Same comments as in ->change().
if ematch doesnt implement a destroy or dump then mother classifier is responsible.
Quoted 5 lines
tcf_em_tree_match(skb, tree, res)
res: structtcf_result*Macro returning 1 if no ematches are configured, otherwise the tree is evaulated and 1 is returned if the tree matches.
I think that looks valid for simplicty case. I wasnt so sure about the INVERT thing you had. It doesnt look like a bad idea, just different from what i had in mind (where you let the ematch worry about inversion).
Quoted 11 lines
The complete API is also visible if ematch is not configured but will result in empty macros/structures. Those need to be improved though.
API visible to ematches:
tcf_em_register(ops)
tcf_em_unregister(ops)ematches must at least provide the following callbacks:
Quoted 7 lines
change, match
Optional callbacks are: destroy, dump
kind must be set to a unique ID, i thought about declaring 1..2^16 to ematches within the mainline tree and have the rest declared as to be used for private use to avoid collisions.
With std actions also this was an issue - at the moment dont have anything in any headers just to make it free for all - This way you could write a simple module that has zero dependency on an already compiled kernel. There would be standard practise where say 11 would mean something - but i suggest not to enforce it; the register() should probably spit some helpful message of who already has the number. you are trying to grab.
Quoted 9 lines
Patch 2: u32 ematch
Is an ematch based on the existing u32 match but allows to specify the layer and is able to read u32 values if alignment does not allow direct access. Additionally it supports the operands, eq, lt, gt. It is a few ticks slower than the existing match but worth it. However, it does not support the neat nexthdr via hashing as u32 does which is the main problem before u32 can make proper use of it.
It does emulate a u32 node but not the classifier - which is a _lot_ more sophisticated (with multilevel trees of hashes etc). Maybe you should change its name to something like 32bit match.
Quoted 4 lines
Patch 3: nbyte ematch
Compares n bytes at specified offset. To be used for IPv6 address matches to avoid 4 ANDed u32 matches.
This looks useful.
My recommendation would be to have the metamatch as the first thing so we can kill indev and friends.
Quoted 7 lines
Patch 4: Basic Classifier
This is the most basic classifier possible doing nothing more than executing extensions and ematches. It follows the architecture of u32 and fw by storing a filter list in
tp->root. This eventually makes fw obsolete once meta ematch is available. I didn't copy the u32/fw code but rather made use of thelist.h.
Very inefficient, but serves the purpose of an example. [Even if you go as basic a hash as fw classifier you will do better]
Quoted 2 lines
pskbs are completely unhandled so far as I'm still not sure how to do it properly.
Given where we are doing these things (egress and ingress of stack) we would mostly be fine (unlike netfilter).
cheers,
jamal
* jamal <[email protected]> 2005-01-03 23:13
Quoted 10 lines
struct
tcf_ematch_hdr{ __u16 handle; __u16 matchID; __u16 kind; __u8 flags; __u8 pad; /* currently unused */ };you need both matchID and handle?
No, handle is yet unused and I think we can screw it again.
Quoted 1 line
Both
tcf_ematch_opsandtcf_ematch_hdrhave kind;
Correct, I wanted to avoid having to do transformations but it would save us a few bits.
Quoted 1 line
Is data length stored somewhere?
Not in this patch as it wasn't needed, I added it to my local tree yesterday though. It is indeed required if we allocate in the ematch api instead of having the ematch doing it.
Quoted 1 line
Noticed indev still hanging there ;-> shouldnt that die by this patch?
As soon as I find the time to write the meta ematch.
Quoted 10 lines
Quoted 6 lines
tcf_em_tree_change(tp, dst, src)
dst: destination ematch tree (from classifier private data)
src: source ematch tree (temporary tree from_validate)Replaces the ematch tree in the classifier with the temporary tree.
Seems to assume some owner of the ematch other than mother classifier. Recall the idea of ownership by classifier we discussed earlier which should be default if the ematch doesnt implement a ->change()
The classifier must always be the owner. Splitting the vaildation and changing into 2 separate functions makes it easy for the classifier to stay consistent while changing without doing expensive error recovery.
Quoted 8 lines
BTW, Is the assumption i can have a u32:
match
ematch
match
match
ematchnow gone? I couldnt tell.
I can't tell you either but not really. It's still possible but I'm not sure if it makes sense. My idea was to replace match with ematch so it would benefit from logic relations. The problem arises when we get to the nexthdr offset mangling.
I have to look into this but I might have to drop my idea and do as you state above.
Quoted 11 lines
Quoted 7 lines
tcf_em_tree_destroy(tp, tree)
Destroys an ematch tree
tcf_em_tree_dump(skb, tree, tlv_type)
tlv_type: T of ematches TLV (classifier specific)Dumps the ematch tree to the skb with given
tlv_type.Same comments as in ->change().
if ematch doesnt implement a destroy or dump then mother classifier is responsible.
Right, I changed this already. change/dump/destroy are fully optional. Here's the latest API to the classifier:
change() (Optional)
Called if provided, otherwise ematch api allocates the data, stores it in m->data and sets m->datalen. Special Case: If TCF_EM_SIMPLE is set the ematch data consists of a simple u32 which means no allocation is required and the value is stored in m->data directly.
Note: I might add a special field to ematch_ops which can be set to the expected length of the ematch data so we have at least some basic sanity check. Thoughts?
match() (Must)
...
destroy() (Optional)
Called if provided, otheriwse m->data is freed in ematch api unless TCF_EM_SIMPLE is set.
dump() (Optional)
Called if provided, otherwise m->data is dumped onto the skb with m->datalen as L. Special handling again for TCF_EM_SIMPLE.
I think this makes it as simple as it can get while keeping the door open for complex ematches such as meta ematch.
Quoted 7 lines
With std actions also this was an issue - at the moment dont have anything in any headers just to make it free for all - This way you could write a simple module that has zero dependency on an already compiled kernel. There would be standard practise where say 11 would mean something - but i suggest not to enforce it; the
register()should probably spit some helpful message of who already has the number. you are trying to grab.
The warning is a good idea. I don't want to enforce it, a comment is just fine and it's up to you whehter you want to fix your ematch everyime a new ematch makes it into the kernel. I added this comment:
/* Ematch type assignments
* 1..32767 Reserved for ematches inside kernel tree
* 32768..65535 Free to use, not reliable
*/
Quoted 5 lines
Quoted 1 line
Patch 2: u32 ematch
It does emulate a u32 node but not the classifier - which is a _lot_ more sophisticated (with multilevel trees of hashes etc). Maybe you should change its name to something like 32bit match.
Agreed. Note: With the latest API everything except for match can be screwed. Same for em_nbyte.
Quoted 8 lines
Quoted 4 lines
Patch 3: nbyte ematch
Compares n bytes at specified offset. To be used for IPv6 address matches to avoid 4 ANDed u32 matches.
This looks useful.
My recommendation would be to have the metamatch as the first thing so we can kill indev and friends.
Right, but those were easy to write in in interruptive working enviroment and somewhat validated the API. meta ematch will take some time to write but it sure has top priority.
Quoted 4 lines
Quoted 1 line
Patch 4: Basic Classifier
Very inefficient, but serves the purpose of an example. [Even if you go as basic a hash as fw classifier you will do better]
Fully agreed, nevertheless I think something like this is required to fill the gaps of u32 and fw.
Quoted 11 lines · Thomas Graf
* jamal <[email protected]> 2005-01-03 23:13
Right, I changed this already. change/dump/destroy are fully optional. Here's the latest API to the classifier:
change()(Optional)
Called if provided, otherwise ematch api allocates the data, stores it inm->dataand setsm->datalen. Special Case: IfTCF_EM_SIMPLEis set the ematch data consists of a simple u32 which means no allocation is required and the value is stored inm->datadirectly.
Quoted 3 lines
Note: I might add a special field to
ematch_opswhich can be set to the expected length of the ematch data so we have at least some basic sanity check. Thoughts?
My thinking is:
It doesnt have to be simple 32 bit data.
If i pass you a struct and tell you what length it is, then you as the classifier dont know need to know anything about it. You just store mystruct as data and datalen from the TLV. you then pass the datastruct to match() - Of course the match() will have to know what that struct means.
Quoted 6 lines
match()(Must)
...
destroy()(Optional)
Called if provided, otheriwsem->datais freed in ematch api unlessTCF_EM_SIMPLEis set.
Again using the above logic, destroy becomes just kfree(mystruct)
Quoted 3 lines
dump()(Optional)
Called if provided, otherwisem->datais dumped onto the skb withm->datalenas L. Special handling again forTCF_EM_SIMPLE.
and dump becomes a matter of looking at datalen and encapsulating mystruct in a TLV without thinking about what the content is.
Quoted 2 lines
I think this makes it as simple as it can get while keeping the door open for complex ematches such as meta ematch.
Agreed.
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
Patch 4: Basic Classifier
Very inefficient, but serves the purpose of an example. [Even if you go as basic a hash as fw classifier you will do better]
Fully agreed, nevertheless I think something like this is required to fill the gaps of u32 and fw.
agreed.
cheers,
jamal
* jamal <[email protected]> 2005-01-04 08:19
Quoted 10 lines · Thomas Graf
Quoted 1 line
change()(Optional)My thinking is:
It doesnt have to be simple 32 bit data.
If i pass you a struct and tell you what length it is, then you as the classifier dont know need to know anything about it. You just store mystruct as data and datalen from the TLV. you then pass the datastruct tomatch()- Of course thematch()will have to know what that struct means.
That's exactly how it is, basically the logic is:
if (ops->change) {
err = ops->change(tp, data, datalen, m);
if (err < 0)
goto errout;
} else if (datalen > 0) {
if (mh->flags & TCF_EM_SIMPLE) {
if (datalen != sizeof(u32))
goto errout;
m->data = *(u32 *) data;
} else {
void *v = kmalloc(datalen, GFP_KERNEL);
if (v == NULL) {
err = -ENOBUFS;
goto errout;
}
memcpy(v, data, datalen);
m->data = (unsigned long) v;
}
}
m->datalen = datalen;Quoted 5 lines
Quoted 3 lines
destroy()(Optional)
Called if provided, otheriwsem->datais freed in ematch api unlessTCF_EM_SIMPLEis set.Again using the above logic, destroy becomes just kfree(mystruct)
Right, that's exactly how it is
if (m->ops->destroy) m->ops->destroy(tp, m); else if (!(m->hdr.flags & TCF_EM_SIMPLE) && m->data) kfree((void *) m->data);
Quoted 6 lines
Quoted 3 lines
dump()(Optional)
Called if provided, otherwisem->datais dumped onto the skb withm->datalenas L. Special handling again forTCF_EM_SIMPLE.and dump becomes a matter of looking at datalen and encapsulating mystruct in a TLV without thinking about what the content is.
Absolutely true, you know about the code before you read it ;->
if (m->ops->dump) {
if (m->ops->dump(skb, m) < 0)
goto rtattr_failure;
} else if (m->hdr.flags & TCF_EM_SIMPLE) {
u32 u = m->data;
RTA_PUT_NOHDR(skb, sizeof(u32), &u);
} else if (m->datalen > 0)
RTA_PUT_NOHDR(skb, m->datalen, (void *) m->data);* jamal <[email protected]> 2005-01-03 23:13
Quoted 5 lines · Thomas Graf
Quoted 1 line
Patch 4: Basic Classifier
Very inefficient, but serves the purpose of an example. [Even if you go as basic a hash as fw classifier you will do better]
Might be worth to mention the motivation for this. fw and u32 will definitely perform much better on complex setups but many do not use u32 hashing not to mention even understand it or have large nfmark -> classid fw maps.
Many use u32 to match simple stuff as port numbers, dscp values or ip subnet addresses and create a new filter for every port/dscp value and for every address. Some even use temporary classes to emulate logic relations and this gets really slow. I have to get numbers first but a single basic filter with ORed matches is probably faster than a separate u32 filter for every case. Sure, once u32 has ematch support it gets better and the hashing shouldn't have too much influence even if it's unused.. We can see what to do once u32 can handle ematches.
Quoted 9 lines · Thomas Graf
* jamal <[email protected]> 2005-01-03 23:13
Quoted 2 lines
Very inefficient, but serves the purpose of an example. [Even if you go as basic a hash as fw classifier you will do better]
Might be worth to mention the motivation for this. fw and u32 will definitely perform much better on complex setups but many do not use u32 hashing not to mention even understand it or have large nfmark -> classid fw maps.
agreed.
Quoted 6 lines
Many use u32 to match simple stuff as port numbers, dscp values or ip subnet addresses and create a new filter for every port/dscp value and for every address. Some even use temporary classes to emulate logic relations and this gets really slow. I have to get numbers first but a single basic filter with ORed matches is probably faster than a separate u32 filter for every case.
I am pretty sure someone who knows u32 well can outperform you (in the scenarios where u32 works using AND etc).
Start hitting 50K rules then lets talk ;->
Quoted 4 lines
Sure, once u32
has ematch support it gets better and the hashing shouldn't have too much influence even if it's unused.. We can see what to do once u32 can handle ematches.
If your intent is to write an ematch holder, then it would be worth to at least go as far as making it some basic hash - as basic as fw does; where collision leads toa linked list. If it is just to show an example, then it is fine.
cheers,
jamal
* jamal <[email protected]> 2005-01-04 08:22
Quoted 11 lines · Thomas Graf
Quoted 6 lines
Many use u32 to match simple stuff as port numbers, dscp values or ip subnet addresses and create a new filter for every port/dscp value and for every address. Some even use temporary classes to emulate logic relations and this gets really slow. I have to get numbers first but a single basic filter with ORed matches is probably faster than a separate u32 filter for every case.
I am pretty sure someone who knows u32 well can outperform you (in the scenarios where u32 works using AND etc).
Start hitting 50K rules then lets talk ;->
Sure but I'd call a filter with 50K ANDed rules an unlikely scenario ;-> In most cases logic will beat brute force. I used to have a u32 setup with 4K matches and hashing, it was not only error prone but could be replaced with 12 egp filters gaining 90kpps. Why's that? Simply because it was easier to optimize the logic behind it. egp itself is terribly slow compared to u32.
Quoted 4 lines
If your intent is to write an ematch holder, then it would be worth to at least go as far as making it some basic hash - as basic as fw does; where collision leads toa linked list. If it is just to show an example, then it is fine.
Using what key? We have no knowledge about what the ematches want to see or not.
Quoted 8 lines · Thomas Graf
* jamal <[email protected]> 2005-01-04 08:22
Quoted 5 lines · Thomas Graf
I am pretty sure someone who knows u32 well can outperform you (in the scenarios where u32 works using AND etc).
Start hitting 50K rules then lets talk ;->Sure but I'd call a filter with 50K ANDed rules an unlikely scenario ;->
50K matches is probably senseless - i was talking about rules (which contain matches).
Quoted 5 lines
In most cases logic will beat brute force. I used to have a u32 setup with 4K matches and hashing, it was not only error prone but could be replaced with 12 egp filters gaining 90kpps. Why's that? Simply because it was easier to optimize the logic behind it. egp itself is terribly slow compared to u32.
I think this is a debate that can be easily settled ;-> Agreed logic will beat brute force smartness and u32 is not exactly for the faint hearted. And its usability is extremely poor - but lets maintain its power as is.
Quoted 7 lines
Quoted 4 lines
If your intent is to write an ematch holder, then it would be worth to at least go as far as making it some basic hash - as basic as fw does; where collision leads toa linked list. If it is just to show an example, then it is fine.
Using what key? We have no knowledge about what the ematches want to see or not.
Ok, good question ;->
Maybe you should have own some 32 bit key?
cheers,
jamal
* jamal <[email protected]> 2005-01-04 21:54
Quoted 4 lines
I think this is a debate that can be easily settled ;-> Agreed logic will beat brute force smartness and u32 is not exactly for the faint hearted. And its usability is extremely poor - but lets maintain its power as is.
Absolutely.
Quoted 5 lines
Quoted 2 lines
Using what key? We have no knowledge about what the ematches want to see or not.
Ok, good question ;->
Maybe you should have own some 32 bit key?
Actually the goal of basic is to be an alternative to u32 if hashing is not required because I think adding hashing will simply result in a duplication of u32.
Updated patch with the following changes (still untested)
* destroy/dump/change are not optional (only match is required)
* ematch can set datalen in ematch_ops to have the ematch api do a data length sanity check. (to at least avoid bogus memory refs)
* better nop macros if ematch is not enabled
* TCF_EM_SIMPLE flag which marks an ematch config as simple, meaning that the data consists of a u32 value.
* API documentation
* removed handle from ematch_hdr
* userspace visible ematch header is no longer used in ematch tree and the attributes are copied now to avoid duplications such as kind.
* suggestion comment to use a kind > 2^15 for private/temporary ematches to avoid collisions on kernel upgrades
* some minor cosmetic fixes to make code look more pretty
* renamed tcf_em_tree_change to tcf_em_tree_replace, it gives a better impression on what is being done
Jamal, I know it's still not simple enough for you but can you live with it? ;->
include/linux/pkt_cls.h +47 -0
@@ -319,4 +319,51 @@#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1) +struct tcf_ematch_tree_hdr +{ +__u16 nmatches; +__u16 progid; +}; + +enum +{ +TCA_EMATCH_TREE_UNSPEC , +TCA_EMATCH_TREE_HDR , +TCA_EMATCH_TREE_LIST , + __TCA_EMATCH_TREE_MAX +}; +#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1) + +struct tcf_ematch_hdr +{ +__u16 matchID; +__u16 kind; +__u16 flags; +__u16 pad;/* currently unused */ +}; + +/* Ematch type assignments +* 1..32767 Reserved for ematches inside kernel tree +* 32768..65535 Free to use, not reliable +*/ +enum +{ +TCF_EM_CONTAINER , + __TCF_EM_MAX +}; + +#define TCF_EM_REL_MASK 3 +#define TCF_EM_REL_VALID (v) \ + (!(((v) & TCF_EM_REL_MASK) == TCF_EM_REL_MASK)) +#define TCF_EM_LAST_KEY (v) (!((v) & TCF_EM_REL_MASK)) + +#define TCF_EM_REL_OBVIOUS (v, r) (TCF_EM_LAST_KEY(v) || \ + (!(r) && ((v) & TCF_EM_REL_AND)) || ((r) && ((v) & TCF_EM_REL_OR))) + +#define TCF_EM_REL_END (1<<0) +#define TCF_EM_REL_AND (1<<1) +#define TCF_EM_REL_OR (1<<2) +#define TCF_EM_INVERT (1<<3) +#define TCF_EM_SIMPLE (1<<4) +#endif
include/linux/rtnetlink.h +5 -0
@@ -779,6 +779,11 @@ goto rtattr_failure; \ __rta_fill(skb, attrtype, attrlen, data); }) +#define RTA_PUT_NOHDR (skb, attrlen, data) \ +({ if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \ + goto rtattr_failure; \ + memcpy(skb_put(skb, RTA_ALIGN(attrlen)), data, attrlen); }) +static inline struct rtattr *__rta_reserve (struct sk_buff *skb,int attrtype,int attrlen) {
include/net/pkt_cls.h +121 -0
127 lines not on this page · raw message
net/sched/Kconfig +13 -0
@@ -375,6 +375,19 @@ To compile this code as a module, choose M here: the module will be called cls_rsvp6. +config NET_EMATCH + bool "Extended Matches" + depends on NET_CLS + ---help--- + Say Y here if you want to use extended matches on top of classifiers + and select the extended matches below. + + Extended matches are small classification helpers not worth writing + a separate classifier. + + You must have a recent version of the iproute2 tools in order to use + extended matches. + config NET_CLS_ACT bool "Packet ACTION" depends on EXPERIMENTAL && NET_CLS && NET_QOS
net/sched/Makefile +1 -0
@@ -33,3 +33,4 @@ obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o +obj-$(CONFIG_NET_EMATCH) += ematch.o
net/sched/ematch.c +396 -0
396 lines not on this page · raw message
Quoted 2 lines · Thomas Graf
*
TCF_EM_SIMPLEflag which marks an ematch config as simple, meaning that the data consists of a u32 value.
This is 1 of 2 parts i think thats still an issue; otherwise looks very good.
Why do i need to signal something as simple? AND why does it have to be 32 bit type - what edge does that give you?
I should be able to specify a struct with two 32 bits and encap it in a TLV and the classifier can treat it the same way - it knows the type and length - thats sufficient to create, destroy and dump.
The other issue is still on the ematch/match interleaving i.e i should be able to say something along the lines:
//simple slammer-worm or code-red ACL detector rule //using u32 classifier and ematches
(match ip protocol udp port 1434 AND
ematch packetlen minsize 404 maxsize 404) OR (match ip protocol tcp http AND
ematch urlscanner "*.ida")
action ipt -j ULOG "Virus detected and dropped" action drop
Not a very good example - but you can see how powerfull this is when you can quickly use a string scanner such as the one you have as an ematch while maintaining u32 as is.
cheers,
jamal
* jamal <[email protected]> 2005-01-04 22:12
Quoted 9 lines · Thomas Graf
Quoted 3 lines
*
TCF_EM_SIMPLEflag which marks an ematch config as simple, meaning that the data consists of a u32 value.This is 1 of 2 parts i think thats still an issue; otherwise looks very good.
Why do i need to signal something as simple? AND why does it have to be 32 bit type - what edge does that give you?
You don't have to, providing a 32bit data chunk without TCF_EM_SIMPLE set will simply result in allocating & copy. It's an optimization, nothing more.
Quoted 4 lines
I should be able to specify a struct with two 32 bits and encap it in a TLV and the classifier can treat it the same way - it knows the type and length - thats sufficient to create, destroy and dump.
Correct, maybe you're right and I should drop it again.
Quoted 12 lines
The other issue is still on the ematch/match interleaving i.e i should be able to say something along the lines:
//simple slammer-worm or code-red ACL detector rule //using u32 classifier and ematches
(match ip protocol udp port 1434 AND
ematch packetlen minsize 404 maxsize 404) OR (match ip protocol tcp http AND
ematch urlscanner "*.ida")
action ipt -j ULOG "Virus detected and dropped" action drop
Quoted 3 lines
Not a very good example - but you can see how powerfull this is when you can quickly use a string scanner such as the one you have as an ematch while maintaining u32 as is.
Basically you could do that already with the basic classifier but I understand your concern and it would be neat to benefit from u32's hashing. There are 2 options:
1) We make u32 hold multiple ematch trees, a u32 key can be of 3
kinds: u32/ematch/container. It's kind of a hack and not very fast due to a lot of stack movement.
2) We make the existing u32 match be an ematch which I already did expect for the nexthdr bits. That is the select will simply be replaced by an ematch tree. I'll take a look into how we could have the classifier take influence on the ematches config data. One possibiliy is to have a struct transfered via map which contains useful data such as offset to next header (u32/rsvp). I have to think about this a little more though.
Personally I'm all for 2) because it's just cleaner and easier to maintain. It's probably the best to not to use the u32 ematch I wrote (which I renamed to cmp) but to write a new one behaving exactly the same as the existing u32 match.
Attached cmp ematch (formerly u32), it was on diet for a while and is quite smallish now.
include/linux/pkt_cls.h +25 -0
@@ -349,6 +349,7 @@enum {TCF_EM_CONTAINER , +TCF_EM_CMP , __TCF_EM_MAX };
@@ -366,4 +367,28 @@#define TCF_EM_INVERT (1<<3)#define TCF_EM_SIMPLE (1<<4) +struct tcf_em_cmp +{ +__u32 val; +__u32 mask; +__u16 off; +__u8 align; +__u8 layer:4 ; +__u8 opnd:4 ; +}; + +enum +{ +TCF_EM_ALIGN_U8 =1 , +TCF_EM_ALIGN_U16 =2 , +TCF_EM_ALIGN_U32 =4 +}; + +enum +{ +TCF_EM_OPND_EQ , +TCF_EM_OPND_GT , +TCF_EM_OPND_LT +}; +#endif
include/net/pkt_cls.h +30 -0
@@ -270,6 +270,36 @@#endif /* CONFIG_NET_EMATCH */ +static inline u32 tcf_read_bucket (u8 *ptr,u8 align) +{ +switch (align) { +case TCF_EM_ALIGN_U8 : +return *ptr; +case TCF_EM_ALIGN_U16 : +return (*ptr <<8 ) | *(ptr+1 ); +case TCF_EM_ALIGN_U32 : +return (*ptr <<24 ) | (*(ptr+1 ) <<16 ) | + (*(ptr+2 ) <<8 ) | *(ptr+3 ); + } +return 0 ; +} + +static inline u8 *tcf_get_base_ptr (struct sk_buff *skb,u8 layer) +{ +switch (layer) { +case 0 : +return skb->data; +case 1 : +return skb->nh.raw; +case 2 : +return skb->h.raw; + } +return NULL ; +} + +#define tcf_valid_offset (skb, ptr, off, len) \ + ((ptr + off + len) < skb->tail && (ptr + off) > skb->head) +#ifdef CONFIG_NET_CLS_IND static inline int tcf_change_indev (struct tcf_proto *tp,char *indev,struct rtattr *indev_tlv)
net/sched/Kconfig +10 -0
@@ -388,6 +388,16 @@ You must have a recent version of the iproute2 tools in order to use extended matches. +config NET_EMATCH_CMP + tristate "Simple packet data comparison" + depends on NET_EMATCH + ---help--- + Say Y here if you want to be able to classify packets based on + simple packet data comparisons for 8, 16, and 32bit values. + + To compile this code as a module, choose M here: the + module will be called em_cmp. + config NET_CLS_ACT bool "Packet ACTION" depends on EXPERIMENTAL && NET_CLS && NET_QOS
net/sched/Makefile +1 -0
@@ -34,3 +34,4 @@ obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o obj-$(CONFIG_NET_EMATCH) += ematch.o +obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o
net/sched/em_cmp.c +66 -0
66 lines not on this page · raw message
Quoted 8 lines · Thomas Graf
* jamal <[email protected]> 2005-01-04 22:12
Quoted 2 lines
Why do i need to signal something as simple? AND why does it have to be 32 bit type - what edge does that give you?
You don't have to, providing a 32bit data chunk without
TCF_EM_SIMPLEset will simply result in allocating & copy. It's an optimization, nothing more.
Sorry i missed that. Isnt it still unecessary though? You should be able to pass L=4 and not need the speacial treatment, no?
Quoted 10 lines
Quoted 3 lines
Not a very good example - but you can see how powerfull this is when you can quickly use a string scanner such as the one you have as an ematch while maintaining u32 as is.
Basically you could do that already with the basic classifier but I understand your concern and it would be neat to benefit from u32's hashing. There are 2 options:
1) We make u32 hold multiple ematch trees, a u32 key can be of 3
kinds: u32/ematch/container. It's kind of a hack and not very fast due to a lot of stack movement.
Indeed this is what i was thinking of.
The only added overhead I can think of is when processing a series of u32 keys _within the same selector_ (not across selectors), you check if its u32 native and execute localy (as is done now) or transfer the check to the ematch defined in that key and continue to next key based on the ematchs return code + the logical operation.
Quoted 7 lines
2) We make the existing u32 match be an ematch which I already did expect for the nexthdr bits. That is the select will simply be replaced by an ematch tree. I'll take a look into how we could have the classifier take influence on the ematches config data. One possibiliy is to have a struct transfered via map which contains useful data such as offset to next header (u32/rsvp). I have to think about this a little more though.
This could be done in addition to #1. I see #1 as more important for u32 but not so for things like fwmark, tcindex which should fizzle away with meta ematch. I think the danger is in trying to replicate u32 as an ematch; if somehow you can loop back and use the real u32 code, then fine. I feel it being non-trivial to do so.
Like i said earlier, theres a lot of power in u32 other than in basic matching.
Quoted 2 lines
Personally I'm all for 2) because it's just cleaner and easier to maintain.
Aha, thats why we were not converging then ;->
I think #2 is better for other classifiers which were already doomed anyways. #1 is important for u32 and perhaps other classifiers like rsvp and route. And yes, #1 is more work ;->
Quoted 4 lines
It's probably the best to not to use the u32 ematch I wrote (which I renamed to cmp) but to write a new one behaving exactly the same as the existing u32 match.
hang on:-> No dont rewrite u32 please. Your cmp is good for the basic matches that u32 does, but is _nowhere_ close to being able to do what u32 can when used properly.
Quoted 2 lines
Attached cmp ematch (formerly u32), it was on diet for a while and is quite smallish now.
Looks very appetizing. Two general comments:
include/linux/pkt_cls.h line 354
Quoted 10 lines
diff -Nru
linux-2.6.10-bk6.orig/include/linux/pkt_cls.hlinux-2.6.10-bk6/include/linux/pkt_cls.hinclude/linux/pkt_cls.h +1
-0@@ -349,6 +349,7 @@enum {TCF_EM_CONTAINER , +TCF_EM_CMP , __TCF_EM_MAX };
I Should be able to compile a new ematch as a module in an already running kernel. So, other than generic stuff for ematches, things like TCF_EM_CMP should not be in that enumeration.
Quoted 18 lines
include/linux/pkt_cls.h +14
-0@@ -366,4 +367,28 @@#define TCF_EM_INVERT (1<<3)#define TCF_EM_SIMPLE (1<<4) +struct tcf_em_cmp +{ +__u32 val; +__u32 mask; +__u16 off; +__u8 align; +__u8 layer:4 ; +__u8 opnd:4 ; +}; + +enum +{ +TCF_EM_ALIGN_U8 =1 , +TCF_EM_ALIGN_U16 =2 ,
include/linux/pkt_cls.h line 393
Quoted 10 lines
include/linux/pkt_cls.h +10
-0+ TCF_EM_ALIGN_U32 = 4 +}; + +enum +{ +TCF_EM_OPND_EQ , +TCF_EM_OPND_GT , +TCF_EM_OPND_LT +}; +
Which means the above should go in its own file; probably create a include/linux/tc_ematch directory with a file of sort tcf_em_cmp.h which holds all the above.
Quoted 28 lines
include/linux/pkt_cls.h +0
-0#endif diff -Nru
linux-2.6.10-bk6.orig/include/net/pkt_cls.hlinux-2.6.10-bk6/include/net/pkt_cls.hinclude/net/pkt_cls.h +20
-0@@ -270,6 +270,36 @@#endif /* CONFIG_NET_EMATCH */ +static inline u32 tcf_read_bucket (u8 *ptr,u8 align) +{ +switch (align) { +case TCF_EM_ALIGN_U8 : +return *ptr; +case TCF_EM_ALIGN_U16 : +return (*ptr <<8 ) | *(ptr+1 ); +case TCF_EM_ALIGN_U32 : +return (*ptr <<24 ) | (*(ptr+1 ) <<16 ) | + (*(ptr+2 ) <<8 ) | *(ptr+3 ); + } +return 0 ; +} + +static inline u8 *tcf_get_base_ptr (struct sk_buff *skb,u8 layer) +{ +switch (layer) { +case 0 : +return skb->data; +case 1 :
include/net/pkt_cls.h line 302
Quoted 10 lines
include/net/pkt_cls.h +10
-0+return skb->nh.raw; +case 2 : +return skb->h.raw; + } +return NULL ; +} + +#define tcf_valid_offset (skb, ptr, off, len) \ + ((ptr + off + len) < skb->tail && (ptr + off) > skb->head) +
And all this also goes in that header file as well.
cheers,
jamal
* jamal <[email protected]> 2005-01-05 08:33
Quoted 6 lines · Thomas Graf
Quoted 5 lines
* jamal <[email protected]> 2005-01-04 22:12
Quoted 2 lines
Why do i need to signal something as simple? AND why does it have to be 32 bit type - what edge does that give you?
Quoted 6 lines
Quoted 3 lines
You don't have to, providing a 32bit data chunk without
TCF_EM_SIMPLEset will simply result in allocating & copy. It's an optimization, nothing more.Sorry i missed that. Isnt it still unecessary though? You should be able to pass L=4 and not need the speacial treatment, no?
Agreed, but the ematch might expect an allocated block. Assuming the data is variable and sometimes is L=4, sometimes L=16 the ematch requires special handling because m->data might hold the value directly or a pointer depending on datalen.
Quoted 10 lines
Quoted 3 lines
1) We make u32 hold multiple ematch trees, a u32 key can be of 3
kinds: u32/ematch/container. It's kind of a hack and not very fast due to a lot of stack movement.Indeed this is what i was thinking of.
The only added overhead I can think of is when processing a series of u32 keys_withinthe sameselector_(not across selectors), you check if its u32 native and execute localy (as is done now) or transfer the check to the ematch defined in that key and continue to next key based on the ematchs return code + the logical operation.
Exactly, does the performance gap come with any advantage? No. That's why I don't like it.
Quoted 8 lines
Quoted 7 lines
2) We make the existing u32 match be an ematch which I already did expect for the nexthdr bits. That is the select will simply be replaced by an ematch tree. I'll take a look into how we could have the classifier take influence on the ematches config data. One possibiliy is to have a struct transfered via map which contains useful data such as offset to next header (u32/rsvp). I have to think about this a little more though.
Quoted 7 lines
This could be done in addition to #1. I see #1 as more important for u32 but not so for things like fwmark, tcindex which should fizzle away with meta ematch. I think the danger is in trying to replicate u32 as an ematch; if somehow you can loop back and use the real u32 code, then fine. I feel it being non-trivial to do so.
Like i said earlier, theres a lot of power in u32 other than in basic matching.
Most importantly I don't want to touch any of the hashing code in u32. I really like and it should stay as it is. The existing u32 match can be easly made an ematch so this would safe us the extra work in u32 to implement logic relations again and to fiddle with complicated selector TLVs. The only problem with this is the nexthdr bits because it relies on the hashing code. So we have to make this data available to the ematch which is actually not a bad idea anyway. So I'm thinking about introducing a new structure tcf_em_pkt_info or alike which carries some additional information found out by the classifiers which can be used by ematches. This can be information about the next header, already extracted dscp values, etc.
This would give us the chance to add a very small em_u32.c (~40 lines) doing exactly the same as the current u32 match and have the u32 selector replaced with an ematch tree at no additional cost. Backward compatibility is as easy as creating a flat ANDed ematch tree.
Note: The u32 ematch I'm talking about is not the cmp ematch, cmp is more advanced but also slightly slower.
Thoughts?
Quoted 3 lines
I think #2 is better for other classifiers which were already doomed anyways. #1 is important for u32 and perhaps other classifiers like rsvp and route. And yes, #1 is more work ;->
Why is it better? What's the advantage?
Quoted 3 lines
hang on:-> No dont rewrite u32 please. Your cmp is good for the basic matches that u32 does, but is _nowhere_ close to being able to do what u32 can when used properly.
Right, that's why I now call it cmp and the existing u32 match becomes the u32 ematch.
Quoted 3 lines
I Should be able to compile a new ematch as a module in an already running kernel. So, other than generic stuff for ematches, things like
TCF_EM_CMPshould not be in that enumeration.
It's not a requirement to put it there but we need to manage the assigned types for ematches in mainline anyway.
Quoted 3 lines
Which means the above should go in its own file; probably create a
include/linux/tc_ematchdirectory with a file of sorttcf_em_cmp.hwhich holds all the above.
This one I can agree.
Quoted 1 line
And all this also goes in that header file as well.
I put it here because it might be very useful for other ematches or further classifiers, you name it. tcf_get_base_ptr is used by nbyte ematch for example.
Quoted 11 lines
Most importantly I don't want to touch any of the hashing code in u32. I really like and it should stay as it is. The existing u32 match can be easly made an ematch so this would safe us the extra work in u32 to implement logic relations again and to fiddle with complicated selector TLVs. The only problem with this is the nexthdr bits because it relies on the hashing code. So we have to make this data available to the ematch which is actually not a bad idea anyway. So I'm thinking about introducing a new structure
tcf_em_pkt_infoor alike which carries some additional information found out by the classifiers which can be used by ematches. This can be information about the next header, already extracted dscp values, etc.
Here's what I mean, it moves the u32 match as-is to an ematch so it benefits from logic relations, inversion and can be used from other classifiers as well. All we have to do is set info->ptr and info->nexthdr to ptr respetively off2 before we evaluate the ematch tree. The pkt_info struct is then passed to tcf_em_tree_match and made available to every ematch.
Thoughts?
include/linux/pkt_cls.h +1 -0
@@ -351,6 +351,7 @@TCF_EM_CONTAINER ,TCF_EM_CMP ,TCF_EM_NBYTE , +TCF_EM_U32 , __TCF_EM_MAX };
include/net/pkt_cls.h +2 -0
@@ -274,6 +274,8 @@struct tcf_pkt_info { +u8 * ptr; +int nexthdr; };static inline u32 tcf_read_bucket (u8 *ptr,u8 align)
net/sched/Kconfig +6 -0
@@ -408,6 +408,12 @@ To compile this code as a module, choose M here: the module will be called em_nbyte. +config NET_EMATCH_U32 + tristate "U32 hashing key" + depends on NET_EMATCH + ---help--- + TODO + config NET_CLS_ACT bool "Packet ACTION" depends on EXPERIMENTAL && NET_CLS && NET_QOS
net/sched/Makefile +1 -0
@@ -36,3 +36,4 @@ obj-$(CONFIG_NET_EMATCH) += ematch.o obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o +obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o
net/sched/em_u32.c +53 -0
53 lines not on this page · raw message
Quoted 8 lines · Thomas Graf
Here's what I mean, it moves the u32 match as-is to an ematch so it benefits from logic relations, inversion and can be used from other classifiers as well. All we have to do is set
info->ptrandinfo->nexthdrto ptr respetively off2 before we evaluate the ematch tree. Thepkt_infostruct is then passed totcf_em_tree_matchand made available to every ematch.Thoughts?
I think this is fine; getting into complicated-land with off2 etc but fine and does not preclude (and is lower importance in my opinion) than having u32 do its own magic.
Note again Thomas: I do realize its more work to do the ematch/match thing ;->
cheers,
jamal
Sorry for the latency - vacation over, i am gonna slow down a little ..
Quoted 1 line · Thomas Graf
* jamal <[email protected]> 2005-01-05 08:33
[..]
Quoted 7 lines
Quoted 2 lines
Sorry i missed that. Isnt it still unecessary though? You should be able to pass L=4 and not need the speacial treatment, no?
Agreed, but the ematch might expect an allocated block. Assuming the data is variable and sometimes is L=4, sometimes L=16 the ematch requires special handling because
m->datamight hold the value directly or a pointer depending on datalen.
So the issue is whether its by ref or copy? Maybe thats what the flag is for then. My view is that _everything_ for ematches should be by copy for simplicty.
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
1) We make u32 hold multiple ematch trees, a u32 key can be of 3
kinds: u32/ematch/container. It's kind of a hack and not very fast due to a lot of stack movement.
Quoted 8 lines
Quoted 6 lines
Indeed this is what i was thinking of.
The only added overhead I can think of is when processing a series of u32 keys_withinthe sameselector_(not across selectors), you check if its u32 native and execute localy (as is done now) or transfer the check to the ematch defined in that key and continue to next key based on the ematchs return code + the logical operation.Exactly, does the performance gap come with any advantage? No.
Oh, yes;-> the one check in the datapath comes with a _huge_ advantage even all that you had was old style matches because now you have embeded logical operations which are more than just the old AND. But more importantly you can use ematches as well to influence the existing u32 tree path.
Quoted 20 lines
That's
why I don't like it.Quoted 8 lines
Quoted 7 lines
2) We make the existing u32 match be an ematch which I already did expect for the nexthdr bits. That is the select will simply be replaced by an ematch tree. I'll take a look into how we could have the classifier take influence on the ematches config data. One possibiliy is to have a struct transfered via map which contains useful data such as offset to next header (u32/rsvp). I have to think about this a little more though.
Quoted 7 lines
This could be done in addition to #1. I see #1 as more important for u32 but not so for things like fwmark, tcindex which should fizzle away with meta ematch. I think the danger is in trying to replicate u32 as an ematch; if somehow you can loop back and use the real u32 code, then fine. I feel it being non-trivial to do so.
Like i said earlier, theres a lot of power in u32 other than in basic matching.
Quoted 1 line
Most importantly I don't want to touch any of the hashing code in u32.
What i am reading is you see more work involved. Is this correct?
Quoted 16 lines
I really like and it should stay as it is. The existing u32 match can be easly made an ematch so this would safe us the extra work in u32 to implement logic relations again and to fiddle with complicated selector TLVs. The only problem with this is the nexthdr bits because it relies on the hashing code. So we have to make this data available to the ematch which is actually not a bad idea anyway. So I'm thinking about introducing a new structure
tcf_em_pkt_infoor alike which carries some additional information found out by the classifiers which can be used by ematches. This can be information about the next header, already extracted dscp values, etc.This would give us the chance to add a very small
em_u32.c(~40 lines) doing exactly the same as the current u32 match and have the u32 selector replaced with an ematch tree at no additional cost. Backward compatibility is as easy as creating a flat ANDed ematch tree.
Quoted 4 lines
Note: The u32 ematch I'm talking about is not the cmp ematch, cmp is more advanced but also slightly slower.
Thoughts?
I think I understand more after reading the above now.
There is one issue which i think is the big source of our lack of sync:
You conclude people are gonna want to use the logical tree building scheme you are putting in to put together matches and ematches. U32 _already_ has a tree building scheme which is very very flexible. Now that the sel2 matches will provide u32 logial operators, it presents a very interesting fresh outlook on life in a jiffy of a packet. This is what i dont wanna kill or ignore. fw, tcindex etc donot have this infrastructure so they dont matter.
Quoted 5 lines
Quoted 3 lines
I think #2 is better for other classifiers which were already doomed anyways. #1 is important for u32 and perhaps other classifiers like rsvp and route. And yes, #1 is more work ;->
Why is it better? What's the advantage?
Refer to what i said above: u32 has built in tree building scheme made more interesting now that there exist more interesting logical operators.
Quoted 6 lines
Quoted 3 lines
hang on:-> No dont rewrite u32 please. Your cmp is good for the basic matches that u32 does, but is _nowhere_ close to being able to do what u32 can when used properly.
Right, that's why I now call it cmp and the existing u32 match becomes the u32 ematch.
Again, u32 classifier is not just matches; the more interesting thing is the layout of the rules that it can be taught to do.
I think the ematch which emulates the std u32 match is of course valuable to have but it _doesnt_ deserve the same name.
Quoted 6 lines
Quoted 3 lines
I Should be able to compile a new ematch as a module in an already running kernel. So, other than generic stuff for ematches, things like
TCF_EM_CMPshould not be in that enumeration.It's not a requirement to put it there but we need to manage the assigned types for ematches in mainline anyway.
Thinking more about it; not sure why you would even bother managing them. Everything runs at the same kernel privilege level. I am not sure you want to have certain things that can only be built when recompiling the kernel
Quoted 5 lines
Quoted 1 line
And all this also goes in that header file as well.
I put it here because it might be very useful for other ematches or further classifiers, you name it.
tcf_get_base_ptris used by nbyte ematch for example.
If its generic then it stays in the main header;
cheers,
jamal
* jamal <[email protected]> 2005-01-06 08:47
Quoted 3 lines
So the issue is whether its by ref or copy? Maybe thats what the flag is for then. My view is that _everything_ for ematches should be by copy for simplicty.
If we do everything as ref we'll be allocating 4 byte chunks or we introduce a storage u32 which pollutes the structure. I don't like that given that the transfer of a single u32 is probably the most common for all those smallish ematches for a specific thing. For simplicity, you don't even notice if you're not aware of that it can be of help so I don't think we're losing any simplicity here.
Quoted 5 lines
Oh, yes;-> the one check in the datapath comes with a _huge_ advantage even all that you had was old style matches because now you have embeded logical operations which are more than just the old AND. But more importantly you can use ematches as well to influence the existing u32 tree path.
Missunderstanding here, I meant is there any advantage in having multiple ematch trees (interleaved) over just making the existing u32 key an ematch and have the selector (with the hashing bits extracted) with one ematch tree.
Quoted 1 line
What i am reading is you see more work involved. Is this correct?
Well, given we can agree on moving the u32 key to an ematch and have the selector replaced with an ematch tree the following modifications would be required in u32:
1) extract hashing bits out of selector and move it into a new TLV.
2) Replace the foreach key match loop with an ematch_tree match
3) Fill out a pkt_info struct with ptr and off2 so we don't lose hashing capabilities
4) Add backward compat code. Old selector must be transformed into a flat ematch tree and the hashing bits must be extracted and stored in the new struct.
Quoted 4 lines
There is one issue which i think is the big source of our lack of sync:
You conclude people are gonna want to use the logical tree building scheme you are putting in to put together matches and ematches. U32 _already_ has a tree building scheme which is very very flexible.
I know and I'm not gonna break it but rather replace the ANDed u32 key chains with an ematch tree. I'm fully aware of what u32 can do and I will in no way remove anything.
To make it clear, I'm only gonna change about 10 lines in classify:
for (i = n->sel.nkeys; i>0; i--, key++) {
if ((*(u32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
n = n->next;
goto next_knode;
}
}will be replaced with:
info.nexthdr = off2;
info.ptr = ptr;
if (!tcf_em_tree_match(..., &info)) {
n = n->next;
goto next_knode;
}That's all, nothing else is changed. I think this is exactly the part were we're out of sync.
The most difficult part is to do the Kconfig dependencies in a smart way ;->
Quoted 4 lines
Again, u32 classifier is not just matches; the more interesting thing is the layout of the rules that it can be taught to do.
I think the ematch which emulates the std u32 match is of course valuable to have but it _doesnt_ deserve the same name.
Stupid terms, em_u32.c is a replacement for the u32 key and it has exactly the same behaviour. I'll be happy to rename it but as you know I really suck at naming things ;->
Quoted 4 lines
Thinking more about it; not sure why you would even bother managing them. Everything runs at the same kernel privilege level. I am not sure you want to have certain things that can only be built when recompiling the kernel
Well, we have exactly the same issues as with TLV types. I don't see why one would need to recompile things. The enumeration is for ematches included in the kernel tree.
Quoted 1 line · Thomas Graf
* jamal <[email protected]> 2005-01-06 08:47
[..]
Quoted 6 lines
If we do everything as ref we'll be allocating 4 byte chunks or we introduce a storage u32 which pollutes the structure. I don't like that given that the transfer of a single u32 is probably the most common for all those smallish ematches for a specific thing. For simplicity, you don't even notice if you're not aware of that it can be of help so I don't think we're losing any simplicity here.
I am not sure the optimization for a single u32 as the ematch data is valid ;-> But this is not a show stopper, i will wait for the code to see if its an annoyance or tolerable.
Quoted 4 lines
Missunderstanding here, I meant is there any advantage in having multiple ematch trees (interleaved) over just making the existing u32 key an ematch and have the selector (with the hashing bits extracted) with one ematch tree.
Misunderstanding is the right description.
If you did a s/ematch/match for the u32 part then we'd be shooting for the same thing;-> So i take back what i said, you are not gonna mess up the u32 tree logic.
Quoted 3 lines
1) extract hashing bits out of selector and move it into a new TLV.
2) Replace the foreach key match loop with anematch_treematch
This is our contention point.
Quoted 2 lines
3) Fill out a
pkt_infostruct with ptr and off2 so we don't lose hashing capabilities
And this is why i dont like it.
Quoted 3 lines
4) Add backward compat code. Old selector must be transformed into a flat ematch tree and the hashing bits must be extracted and stored in the new struct.
I think the u32 changes are one-shot if you want to avoid lotsa #ifdefs. Someone sends you a old sel, then convert it to a new one for storage. Dumping is a little trickier, need some way to recognize old style request.
Quoted 1 line
The most difficult part is to do the
Kconfigdependencies in a smart way ;->
The trick would be to always use sel2 and present no kconfig options for back compat. We need to figure out how to recognize an old style dump and we are set.
Quoted 8 lines
Quoted 4 lines
Again, u32 classifier is not just matches; the more interesting thing is the layout of the rules that it can be taught to do.
I think the ematch which emulates the std u32 match is of course valuable to have but it _doesnt_ deserve the same name.Stupid terms,
em_u32.cis a replacement for the u32 key and it has exactly the same behaviour. I'll be happy to rename it but as you know I really suck at naming things ;->
em_u32 sounds better ;->
Above you are trying to insert off2 into the info (what i said i didnt like) - how are you going to achieve the same with a standalone en_u32 from say you basic classifier?
Quoted 8 lines
Quoted 4 lines
Thinking more about it; not sure why you would even bother managing them. Everything runs at the same kernel privilege level. I am not sure you want to have certain things that can only be built when recompiling the kernel
Well, we have exactly the same issues as with TLV types. I don't see why one would need to recompile things. The enumeration is for ematches included in the kernel tree.
Your call. Actions do it the way i described it. It is more flexible in my opionion, nothing reserved. Good practise is to know who uses what (not hardcoding in headers) and the register will catch any discrepancy.
cheers,
jamal
* jamal <[email protected]> 2005-01-07 08:45
Quoted 4 lines
Quoted 2 lines
3) Fill out a
pkt_infostruct with ptr and off2 so we don't lose hashing capabilitiesAnd this is why i dont like it.
What's the reason for not liking it? I know it's not a perfect solution in terms of layers but having the classifier sharing already gathered information to an ematch is not a bad thing.
Quoted 4 lines
I think the u32 changes are one-shot if you want to avoid lotsa #ifdefs. Someone sends you a old sel, then convert it to a new one for storage. Dumping is a little trickier, need some way to recognize old style request.
The easiest way is to introduce a new TLV type and regard configuration requests carrying the old type in compatibility mode.
Quoted 3 lines
The trick would be to always use sel2 and present no kconfig options for back compat. We need to figure out how to recognize an old style dump and we are set.
Given we always use the new method by converting old style parameters and we use em_u32 as u32 key we would need to put a dependcy on ematch && em_u32 for cls_u32.
Quoted 3 lines
Above you are trying to insert off2 into the info (what i said i didnt like) - how are you going to achieve the same with a standalone
en_u32from say you basic classifier?
I won't and it's not necessary, one can use u32 if he requires the nexthdr capabilities or otherwise use em_cmp support the skb layers. (Which i know is not perfect since the pointers to those layers are not provided all the time).
Quoted 9 lines · Thomas Graf
* jamal <[email protected]> 2005-01-07 08:45
Quoted 4 lines
Quoted 2 lines
3) Fill out a
pkt_infostruct with ptr and off2 so we don't lose hashing capabilitiesAnd this is why i dont like it.
What's the reason for not liking it? I know it's not a perfect solution in terms of layers but having the classifier sharing already gathered information to an ematch is not a bad thing.
I think its _a hack_ Thomas ;-> Mostly because it has dependency on u32. off2 doesnt exist on any other classifier and the basic ematch should be usable by any classifier.
Quoted 3 lines
The easiest way is to introduce a new TLV type and regard configuration requests carrying the old type in compatibility mode.
Sounds reasonable.
Quoted 8 lines
Quoted 3 lines
The trick would be to always use sel2 and present no kconfig options for back compat. We need to figure out how to recognize an old style dump and we are set.
Given we always use the new method by converting old style parameters and we use
em_u32as u32 key we would need to put a dependcy on ematch &&em_u32forcls_u32.
I think that you should kill this em_u32 idea if it works only with u32.
Quoted 8 lines
Quoted 3 lines
Above you are trying to insert off2 into the info (what i said i didnt like) - how are you going to achieve the same with a standalone
en_u32from say you basic classifier?I won't and it's not necessary, one can use u32 if he requires the nexthdr capabilities or otherwise use
em_cmpsupport the skb layers. (Which i know is not perfect since the pointers to those layers are not provided all the time).
Why not just have a check to see if it is native match then not to call up any ematch executing code. Have the native match maybe be of kind 0. Have the return code for ematch lookup return something that indicates that you need to match using local u32 instead of ematch.
cheers,
jamal
* jamal <[email protected]> 2005-01-10 08:26
Quoted 3 lines
I think its _a
hack_Thomas ;-> Mostly because it has dependency on u32. off2 doesnt exist on any other classifier and the basic ematch should be usable by any classifier.
It does not, u32 does have a dependency on em_u32 but not vice versa. em_u32 is perfectly useful even without nexthdr functionality since this is the way it is used today in 90% of the cases and it should be a little bit faster than em_cmp but also a bit less powerful. On top of that, rsvp could provide this information as well so one could extend rsvp with em_u32 ematches. I think we should not think of it as being dependant on off2 but rather as it is able to use information from a underlying layer.
Quoted 4 lines
Why not just have a check to see if it is native match then not to call up any ematch executing code. Have the native match maybe be of kind 0. Have the return code for ematch lookup return something that indicates that you need to match using local u32 instead of ematch.
This limits the number of native ematches to 1 or any other reserved number and complicates userspace part for no reason. Is there any advantage besides that it fits into layerrs more nicely? I can tell you the disavantages and then we can compare ;->
- additional code is required in the classifier which would not be required otherwise.
- given we define 0 as native ematch, what happens if we need another native one? reserve a number in the namespace and make a comment, "please do not use" or will we just say, well, we can make it a regular ematch, it's not perfectly clean but it works perfectly fine?
- making it a little bit generic such as em_u32 makes it useable by other classifiers. One example is the above mentioned rsvp which parses headers or there might be other specialized classifiers having use for it. we can't have this if its put into the classifier itself.
- userspace needs additional special handling and this will get ugly once we need more than 1 native ematch, we'd need some register api so ematch modules could tell which numbers are native for them.
- did i state it's more work already? ;->
Quoted 5 lines · Thomas Graf
* jamal <[email protected]> 2005-01-10 08:26
Quoted 3 lines
I think its _a
hack_Thomas ;-> Mostly because it has dependency on u32. off2 doesnt exist on any other classifier and the basic ematch should be usable by any classifier.
Quoted 8 lines
It does not, u32 does have a dependency on
em_u32but not vice versa.em_u32is perfectly useful even without nexthdr functionality since this is the way it is used today in 90% of the cases and it should be a little bit faster thanem_cmpbut also a bit less powerful. On top of that, rsvp could provide this information as well so one could extend rsvp withem_u32ematches. I think we should not think of it as being dependant on off2 but rather as it is able to use information from a underlying layer.
Ok, you make a convincing arguement ;-> No more concerns from my side. Churn that code!
cheers,
jamal
* jamal <[email protected]> 2005-01-10 17:05
Quoted 15 lines · Thomas Graf
Quoted 5 lines
* jamal <[email protected]> 2005-01-10 08:26
Quoted 3 lines
I think its _a
hack_Thomas ;-> Mostly because it has dependency on u32. off2 doesnt exist on any other classifier and the basic ematch should be usable by any classifier.Quoted 8 lines
It does not, u32 does have a dependency on
em_u32but not vice versa.em_u32is perfectly useful even without nexthdr functionality since this is the way it is used today in 90% of the cases and it should be a little bit faster thanem_cmpbut also a bit less powerful. On top of that, rsvp could provide this information as well so one could extend rsvp withem_u32ematches. I think we should not think of it as being dependant on off2 but rather as it is able to use information from a underlying layer.
Quoted 2 lines
Ok, you make a convincing arguement ;-> No more concerns from my side. Churn that code!
I started testing via the basic classifier but will do the cls_u32 changes soon and then remerge and do the final tests once all the other pkt_sched changes have made it into linus's tree and I can work from a fresh bk tree. I'll also try to find the time this week to do the iproute2 changes for the tcf_exts changset so iproute2 is actually capable of configuring actions for all classifiers.
RFC 1/1 meta ematch
In reply to jamal* jamal <[email protected]> 2005-01-10 17:05
Quoted 4 lines
Ok, you make a convincing arguement ;-> No more concerns from my side. Churn that code!
Found some cycles today and wrote the meta ematch. It tried to find a good compromise between speed and power.
So far I added the following matching possibilies:
- random
- load average (0,1,2)
- dev (numeric and string)
- indev (numeric and string)
- realdev (numeric and string)
- skb priority
- ... protocol
- ... security
- ... pkttype (to easly match on multicast/broadcast)
- ... pktlen
- ... datalen
- ... maclen
- netfilter mark
- ... cache
- ... conntrack info
- ... debug variable
- tc index
- ... verdict
- ... classid
- routing classid
- .... iif
Yet to come are more routing and socket attributes such as queue sizes, backlog sizes, neighbour attribute of the route found, ...
It is also possible to compare two kernel meta values, e.g realdev equals dev.
Numeric matches may be modified via shift and mask operators to for example only consider a part of nfmark.
Binary matches may have a shift modifier to only consider a certain amount of the data, e.g. "eth1" with shift 1 would end up with "eth". I added this because I wanted something like eth% but didn't want to implement expensive string operations.
If its not obvious, random and loadavg are intended for load balancing purposes, i.e.
tc filter add ... basic meta random mask 1 eq 1 and \loadavg_5 lt 10 action redirect ...
include/linux/pkt_cls.h +1 -0
@@ -352,6 +352,7 @@TCF_EM_CMP ,TCF_EM_NBYTE ,TCF_EM_U32 , +TCF_EM_META , __TCF_EM_MAX };
include/linux/tc_ematch/tc_em_meta.h +71 -0
71 lines not on this page · raw message
net/sched/Kconfig +10 -0
@@ -428,6 +428,16 @@ To compile this code as a module, choose M here: the module will be called em_u32. +config NET_EMATCH_META + tristate "Metadata" + depends on NET_EMATCH + ---help--- + Say Y here if you want to be ablt to classify packets based on + metadata. + + To compile this code as a module, choose M here: the + module will be called em_meta. + config NET_CLS_ACT bool "Packet ACTION" depends on EXPERIMENTAL && NET_CLS && NET_QOS
net/sched/Makefile +1 -0
@@ -37,3 +37,4 @@ obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o +obj-$(CONFIG_NET_EMATCH_META) += em_meta.o
net/sched/em_meta.c +566 -0
566 lines not on this page · raw message
Re: [RFC] meta ematch
Quoted 32 lines · Thomas Graf
Found some cycles today and wrote the meta ematch. It tried to find a good compromise between speed and power.
So far I added the following matching possibilies:
- random
- load average (0,1,2)
- dev (numeric and string)
- indev (numeric and string)
- realdev (numeric and string)
- skb priority
- ... protocol
- ... security
- ... pkttype (to easly match on multicast/broadcast)
- ... pktlen
- ... datalen
- ... maclen
- netfilter mark
- ... cache
- ... conntrack info
- ... debug variable
- tc index
- ... verdict
- ... classid
- routing classid
- .... iifYet to come are more routing and socket attributes such as queue sizes, backlog sizes, neighbour attribute of the route found, ...
It is also possible to compare two kernel meta values, e.g realdev equals dev.
Quoted 10 lines
Numeric matches may be modified via shift and mask operators to for example only consider a part of nfmark.
Binary matches may have a shift modifier to only consider a certain amount of the data, e.g. "eth1" with shift 1 would end up with "eth". I added this because I wanted something like eth% but didn't want to implement expensive string operations.
Looks great. I have a few doubts about about the set of chosen values though. Things like nf_debug and nf_cache were never meant to be userspace-visible. What about backwards compatibility if we want to remove it, or some other more meaningful value where just returning 0 wouldn't be the same ?
A couple of minor things:
- var_dev sets dst->value to dev->name, meta_var_destroy will try to free dev->name.
- meta_int_change only uses 32 bit, but dst->value is unsigned long (64 bit on 64-bit arches). nfmark for example is unsigned long, so you should also use *(unsigned long *).
- for the same reason meta_int_compare should return long not int
Quoted 4 lines
If its not obvious, random and loadavg are intended for load balancing purposes, i.e.
I have my doubts about the usefullness of load balancing traffic based on CPU load, but I guess it doesn't hurt.
Regards
Patrick
Re: [RFC] meta ematch
* Patrick McHardy <[email protected]> 2005-01-13 19:54
Quoted 5 lines
Looks great. I have a few doubts about about the set of chosen values though. Things like
nf_debugandnf_cachewere never meant to be userspace-visible. What about backwards compatibility if we want to remove it, or some other more meaningful value where just returning 0 wouldn't be the same ?
It is indeed problematic and they should be marked as "for debugging purposes (unreliable)" but at least nf_debug and nfctinfo are very useful for debugging.
Quoted 2 lines
-
var_devsetsdst->valuetodev->name,meta_var_destroywill try to freedev->name.
The dst meta_value is the l_value/r_lvalue from em_meta_match and never gets destroyed. I reused meta_data to store address & length. It might be a good idea to make a new struct for this to make it more readable though.
Quoted 3 lines
-
meta_int_changeonly uses 32 bit, butdst->valueis unsigned long (64 bit on 64-bit arches). nfmark for example is unsigned long, so you should also use *(unsigned long *).
Doesn't work when size of long differs between kernel and userspace. I'm aware of this but it seems everyone is using int anyway for nfmark, so yes this indeed limits the use of nfmark match to only 32 bits on 64bit machines. The proper way is to introduce a new type TCF_EM_TYPE_INT64 and access nfmark over it but I didn't want to create a new type just because of this special case. We can always add it later as addition to the 32bit version.
Quoted 1 line
- for the same reason
meta_int_compareshould return long not int
Agreed.
Re: [RFC] meta ematch
Quoted 12 lines · Thomas Graf
* Patrick McHardy <[email protected]> 2005-01-13 19:54
Quoted 7 lines
Looks great. I have a few doubts about about the set of chosen values though. Things like
nf_debugandnf_cachewere never meant to be userspace-visible. What about backwards compatibility if we want to remove it, or some other more meaningful value where just returning 0 wouldn't be the same ?
Quoted 4 lines
It is indeed problematic and they should be marked as "for debugging purposes (unreliable)" but at least
nf_debugand nfctinfo are very useful for debugging.
True. nfctinfo is even useful for more, the direction of a connection might be interesting. connmark, conntrack counters, src-ip before SNAT etc. might also be interesting, but they are horrible to implement cleanly because any dependency on ip_conntrack_lock will automatically load ip_conntrack. Perhaps we should add something like nf_ct_get_afinfo() to return a set of conntrack operations to nf_conntrack.
For things beside the nf* fields: I think we should make it very clear that everything that isn't already visible to userspace in some way, and thus won't disappear (like priority, nfmark, load average ...), can get changed/removed any time.
Quoted 10 lines
Quoted 4 lines
-
var_devsetsdst->valuetodev->name,meta_var_destroywill try to freedev->name.The
dstmeta_valueis the l_value/r_lvalue fromem_meta_matchand never gets destroyed. I reusedmeta_datato store address & length. It might be a good idea to make a new struct for this to make it more readable though.
Looks good to me already. I only looked at the diff, so I didn't really follow the codepath.
Quoted 6 lines
Quoted 5 lines
-
meta_int_changeonly uses 32 bit, butdst->valueis unsigned long (64 bit on 64-bit arches). nfmark for example is unsigned long, so you should also use *(unsigned long *).
Quoted 9 lines
Doesn't work when size of long differs between kernel and userspace. I'm aware of this but it seems everyone is using int anyway for nfmark, so yes this indeed limits the use of nfmark match to only 32 bits on 64bit machines. The proper way is to introduce a new type
TCF_EM_TYPE_INT64and access nfmark over it but I didn't want to create a new type just because of this special case. We can always add it later as addition to the 32bit version.
Shouldn't be too hard to get right. In the kernel you can decide based on RTA_PAYLOAD. Userspace needs some other way to notice it is running as a 32-bit binary on a 64-bit kernel, but that's something you can't solve in the kernel anyway.
Regards
Patrick
Re: [RFC] meta ematch
* Patrick McHardy <[email protected]> 2005-01-14 02:13
Quoted 6 lines
True. nfctinfo is even useful for more, the direction of a connection might be interesting. connmark, conntrack counters, src-ip before SNAT etc. might also be interesting, but they are horrible to implement cleanly because any dependency on
ip_conntrack_lockwill automatically loadip_conntrack. Perhaps we should add something likenf_ct_get_afinfo()to return a set of conntrack operations tonf_conntrack.
Yes, I'm kind of afraid to create a too big dependency on netfilter, so I sticked to the easly reachable values.
I think I'll remove the netfilter attributes again except for nfmark and readd them together with the more complicated routing information and the socket attributes to not delay the whole ematch patch for too long.
Quoted 4 lines
For things beside the nf* fields: I think we should make it very clear that everything that isn't already visible to userspace in some way, and thus won't disappear (like priority, nfmark, load average ...), can get changed/removed any time.
Agreed.
Quoted 7 lines
Quoted 5 lines
The
dstmeta_valueis the l_value/r_lvalue fromem_meta_matchand never gets destroyed. I reusedmeta_datato store address & length. It might be a good idea to make a new struct for this to make it more readable though.Looks good to me already. I only looked at the diff, so I didn't really follow the codepath.
I changed it anyway, it looks a lot cleaner now.
Quoted 4 lines
Shouldn't be too hard to get right. In the kernel you can decide based on
RTA_PAYLOAD. Userspace needs some other way to notice it is running as a 32-bit binary on a 64-bit kernel, but that's something you can't solve in the kernel anyway.
Both have their drawbacks but I think yours is a bit simpler. I changed it to the code below and gave responsibility to userspace.
+ if (RTA_PAYLOAD(rta) >= sizeof(unsigned long)) {
+ dst->val = *(unsigned long *) RTA_DATA(rta);
+ dst->len = sizeof(unsigned long);
+ } else if (RTA_PAYLOAD(rta) == sizeof(u32)) {
+ dst->val = *(u32 *) RTA_DATA(rta);
+ dst->len = sizeof(u32);
+ } else
+ return -EINVAL;
Here's a revised patch. I fixed the numeric comparison issues and added meta_obj instead of using meta_data to give a better impression on the difference of a comparable object and meta data definitions.
include/linux/pkt_cls.h +1 -0
@@ -352,6 +352,7 @@TCF_EM_CMP ,TCF_EM_NBYTE ,TCF_EM_U32 , +TCF_EM_META , __TCF_EM_MAX };
include/linux/tc_ematch/tc_em_meta.h +72 -0
72 lines not on this page · raw message
net/sched/Kconfig +11 -0
@@ -428,6 +428,17 @@ To compile this code as a module, choose M here: the module will be called em_u32. +config NET_EMATCH_META + tristate "Metadata" + depends on NET_EMATCH + ---help--- + Say Y here if you want to be ablt to classify packets based on + metadata such as load average, netfilter attributes, socket + attributes and routing decisions. + + To compile this code as a module, choose M here: the + module will be called em_meta. + config NET_CLS_ACT bool "Packet ACTION" depends on EXPERIMENTAL && NET_CLS && NET_QOS
net/sched/Makefile +1 -0
@@ -37,3 +37,4 @@ obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o +obj-$(CONFIG_NET_EMATCH_META) += em_meta.o
net/sched/em_meta.c +587 -0
587 lines not on this page · raw message
Re: [RFC] meta ematch
Quoted 4 lines · Thomas Graf
Here's a revised patch. I fixed the numeric comparison issues and added
meta_objinstead of usingmeta_datato give a better impression on the difference of a comparable object and meta data definitions.
I scanned the code very quickly; lets start with the big picture then i will send some more comments:
Did i understand this correctly that a metamatch MUST have a lvalue + rvalue pair?
What if all i wanted to say was
..
ematch indev eth0
I only see one value there - does that become l or r?
more comments coming - just ned some caffeine then i will stare.
cheers,
jamal
Re: [RFC] meta ematch
* jamal <[email protected]> 2005-01-16 09:58
Quoted 10 lines · Thomas Graf
Quoted 4 lines
Here's a revised patch. I fixed the numeric comparison issues and added
meta_objinstead of usingmeta_datato give a better impression on the difference of a comparable object and meta data definitions.I scanned the code very quickly; lets start with the big picture then i will send some more comments:
Did i understand this correctly that a metamatch MUST have a lvalue + rvalue pair?
They MAY have bove.
Quoted 4 lines
What if all i wanted to say was
..
ematch indev eth0
The lvalue will be TCF_META_ID_INDEV and your rvalue will be TCF_META_TYPE_VAR with "eth0" as payload(TCF_EM_META_RVALUE). TCF_EM_META_LVALUE will be unused in this case.
Re: [RFC] meta ematch
Quoted 3 lines · Thomas Graf
The lvalue will be
TCF_META_ID_INDEVand your rvalue will beTCF_META_TYPE_VARwith "eth0" aspayload(TCF_EM_META_RVALUE).TCF_EM_META_LVALUEwill be unused in this case.
ok - i get it. So the rvalue is basically just the data that needs to be compared against. rvalue confused me a little. If you had called it meta_data i would have got it right away. But now that you explain it, makes sense.
I am not sure iam following yet:
So in the case of indev, you would need to
- get indev ifindex from skb
- get indev name from skb
- compare the two??
Actually it may be a little overkill to have those two as separate entities with their own headers etc, no? Why not just store it in the same fashion you transported it from/to user space?
I will start looking at the code
cheers,
jamal
Re: [RFC] meta ematch
* jamal <[email protected]> 2005-01-16 10:37
Quoted 10 lines · Thomas Graf
Quoted 4 lines
The lvalue will be
TCF_META_ID_INDEVand your rvalue will beTCF_META_TYPE_VARwith "eth0" aspayload(TCF_EM_META_RVALUE).TCF_EM_META_LVALUEwill be unused in this case.ok - i get it. So the rvalue is basically just the data that needs to be compared against. rvalue confused me a little. If you had called it
meta_datai would have got it right away. But now that you explain it, makes sense.
The rvalue may also point to a metadata in the kernel. This gets useful when comparing dev against real dev or if nfmark, tcindex, you name it carries a ifindex for example. It would even be possible to compare two strings from userspace but that wouldn't make sense. The only difference between lvalue and rvalue is that the lvalue carries the operand.
Quoted 10 lines
I am not sure iam following yet:
So in the case of indev, you would need to
- get indev ifindex from skb
- get indev name from skb
- compare the two??Actually it may be a little overkill to have those two as separate entities with their own headers etc, no? Why not just store it in the same fashion you transported it from/to user space?
For devices, userspace can choose between comparing indices or device names. The variable type will get more use once I add the IPv6 routing meta matches.
Re: [RFC] meta ematch
Quoted 7 lines · Thomas Graf
The rvalue may also point to a metadata in the kernel. This gets useful when comparing dev against real dev or if nfmark, tcindex, you name it carries a ifindex for example. It would even be possible to compare two strings from userspace but that wouldn't make sense. The only difference between lvalue and rvalue is that the lvalue carries the operand.
ok, more clarity.
Quoted 8 lines
Quoted 8 lines
I am not sure iam following yet:
So in the case of indev, you would need to
- get indev ifindex from skb
- get indev name from skb
- compare the two??
Can you explain the above in context of indev = "eth0"? I am still not sure i get it:
+ if (meta_get(skb, info, &meta->lvalue, &l_value) < 0 ||
+ meta_get(skb, info, &meta->rvalue, &r_value) < 0)
+ return 0;
+ r = meta_type_ops(&meta->lvalue)->compare(&l_value, &r_value);
cheers,
jamal
Re: [RFC] meta ematch
* jamal <[email protected]> 2005-01-16 11:19
Quoted 11 lines
Quoted 7 lines
Quoted 7 lines
I am not sure iam following yet:
So in the case of indev, you would need to
- get indev ifindex from skb
- get indev name from skb
- compare the two??Can you explain the above in context of indev = "eth0"? I am still not sure i get it:
net/sched/em_meta.c line 471
Quoted 4 lines
net/sched/em_meta.c +4
-0+if (meta_get (skb, info, &meta->lvalue, &l_value) <0 || +meta_get (skb, info, &meta->rvalue, &r_value) <0 ) +return 0 ; + r =meta_type_ops (&meta->lvalue)->compare (&l_value, &r_value);
Sure, indev = "eth0"
TCA_EM_META_HDR = {
.left = {
.kind = TCF_META_TYPE_VAR << 12 | TCF_META_ID_INDEV,
.op = TCF_EM_EQ,
},
.right = {
.kind = TCF_META_TYPE_VAR << 12 | TCF_META_ID_VALUE,
},
};TCA_EM_META_LVALUE = EMPTY; /* unused */TCA_EM_META_RVALUE = "eth0"
The configuration part will transform this into:
struct meta_match = {
.lvalue = {
.hdr = {
.kind = TCF_META_TYPE_VAR << 12 | TCF_META_ID_INDEV,
.op = TCF_EM_EQ,
},
},
.rvalue = {
.hdr = {
.kind = TCF_META_TYPE_VAR << 12 | TCF_META_ID_VALUE,
}
.val = strdup("eth0"),
.len = strlen("eth0"),
},
}meta_get will make meta_obj's out of it:
struct meta_obj l_value = {
.value = dev->name,
.len = strlen(dev->name),
},struct meta_obj r_value = {
.value = "eth0",
.len = strlen("eth0"),
}the type specific compare will compare these.
Re: [RFC] meta ematch
In reply to Thomas GrafQuoted 1 line · Thomas Graf
diff -Nru
linux-2.6.10-bk14.orig/include/linux/tc_ematch/tc_em_meta.hlinux-2.6.10-bk14/include/linux/tc_ematch/tc_em_meta.h
[..]
include/linux/tc_ematch/tc_em_meta.h line 26
Quoted 11 lines
include/linux/tc_ematch/tc_em_meta.h +11
-0+struct tcf_meta_val +{ +__u16 kind; +__u8 shift; +__u8 op; +}; + +#define TCF_META_TYPE_MASK (0xf << 12) +#define TCF_META_TYPE (kind) (((kind) & TCF_META_TYPE_MASK) >> 12) +#define TCF_META_ID_MASK 0x7ff +#define TCF_META_ID (kind) ((kind) & TCF_META_ID_MASK)
Does it smell like there may be endianess issues? Probably not.
Quoted 6 lines
include/linux/tc_ematch/tc_em_meta.h +6
-0+enum +{ +TCF_META_TYPE_VAR , +TCF_META_TYPE_INT , + __TCF_META_TYPE_MAX +};
include/linux/tc_ematch/tc_em_meta.h line 43
Quoted 10 lines
include/linux/tc_ematch/tc_em_meta.h +10
-0+#define TCF_META_TYPE_MAX (__TCF_META_TYPE_MAX - 1) + +enum +{ +TCF_META_ID_VALUE , +TCF_META_ID_RANDOM , +TCF_META_ID_LOADAVG_0 , +TCF_META_ID_LOADAVG_1 , +TCF_META_ID_LOADAVG_2 , +TCF_META_ID_DEV ,
Since filters are attached to devices - is TCF_META_ID_DEV of any value?
Quoted 4 lines
diff -Nru
linux-2.6.10-bk14.orig/net/sched/em_meta.clinux-2.6.10-bk14/net/sched/em_meta.cnet/sched/em_meta.c +2
-0+ +struct meta_obj
net/sched/em_meta.c line 35
Quoted 10 lines
net/sched/em_meta.c +10
-0+{ +unsigned long value; +unsigned int len; +}; + +struct meta_value +{ +struct tcf_meta_val hdr; +unsigned long val; +unsigned int len;
Those last two look like meta_obj you defined above
Quoted 4 lines
net/sched/em_meta.c +4
-0+/************************************************************************** +* System status & misc +**************************************************************************/ +
net/sched/em_meta.c line 60
Quoted 10 lines
net/sched/em_meta.c +10
-0+static int meta_int_random (struct sk_buff *skb,struct tcf_pkt_info *info, +struct meta_value *v,struct meta_obj *dst) +{ +get_random_bytes (&dst->value,sizeof (dst->value)); +return 0 ; +} + +static inline unsigned long fixed_loadavg (unsigned long v) +{ +return (v + (FIXED_1 /200 )) >>FSHIFT ;
200 has some magic connotation to it - a define somewhere perhaps?
Quoted 12 lines
net/sched/em_meta.c +12
-0+} + +static int meta_int_loadavg_0 (struct sk_buff *skb,struct tcf_pkt_info *info, +struct meta_value *v,struct meta_obj *dst) +{ + dst->value =fixed_loadavg (avenrun[0 ]); +return 0 ; +} + +static int meta_int_loadavg_1 (struct sk_buff *skb,struct tcf_pkt_info *info, +struct meta_value *v,struct meta_obj *dst) +{
net/sched/em_meta.c line 82
Quoted 10 lines
net/sched/em_meta.c +10
-0+ dst->value =fixed_loadavg (avenrun[1 ]); +return 0 ; +} + +static int meta_int_loadavg_2 (struct sk_buff *skb,struct tcf_pkt_info *info, +struct meta_value *v,struct meta_obj *dst) +{ + dst->value =fixed_loadavg (avenrun[2 ]); +return 0 ; +}
Theres a lot of parameters not used at all in these calls .get calls. So far i have seen dst->value and some of the skb fields used. I apologize, I normally dont pick on these things - so if you have future plans for why you are passing those, keep them and ignore the comment. BTW, it would probably be useful to return some mnemonic instead of 0.
Quoted 10 lines
net/sched/em_meta.c +10
-0+/************************************************************************** +* Device names & indices +**************************************************************************/ + +static inline int int_dev (struct net_device *dev,struct meta_obj *dst) +{ +if (unlikely (dev ==NULL )) +return -1 ; + + dst->value = dev->ifindex;
net/sched/em_meta.c line 103
Quoted 10 lines
net/sched/em_meta.c +10
-0+return 0 ; +} + +static inline int var_dev (struct net_device *dev,struct meta_obj *dst) +{ +if (unlikely (dev ==NULL )) +return -1 ; + + dst->value = (unsigned long ) dev->name; + dst->len =strlen (dev->name);
So if device dissapears ... what happens to the pointer? [..]
Quoted 4 lines
net/sched/em_meta.c +4
-0+static inline struct meta_ops *meta_ops (struct meta_value *v) +{ +return &__meta_ops[meta_type (v)][meta_id (v)]; +}
net/sched/em_meta.c line 346
Quoted 10 lines
net/sched/em_meta.c +10
-0+ +static int meta_var_compare (struct meta_obj *a,struct meta_obj *b) +{ +int r = a->len - b->len; + +if (r ==0 ) + r =memcmp ((void *) a->value, (void *) b->value, a->len); + +return r; +}
clever
net/sched/em_meta.c line 372
Quoted 8 lines
net/sched/em_meta.c +8
-0+static void meta_var_apply_extras (struct meta_value *v, +struct meta_obj *dst) +{ +int shift = v->hdr.shift; + +if (shift && shift < dst->len) + dst->len -= shift; +}
whats the purpose to the extras?
net/sched/em_meta.c line 386
Quoted 13 lines
net/sched/em_meta.c +13
-0+static int meta_int_compare (struct meta_obj *a,struct meta_obj *b) +{ +/* Let gcc optimize it, the unlikely is not really based on +* some numbers but jump free code for missmatches seems +* more logical. +*/ +if (unlikely (a == b)) +return 0 ; +else if (a < b) +return -1 ; +else +return 1 ; +}
Would be very useful to return mnemonics for readability.
net/sched/em_meta.c line 469
Quoted 10 lines
net/sched/em_meta.c +10
-0+static int em_meta_match (struct sk_buff *skb,struct tcf_ematch *m, +struct tcf_pkt_info *info) +{ +int r; +struct meta_match *meta = (struct meta_match *) m->data; +struct meta_obj l_value, r_value; + +if (meta_get (skb, info, &meta->lvalue, &l_value) <0 || +meta_get (skb, info, &meta->rvalue, &r_value) <0 ) +return 0 ;
This is one part that confused me in my earlier email
net/sched/em_meta.c line 471
Quoted 1 line
net/sched/em_meta.c +1
-0+ r =meta_type_ops (&meta->lvalue)->compare (&l_value, &r_value);
And this is where it started
Overall comment: Well done
usability comment:
Ok, I have to admit I am not a friend of too-friendly, which is one of the faults IMO with netfilter; however, this would have joenetfilterfireman sweat a little too profusely.
I think you could add a new metafield in 31 seconds. I could probably do it in 95 seconds. Would be ideal to get average janeorjoenetfilterfireman to do it in 30 minutes - I dont think you are there.
cheers,
jamal
Re: [RFC] meta ematch
* jamal <[email protected]> 2005-01-16 11:11
Quoted 17 lines · Thomas Graf
Quoted 2 lines
diff -Nru
linux-2.6.10-bk14.orig/include/linux/tc_ematch/tc_em_meta.hlinux-2.6.10-bk14/include/linux/tc_ematch/tc_em_meta.h[..]
include/linux/tc_ematch/tc_em_meta.h line 26
Quoted 11 lines
include/linux/tc_ematch/tc_em_meta.h +11
-0+struct tcf_meta_val +{ +__u16 kind; +__u8 shift; +__u8 op; +}; + +#define TCF_META_TYPE_MASK (0xf << 12) +#define TCF_META_TYPE (kind) (((kind) & TCF_META_TYPE_MASK) >> 12) +#define TCF_META_ID_MASK 0x7ff +#define TCF_META_ID (kind) ((kind) & TCF_META_ID_MASK)Does it smell like there may be endianess issues? Probably not.
Not really as long as iproute2 uses the same byte ordering. It has the same issues as all other rtnetlink users.
Quoted 3 lines
include/linux/tc_ematch/tc_em_meta.h line 43
Quoted 1 line
include/linux/tc_ematch/tc_em_meta.h +1
-0+ TCF_META_ID_DEV,Since filters are attached to devices - is
TCF_META_ID_DEVof any value?
Yes, to compare against realdev and indev.
Quoted 7 lines
net/sched/em_meta.c line 35
Quoted 5 lines
net/sched/em_meta.c +5
-0+struct meta_value +{ +struct tcf_meta_val hdr; +unsigned long val; +unsigned int len;Those last two look like
meta_objyou defined above
Yes, they once were but the code is more readable this way because one cannot mistake meta_obj (temporary data) with the data/len in meta_value (persistent).
Quoted 3 lines
net/sched/em_meta.c line 60
Quoted 1 line
net/sched/em_meta.c +1
-0+return (v + (FIXED_1 /200 )) >>FSHIFT ;200 has some magic connotation to it - a define somewhere perhaps?
I coped this from the code for procfs ;->
Quoted 4 lines
Theres a lot of parameters not used at all in these calls .get calls. So far i have seen
dst->valueand some of the skb fields used. I apologize, I normally dont pick on these things - so if you have future plans for why you are passing those, keep them and ignore the comment.
I do have plans but for more complicated meta matches and they will take some time and will get pushed in a second iteration.
Quoted 9 lines
net/sched/em_meta.c line 103
Quoted 7 lines
net/sched/em_meta.c +7
-0+static inline int var_dev (struct net_device *dev,struct meta_obj *dst) +{ +if (unlikely (dev ==NULL )) +return -1 ; + + dst->value = (unsigned long ) dev->name; + dst->len =strlen (dev->name);So if device dissapears ... what happens to the pointer?
Not possible, the pointer is only legal to use while classifying, dst is on the stack of meta_match and the device cannot disappear while classyfing.
Quoted 10 lines
net/sched/em_meta.c line 372
Quoted 8 lines
net/sched/em_meta.c +8
-0+static void meta_var_apply_extras (struct meta_value *v, +struct meta_obj *dst) +{ +int shift = v->hdr.shift; + +if (shift && shift < dst->len) + dst->len -= shift; +}whats the purpose to the extras?
"eth0" shift 1 gets "eth" so we can emulate eth%. It will also get useful for ipv6 routing bits to implement the prefix.
Quoted 4 lines
Quoted 4 lines
net/sched/em_meta.c +4
-0+static int em_meta_match (struct sk_buff *skb,struct tcf_ematch *m, +struct tcf_pkt_info *info) +{ +int r;
Quoted 8 lines
net/sched/em_meta.c line 469
Quoted 6 lines
net/sched/em_meta.c +6
-0+struct meta_match *meta = (struct meta_match *) m->data; +struct meta_obj l_value, r_value; + +if (meta_get (skb, info, &meta->lvalue, &l_value) <0 || +meta_get (skb, info, &meta->rvalue, &r_value) <0 ) +return 0 ;This is one part that confused me in my earlier email
It transforms the meta data info in (l|r)value into 2 temporary meta objects for comparing. mgiht help if i find a better name.
Quoted 7 lines
Ok, I have to admit I am not a friend of too-friendly, which is one of the faults IMO with netfilter; however, this would have joenetfilterfireman sweat a little too profusely.
I think you could add a new metafield in 31 seconds. I could probably do it in 95 seconds. Would be ideal to get average janeorjoenetfilterfireman to do it in 30 minutes - I dont think you are there.
ideas? a step-by-step guide in Documentation/? ;->
Re: [RFC] meta ematch
Quoted 19 lines · Thomas Graf
* jamal <[email protected]> 2005-01-16 11:11
Quoted 17 lines · Thomas Graf
Quoted 2 lines
diff -Nru
linux-2.6.10-bk14.orig/include/linux/tc_ematch/tc_em_meta.hlinux-2.6.10-bk14/include/linux/tc_ematch/tc_em_meta.h[..]
include/linux/tc_ematch/tc_em_meta.h line 26
Quoted 11 lines
include/linux/tc_ematch/tc_em_meta.h +11
-0+struct tcf_meta_val +{ +__u16 kind; +__u8 shift; +__u8 op; +}; + +#define TCF_META_TYPE_MASK (0xf << 12) +#define TCF_META_TYPE (kind) (((kind) & TCF_META_TYPE_MASK) >> 12) +#define TCF_META_ID_MASK 0x7ff +#define TCF_META_ID (kind) ((kind) & TCF_META_ID_MASK)Does it smell like there may be endianess issues? Probably not.
Quoted 2 lines
Not really as long as iproute2 uses the same byte ordering. It has the same issues as all other rtnetlink users.
wont harm to do a quick test if you have hardware. pedit for example still has some occasional issues some issues with big endian which i havent had time to chase.
Quoted 5 lines
Quoted 3 lines
include/linux/tc_ematch/tc_em_meta.h line 43
Quoted 1 line
include/linux/tc_ematch/tc_em_meta.h +1
-0+ TCF_META_ID_DEV,Since filters are attached to devices - is
TCF_META_ID_DEVof any value?Yes, to compare against realdev and indev.
makes sense
Quoted 8 lines
Quoted 7 lines
net/sched/em_meta.c line 35
Quoted 5 lines
net/sched/em_meta.c +5
-0+struct meta_value +{ +struct tcf_meta_val hdr; +unsigned long val; +unsigned int len;Those last two look like
meta_objyou defined above
Quoted 4 lines
Yes, they once were but the code is more readable this way because one cannot mistake
meta_obj(temporary data) with the data/len inmeta_value(persistent).
fine
Quoted 5 lines
Quoted 3 lines
net/sched/em_meta.c line 60
Quoted 1 line
net/sched/em_meta.c +1
-0+return (v + (FIXED_1 /200 )) >>FSHIFT ;200 has some magic connotation to it - a define somewhere perhaps?
I coped this from the code for procfs ;->
know why they have that number? It must have some significance - or maybe someone just stuck their hand in the air and measured 200? ;->
Quoted 8 lines
Quoted 4 lines
Theres a lot of parameters not used at all in these calls .get calls. So far i have seen
dst->valueand some of the skb fields used. I apologize, I normally dont pick on these things - so if you have future plans for why you are passing those, keep them and ignore the comment.I do have plans but for more complicated meta matches and they will take some time and will get pushed in a second iteration.
np
Quoted 10 lines
Quoted 9 lines
net/sched/em_meta.c line 103
Quoted 7 lines
net/sched/em_meta.c +7
-0+static inline int var_dev (struct net_device *dev,struct meta_obj *dst) +{ +if (unlikely (dev ==NULL )) +return -1 ; + + dst->value = (unsigned long ) dev->name; + dst->len =strlen (dev->name);So if device dissapears ... what happens to the pointer?
Quoted 3 lines
Not possible, the pointer is only legal to use while classifying, dst is on the stack of
meta_matchand the device cannot disappear while classyfing.
makes sense then
Quoted 11 lines
Quoted 10 lines
net/sched/em_meta.c line 372
Quoted 8 lines
net/sched/em_meta.c +8
-0+static void meta_var_apply_extras (struct meta_value *v, +struct meta_obj *dst) +{ +int shift = v->hdr.shift; + +if (shift && shift < dst->len) + dst->len -= shift; +}whats the purpose to the extras?
Quoted 4 lines
"eth0" shift 1 gets "eth" so we can emulate eth%. It will also get useful for ipv6 routing bits to implement the prefix.
makes sense - ala ppp*
Quoted 25 lines
Quoted 4 lines
Quoted 4 lines
net/sched/em_meta.c +4
-0+static int em_meta_match (struct sk_buff *skb,struct tcf_ematch *m, +struct tcf_pkt_info *info) +{ +int r;Quoted 8 lines
net/sched/em_meta.c line 469
Quoted 6 lines
net/sched/em_meta.c +6
-0+struct meta_match *meta = (struct meta_match *) m->data; +struct meta_obj l_value, r_value; + +if (meta_get (skb, info, &meta->lvalue, &l_value) <0 || +meta_get (skb, info, &meta->rvalue, &r_value) <0 ) +return 0 ;This is one part that confused me in my earlier email
It transforms the meta data info in (l|r)value into 2 temporary meta objects for comparing. mgiht help if i find a better name.
Quoted 7 lines
Ok, I have to admit I am not a friend of too-friendly, which is one of the faults IMO with netfilter; however, this would have joenetfilterfireman sweat a little too profusely.
I think you could add a new metafield in 31 seconds. I could probably do it in 95 seconds. Would be ideal to get average janeorjoenetfilterfireman to do it in 30 minutes - I dont think you are there.
Quoted 1 line
ideas? a step-by-step guide in
Documentation/? ;->
I am not sure - probably more inlined commenting as you normally do.
cheers,
jamal
Re: [RFC] meta ematch
* jamal <[email protected]> 2005-01-16 12:18
Quoted 7 lines · Thomas Graf
Quoted 2 lines
Not really as long as iproute2 uses the same byte ordering. It has the same issues as all other rtnetlink users.
wont harm to do a quick test if you have hardware. pedit for example still has some occasional issues some issues with big endian which i havent had time to chase.
Uhmm.. yes. The endianess comes in at sutff like skb->protocol. Leaving it to userspace makes comparison beyond simple equals quite difficult. Providing a method to transform in kernel space adds more complexity.
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
net/sched/em_meta.c line 60
Quoted 1 line
net/sched/em_meta.c +1
-0+return (v + (FIXED_1 /200 )) >>FSHIFT ;200 has some magic connotation to it - a define somewhere perhaps?
I coped this from the code for procfs ;->
know why they have that number? It must have some significance - or maybe someone just stuck their hand in the air and measured 200? ;->
It is some kind of factor and has almost no impact in our case because it only changes the first 4 bits in the exp part and I'm only interested in the integer part. It might be a good idea to take a few bits in from the exp part and provide the load as *10^n where n is either 2 or 3, i.e. a load of 1.9 would be 190. I have to think a little more about this.
Re: [RFC] meta ematch
In reply to jamalQuoted 5 lines · jamal
Quoted 5 lines
net/sched/em_meta.c +5
-0+static int meta_int_loadavg_2 (struct sk_buff *skb,struct tcf_pkt_info *info, +struct meta_value *v,struct meta_obj *dst) +{ + dst->value =fixed_loadavg (avenrun[2 ]); +return 0 ;
Quoted 9 lines
Quoted 2 lines
+}
Theres a lot of parameters not used at all in these calls .get calls. So far i have seen
dst->valueand some of the skb fields used. I apologize, I normally dont pick on these things - so if you have future plans for why you are passing those, keep them and ignore the comment. BTW, it would probably be useful to return some mnemonic instead of 0.
Returning 0 for success and negative error codes is perfectly fine as long as you don't need any magic numbers (1, 2, ..).
Quoted 13 lines
net/sched/em_meta.c line 103
Quoted 9 lines
net/sched/em_meta.c +7
-0+static inline int var_dev (struct net_device *dev,struct meta_obj *dst) +{ +if (unlikely (dev ==NULL )) +return -1 ; + + dst->value = (unsigned long ) dev->name; + dst->len =strlen (dev->name);So if device dissapears ... what happens to the pointer?
Devices don't disappear during packet processing.
Quoted 9 lines
Quoted 9 lines
net/sched/em_meta.c +9
-0+static int meta_int_compare (struct meta_obj *a,struct meta_obj *b) +{ +/* Let gcc optimize it, the unlikely is not really based on +* some numbers but jump free code for missmatches seems +* more logical. +*/ +if (unlikely (a == b)) +return 0 ; +else if (a < b)
Quoted 10 lines
net/sched/em_meta.c line 386
Quoted 6 lines
net/sched/em_meta.c +4
-0+return -1 ; + else + return 1; +}Would be very useful to return mnemonics for readability.
Same as for above, everyone knows what to expect from a *_compare function. Returning stuff like CMP_LT, CMP_BT, .. is just ugly.
Regards
Patrick
Re: [RFC] meta ematch
Quoted 2 lines · Patrick McHardy
jamal wrote:
[..]
Quoted 4 lines
Quoted 1 line
BTW, it would probably be useful to return some mnemonic instead of 0.
Returning 0 for success and negative error codes is perfectly fine as long as you don't need any magic numbers (1, 2, ..).
[..]
Quoted 19 lines
Quoted 9 lines
Quoted 9 lines
net/sched/em_meta.c +9
-0+static int meta_int_compare (struct meta_obj *a,struct meta_obj *b) +{ +/* Let gcc optimize it, the unlikely is not really based on +* some numbers but jump free code for missmatches seems +* more logical. +*/ +if (unlikely (a == b)) +return 0 ; +else if (a < b)Quoted 10 lines
net/sched/em_meta.c line 386
Quoted 6 lines
net/sched/em_meta.c +4
-0+return -1 ; + else + return 1; +}Would be very useful to return mnemonics for readability.
Quoted 2 lines
Same as for above, everyone knows what to expect from a
*_comparefunction. Returning stuff likeCMP_LT,CMP_BT, .. is just ugly.
I am not sure i remember whether -1 or 1 is the LT even though i have used strcmp for years ;-> Actually i try hard not to have my brain remember. In the case of the .get function above, i may agree with you that returning MATCH_SUCEEDED may be a little overkill.
cheers,
jamal
* Thomas Graf:
Quoted 2 lines
I attached 4 patches of a first ematch implementation. Comments and suggestions very much appreciated. Compiles but untested.
This might infringe US patent 5,793,954 and the patents that reference it. 8-(
Quoted 7 lines · Florian Weimer
* Thomas Graf:
Quoted 2 lines
I attached 4 patches of a first ematch implementation. Comments and suggestions very much appreciated. Compiles but untested.
This might infringe US patent 5,793,954 and the patents that reference it. 8-(
hehe. We can sleep better knowing we dont run Linux using C++ ;-> That patents reads like it owns every classifier ever written in C++ that runs on a processor.
cheers,
jamal