]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/commitdiff
em_canid: Number of rules passed during configuration is no longer limited.
authorRostislav Lisovy <lisovy@gmail.com>
Fri, 22 Jun 2012 14:16:39 +0000 (16:16 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Fri, 22 Jun 2012 14:16:39 +0000 (16:16 +0200)
net/sched/em_canid.c

index 5cc6e5e4b68b65eb9e82347b87e5587f15e52d3b..1cdd4a175afe8928427b23cabc809df71e58d3cf 100644 (file)
 #include <net/pkt_cls.h>
 #include <linux/can.h>
 
-#define EM_CAN_RULES_SIZE                              32
+#define EM_CAN_RULES_MAX                                       500
 
 struct canid_match {
-       /*
-        * Raw rules copied from netlink message; Used for sending
-        * information to userspace (when 'tc filter show' is invoked)
-        * AND when matching EFF frames
-        */
-       struct can_filter rules_raw[EM_CAN_RULES_SIZE];
-
        /* For each SFF CAN ID (11 bit) there is one record in this bitfield */
        DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS));
 
        int rules_count;
-       int eff_rules_count;
        int sff_rules_count;
+       int eff_rules_count;
+
+       /*
+        * Raw rules copied from netlink message; Used for sending
+        * information to userspace (when 'tc filter show' is invoked)
+        * AND when matching EFF frames
+        */
+       struct can_filter rules_raw[];
 };
 
 /**
@@ -90,7 +90,7 @@ static void em_canid_sff_match_add(struct canid_match *cm, u32 can_id,
 
 static inline struct canid_match *em_canid_priv(struct tcf_ematch *m)
 {
-       return (struct canid_match *) (m)->data;
+       return (struct canid_match *) m->data;
 }
 
 static int em_canid_match(struct sk_buff *skb, struct tcf_ematch *m,
@@ -131,24 +131,29 @@ static int em_canid_change(struct tcf_proto *tp, void *data, int len,
                                         * fixed size EM_CAN_RULES_SIZE
                                         */
        struct canid_match *cm;
+       struct canid_match *cm_old = (struct canid_match *) m->data;
        int err;
        int i;
+       int rulescnt;
 
        if (len < sizeof(struct can_filter))
                return -EINVAL;
 
+       rulescnt = len / sizeof(struct can_filter);
+
        err = -ENOBUFS;
-       cm = kzalloc(sizeof(*cm), GFP_KERNEL);
+       cm = kzalloc(sizeof(struct canid_match) + sizeof(struct can_filter) *
+               rulescnt, GFP_KERNEL);
        if (cm == NULL)
                goto errout;
 
        cm->sff_rules_count = 0;
        cm->eff_rules_count = 0;
-       cm->rules_count = len/sizeof(struct can_filter);
+       cm->rules_count = rulescnt;
        err = -EINVAL;
 
        /* Be sure to fit into the array */
-       if (cm->rules_count > EM_CAN_RULES_SIZE)
+       if (cm->rules_count > EM_CAN_RULES_MAX)
                goto errout_free;
 
        /*
@@ -191,6 +196,11 @@ static int em_canid_change(struct tcf_proto *tp, void *data, int len,
        m->datalen = sizeof(*cm);
        m->data = (unsigned long) cm;
 
+       if (cm_old != NULL) {
+               printk("canid: Configuring an existing ematch!\n");
+               kfree(cm_old);
+       }
+
        return 0;
 
 errout_free: