X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fsched%2Fematch.c;h=f3a104e323bddd50c299c74c928a95038f1f5af5;hb=1bec3f1a3ec5d922d1040c7845b82cd496c02d90;hp=8f8a16da72a8970acb1c11357ec228573b85cad4;hpb=c7b1b24978d89efab7d420bbdc9557dbe6259c89;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 8f8a16d..f3a104e 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -37,12 +37,12 @@ * --------<-POP--------- * * where B is a virtual ematch referencing to sequence starting with B1. - * + * * ========================================================================== * * How to write an ematch in 60 seconds * ------------------------------------ - * + * * 1) Provide a matcher function: * static int my_match(struct sk_buff *skb, struct tcf_ematch *m, * struct tcf_pkt_info *info) @@ -84,10 +84,7 @@ #include #include #include -#include -#include #include -#include #include #include #include @@ -115,7 +112,7 @@ static inline struct tcf_ematch_ops * tcf_em_lookup(u16 kind) /** * tcf_em_register - register an extended match - * + * * @ops: ematch operations lookup table * * This function must be called by ematches to announce their presence. @@ -211,7 +208,7 @@ static int tcf_em_validate(struct tcf_proto *tp, if (ref <= idx) goto errout; - + em->data = ref; } else { /* Note: This lookup will increase the module refcnt @@ -225,6 +222,19 @@ static int tcf_em_validate(struct tcf_proto *tp, if (em->ops == NULL) { err = -ENOENT; +#ifdef CONFIG_KMOD + __rtnl_unlock(); + request_module("ematch-kind-%u", em_hdr->kind); + rtnl_lock(); + em->ops = tcf_em_lookup(em_hdr->kind); + if (em->ops) { + /* We dropped the RTNL mutex in order to + * perform the module load. Tell the caller + * to replay the request. */ + module_put(em->ops->owner); + err = -EAGAIN; + } +#endif goto errout; } @@ -327,7 +337,7 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct rtattr *rta, /* We do not use rtattr_parse_nested here because the maximum * number of attributes is unknown. This saves us the allocation * for a tb buffer which would serve no purpose at all. - * + * * The array of rt attributes is parsed in the order as they are * provided, their type must be incremental from 1 to n. Even * if it does not serve any real purpose, a failure of sticking @@ -399,7 +409,7 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree) module_put(em->ops->owner); } } - + tree->hdr.nmatches = 0; kfree(tree->matches); } @@ -419,17 +429,19 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree) int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv) { int i; - struct rtattr * top_start = (struct rtattr*) skb->tail; - struct rtattr * list_start; + u8 *tail; + struct rtattr *top_start = (struct rtattr *)skb_tail_pointer(skb); + struct rtattr *list_start; RTA_PUT(skb, tlv, 0, NULL); RTA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr); - list_start = (struct rtattr *) skb->tail; + list_start = (struct rtattr *)skb_tail_pointer(skb); RTA_PUT(skb, TCA_EMATCH_TREE_LIST, 0, NULL); + tail = skb_tail_pointer(skb); for (i = 0; i < tree->hdr.nmatches; i++) { - struct rtattr *match_start = (struct rtattr*) skb->tail; + struct rtattr *match_start = (struct rtattr *)tail; struct tcf_ematch *em = tcf_em_get_match(tree, i); struct tcf_ematch_hdr em_hdr = { .kind = em->ops ? em->ops->kind : TCF_EM_CONTAINER, @@ -448,11 +460,12 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv) } else if (em->datalen > 0) RTA_PUT_NOHDR(skb, em->datalen, (void *) em->data); - match_start->rta_len = skb->tail - (u8*) match_start; + tail = skb_tail_pointer(skb); + match_start->rta_len = tail - (u8 *)match_start; } - list_start->rta_len = skb->tail - (u8 *) list_start; - top_start->rta_len = skb->tail - (u8 *) top_start; + list_start->rta_len = tail - (u8 *)list_start; + top_start->rta_len = tail - (u8 *)top_start; return 0;