Hello!

This is the try number two.
What was changed:
- Added selectable choice in Kconfig file (thanks Jamal!)
- Don't abuse tc_u32_sel to not break backward compatibility (thanks Patrick!).


Stephen, do you have any comments on iproute2 part? I know it's not perfect but this is the best way, I think. "u32 match mark vvvv mmmm" it's intuitive but breaks a little the levels, "u32 mark vvvv mmmm" it's ok but not intuitive....
If you want I can rewrite it if you want.


Thank you for your time.

Signed-off-by: Catalin(ux aka Dino) <catab at umbrella.ro>

---
Catalin(ux aka Dino) BOIE
catab at deuroconsult.ro
http://kernel.umbrella.ro/
--- linux.orig/net/sched/Kconfig        2004-10-19 00:55:06.000000000 +0300
+++ linux/net/sched/Kconfig     2004-11-09 12:47:36.000000000 +0200
@@ -334,6 +334,18 @@ config NET_CLS_IND
          Requires a new iproute2
          You MUST NOT turn this on if you dont have an update iproute2.
 
+config CLS_U32_MARK
+       bool "Use nfmark as a key in U32 classifier"
+       depends on NET_CLS_U32
+       help
+         This allows you to match mark in a u32 filter.
+         Example:
+         tc filter add dev eth0 protocol ip parent 1:0 prio 5 u32 \
+               match mark 0x0090 0xffff \
+               match ip dst 4.4.4.4 \
+               flowid 1:90
+         You must use a new iproute2 to use this feature.
+
 config NET_CLS_RSVP
        tristate "Special RSVP classifier"
        depends on NET_CLS && NET_QOS
--- linux.orig/net/sched/cls_u32.c      2004-10-19 00:53:45.000000000 +0300
+++ linux/net/sched/cls_u32.c   2004-11-09 13:56:42.000000000 +0200
@@ -27,6 +27,7 @@
  *     JHS: We should remove the CONFIG_NET_CLS_IND from here
  *     eventually when the meta match extension is made available
  *
+ *     nfmark match added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro>
  */
 
 #include <asm/uaccess.h>
@@ -57,6 +58,13 @@
 #include <net/pkt_sched.h>
 
 
+struct tc_u32_mark
+{
+       __u32           val;
+       __u32           mask;
+       __u32           success;
+};
+
 struct tc_u_knode
 {
        struct tc_u_knode       *next;
@@ -78,6 +86,9 @@ struct tc_u_knode
 #ifdef CONFIG_CLS_U32_PERF
        struct tc_u32_pcnt      *pf;
 #endif
+#ifdef CONFIG_CLS_U32_MARK
+       struct tc_u32_mark      mark;
+#endif
        struct tc_u32_sel       sel;
 };
 
@@ -139,6 +150,16 @@ next_knode:
                n->pf->rcnt +=1;
                j = 0;
 #endif
+
+#ifdef CONFIG_CLS_U32_MARK
+               if ((skb->nfmark & n->mark.mask) != n->mark.val) {
+                       n = n->next;
+                       goto next_knode;
+               } else {
+                       n->mark.success++;
+               }
+#endif
+
                for (i = n->sel.nkeys; i>0; i--, key++) {
 
                        if 
((*(u32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
@@ -615,6 +636,7 @@ static int u32_change(struct tcf_proto *
        struct tc_u_hnode *ht;
        struct tc_u_knode *n;
        struct tc_u32_sel *s;
+       struct tc_u32_mark *mark;
        struct rtattr *opt = tca[TCA_OPTIONS-1];
        struct rtattr *tb[TCA_U32_MAX];
        u32 htid;
@@ -718,6 +740,16 @@ static int u32_change(struct tcf_proto *
        }
        n->fshift = i;
 }
+
+#ifdef CONFIG_CLS_U32_MARK
+       if (tb[TCA_U32_MARK-1] == 0 ||
+               RTA_PAYLOAD(tb[TCA_U32_MARK-1]) < sizeof(struct tc_u32_mark))
+               return -EINVAL;
+       mark = RTA_DATA(tb[TCA_U32_MARK-1]);
+       memcpy(&n->mark, mark, sizeof(struct tc_u32_mark));
+       n->mark.success = 0;
+#endif
+
        err = u32_set_parms(tp->q, base, ht, n, tb, tca[TCA_RATE-1]);
        if (err == 0) {
                struct tc_u_knode **ins;
@@ -805,6 +837,12 @@ static int u32_dump(struct tcf_proto *tp
                        RTA_PUT(skb, TCA_U32_CLASSID, 4, &n->res.classid);
                if (n->ht_down)
                        RTA_PUT(skb, TCA_U32_LINK, 4, &n->ht_down->handle);
+
+#ifdef CONFIG_CLS_U32_MARK
+               if (n->mark.val || n->mark.mask)
+                       RTA_PUT(skb, TCA_U32_MARK, sizeof(n->mark), &n->mark);
+#endif
+
 #ifdef CONFIG_NET_CLS_ACT
                /* again for backward compatible mode - we want
                *  to work with both old and new modes of entering
--- linux.orig/include/linux/pkt_cls.h  2004-10-19 00:53:07.000000000 +0300
+++ linux/include/linux/pkt_cls.h       2004-11-09 09:50:45.000000000 +0200
@@ -190,6 +190,7 @@ enum
        TCA_U32_ACT,   
        TCA_U32_INDEV,
        TCA_U32_PCNT,
+       TCA_U32_MARK,
        __TCA_U32_MAX
 };
 
--- iproute2-2.6.9/tc/f_u32.c.orig      2004-11-04 15:38:53.000000000 +0200
+++ iproute2-2.6.9/tc/f_u32.c   2004-11-09 13:59:00.000000000 +0200
@@ -7,6 +7,7 @@
  *             2 of the License, or (at your option) any later version.
  *
  * Authors:    Alexey Kuznetsov, <[EMAIL PROTECTED]>
+ *             Match mark added by Catalin(ux aka Dino) BOIE <catab at 
umbrella.ro> [5 nov 2004]
  *
  */
 
@@ -33,7 +34,7 @@ static void explain(void)
        fprintf(stderr, "or         u32 divisor DIVISOR\n");
        fprintf(stderr, "\n");
        fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
-       fprintf(stderr, "       SAMPLE := { ip | ip6 | udp | tcp | icmp | 
u{32|16|8} } SAMPLE_ARGS\n");
+       fprintf(stderr, "       SAMPLE := { ip | ip6 | udp | tcp | icmp | 
u{32|16|8} | mark } SAMPLE_ARGS\n");
        fprintf(stderr, "       FILTERID := X:Y:Z\n");
 }
 
@@ -590,9 +591,42 @@ done:
        return res;
 }
 
+static int parse_mark(int *argc_p, char ***argv_p, struct nlmsghdr *n)
+{
+       int res = -1;
+       int argc = *argc_p;
+       char **argv = *argv_p;
+       struct tc_u32_mark mark;
+
+       if (argc <= 1)
+               return -1;
+
+       if (get_u32(&mark.val, *argv, 0)) {
+               fprintf(stderr, "Illegal \"mark\" value\n");
+               return -1;
+       }
+       NEXT_ARG();
+
+       if (get_u32(&mark.mask, *argv, 0)) {
+               fprintf(stderr, "Illegal \"mark\" mask\n");
+               return -1;
+       }
+       NEXT_ARG();
+
+       if ((mark.val & mark.mask) != mark.val) {
+               fprintf(stderr, "Illegal \"mark\" (impossible combination)\n");
+               return -1;
+       }
 
+       addattr_l(n, MAX_MSG, TCA_U32_MARK, &mark, sizeof(mark));
+       res = 0;
+
+       *argc_p = argc;
+       *argv_p = argv;
+       return res;
+}
 
-static int parse_selector(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
+static int parse_selector(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, 
struct nlmsghdr *n)
 {
        int argc = *argc_p;
        char **argv = *argv_p;
@@ -641,6 +675,12 @@ static int parse_selector(int *argc_p, c
                res = parse_icmp(&argc, &argv, sel);
                goto done;
        }
+       if (matches(*argv, "mark") == 0) {
+               NEXT_ARG();
+               res = parse_mark(&argc, &argv, n);
+               goto done;
+       }
+
        return -1;
 
 done:
@@ -760,7 +800,7 @@ static int u32_parse_opt(struct filter_u
        while (argc > 0) {
                if (matches(*argv, "match") == 0) {
                        NEXT_ARG();
-                       if (parse_selector(&argc, &argv, &sel.sel)) {
+                       if (parse_selector(&argc, &argv, &sel.sel, n)) {
                                fprintf(stderr, "Illegal \"match\"\n");
                                return -1;
                        }
@@ -839,7 +879,7 @@ static int u32_parse_opt(struct filter_u
                                struct tc_u32_key keys[4];
                        } sel2;
                        NEXT_ARG();
-                       if (parse_selector(&argc, &argv, &sel2.sel)) {
+                       if (parse_selector(&argc, &argv, &sel2.sel, n)) {
                                fprintf(stderr, "Illegal \"sample\"\n");
                                return -1;
                        }
@@ -964,11 +1004,22 @@ static int u32_print_opt(struct filter_u
                pf = RTA_DATA(tb[TCA_U32_PCNT]);
        }
 
+       if (sel && show_stats && NULL != pf)
+               fprintf(f, " (rule hit %llu success %llu)",pf->rcnt,pf->rhit);
+
+       if (tb[TCA_U32_MARK]) {
+               struct tc_u32_mark *mark = RTA_DATA(tb[TCA_U32_MARK]);
+               if (RTA_PAYLOAD(tb[TCA_U32_MARK]) < sizeof(*mark)) {
+                       fprintf(f, "\n  Invalid mark (kernel&iproute2 
mismatch)\n");
+               } else {
+                       fprintf(f, "\n  mark 0x%04x 0x%04x (success %d)",
+                               mark->val, mark->mask, mark->success);
+               }
+       }
+
        if (sel) {
                int i;
                struct tc_u32_key *key = sel->keys;
-               if (show_stats && NULL != pf)
-                       fprintf(f, " (rule hit %llu success 
%llu)",pf->rcnt,pf->rhit);
                if (sel->nkeys) {
                        for (i=0; i<sel->nkeys; i++, key++) {
                                fprintf(f, "\n  match %08x/%08x at %s%d",
--- iproute2-2.6.9/include/linux/pkt_cls.h.orig 2004-11-04 15:42:27.000000000 
+0200
+++ iproute2-2.6.9/include/linux/pkt_cls.h      2004-11-09 13:58:15.000000000 
+0200
@@ -190,6 +190,7 @@ enum
        TCA_U32_ACT,   
        TCA_U32_INDEV,
        TCA_U32_PCNT,
+       TCA_U32_MARK,
        __TCA_U32_MAX
 };
 
@@ -224,6 +225,14 @@ struct tc_u32_pcnt
        __u64 rhit;
        __u64 kcnts[0];
 };
+
+struct tc_u32_mark
+{
+       __u32   val;
+       __u32   mask;
+       __u32   success;
+};
+
 /* Flags */
 
 #define TC_U32_TERMINAL                1

Reply via email to