···11111212- reg : Offset and length of the register set for this device1313- interrupts : Interrupt tuple for this device1414+1515+Optional properties:1616+1417- clock-frequency : The oscillator frequency driving the flexcan device15181619Example:
···104104 unsigned long rcv_entries_max;105105};106106107107+/* receive filters subscribed for 'all' CAN devices */108108+extern struct dev_rcv_lists can_rx_alldev_list;109109+107110/* function prototypes for the CAN networklayer procfs (proc.c) */108111extern void can_init_proc(void);109112extern void can_remove_proc(void);
-3
net/can/proc.c
···8383 [RX_EFF] = "rx_eff",8484};85858686-/* receive filters subscribed for 'all' CAN devices */8787-extern struct dev_rcv_lists can_rx_alldev_list;8888-8986/*9087 * af_can statistics stuff9188 */
+10
net/sched/Kconfig
···507507 To compile this code as a module, choose M here: the508508 module will be called em_text.509509510510+config NET_EMATCH_CANID511511+ tristate "CAN Identifier"512512+ depends on NET_EMATCH && CAN513513+ ---help---514514+ Say Y here if you want to be able to classify CAN frames based515515+ on CAN Identifier.516516+517517+ To compile this code as a module, choose M here: the518518+ module will be called em_canid.519519+510520config NET_CLS_ACT511521 bool "Actions"512522 ---help---
···11+/*22+ * em_canid.c Ematch rule to match CAN frames according to their CAN IDs33+ *44+ * This program is free software; you can distribute it and/or55+ * modify it under the terms of the GNU General Public License66+ * as published by the Free Software Foundation; either version77+ * 2 of the License, or (at your option) any later version.88+ *99+ * Idea: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>1010+ * Copyright: (c) 2011 Czech Technical University in Prague1111+ * (c) 2011 Volkswagen Group Research1212+ * Authors: Michal Sojka <sojkam1@fel.cvut.cz>1313+ * Pavel Pisa <pisa@cmp.felk.cvut.cz>1414+ * Rostislav Lisovy <lisovy@gmail.cz>1515+ * Funded by: Volkswagen Group Research1616+ */1717+1818+#include <linux/slab.h>1919+#include <linux/module.h>2020+#include <linux/types.h>2121+#include <linux/kernel.h>2222+#include <linux/string.h>2323+#include <linux/skbuff.h>2424+#include <net/pkt_cls.h>2525+#include <linux/can.h>2626+2727+#define EM_CAN_RULES_MAX 5002828+2929+struct canid_match {3030+ /* For each SFF CAN ID (11 bit) there is one record in this bitfield */3131+ DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS));3232+3333+ int rules_count;3434+ int sff_rules_count;3535+ int eff_rules_count;3636+3737+ /*3838+ * Raw rules copied from netlink message; Used for sending3939+ * information to userspace (when 'tc filter show' is invoked)4040+ * AND when matching EFF frames4141+ */4242+ struct can_filter rules_raw[];4343+};4444+4545+/**4646+ * em_canid_get_id() - Extracts Can ID out of the sk_buff structure.4747+ */4848+static canid_t em_canid_get_id(struct sk_buff *skb)4949+{5050+ /* CAN ID is stored within the data field */5151+ struct can_frame *cf = (struct can_frame *)skb->data;5252+5353+ return cf->can_id;5454+}5555+5656+static void em_canid_sff_match_add(struct canid_match *cm, u32 can_id,5757+ u32 can_mask)5858+{5959+ int i;6060+6161+ /*6262+ * Limit can_mask and can_id to SFF range to6363+ * protect against write after end of array6464+ */6565+ can_mask &= CAN_SFF_MASK;6666+ can_id &= can_mask;6767+6868+ /* Single frame */6969+ if (can_mask == CAN_SFF_MASK) {7070+ set_bit(can_id, cm->match_sff);7171+ return;7272+ }7373+7474+ /* All frames */7575+ if (can_mask == 0) {7676+ bitmap_fill(cm->match_sff, (1 << CAN_SFF_ID_BITS));7777+ return;7878+ }7979+8080+ /*8181+ * Individual frame filter.8282+ * Add record (set bit to 1) for each ID that8383+ * conforms particular rule8484+ */8585+ for (i = 0; i < (1 << CAN_SFF_ID_BITS); i++) {8686+ if ((i & can_mask) == can_id)8787+ set_bit(i, cm->match_sff);8888+ }8989+}9090+9191+static inline struct canid_match *em_canid_priv(struct tcf_ematch *m)9292+{9393+ return (struct canid_match *)m->data;9494+}9595+9696+static int em_canid_match(struct sk_buff *skb, struct tcf_ematch *m,9797+ struct tcf_pkt_info *info)9898+{9999+ struct canid_match *cm = em_canid_priv(m);100100+ canid_t can_id;101101+ int match = 0;102102+ int i;103103+ const struct can_filter *lp;104104+105105+ can_id = em_canid_get_id(skb);106106+107107+ if (can_id & CAN_EFF_FLAG) {108108+ for (i = 0, lp = cm->rules_raw;109109+ i < cm->eff_rules_count; i++, lp++) {110110+ if (!(((lp->can_id ^ can_id) & lp->can_mask))) {111111+ match = 1;112112+ break;113113+ }114114+ }115115+ } else { /* SFF */116116+ can_id &= CAN_SFF_MASK;117117+ match = (test_bit(can_id, cm->match_sff) ? 1 : 0);118118+ }119119+120120+ return match;121121+}122122+123123+static int em_canid_change(struct tcf_proto *tp, void *data, int len,124124+ struct tcf_ematch *m)125125+{126126+ struct can_filter *conf = data; /* Array with rules */127127+ struct canid_match *cm;128128+ struct canid_match *cm_old = (struct canid_match *)m->data;129129+ int i;130130+131131+ if (!len)132132+ return -EINVAL;133133+134134+ if (len % sizeof(struct can_filter))135135+ return -EINVAL;136136+137137+ if (len > sizeof(struct can_filter) * EM_CAN_RULES_MAX)138138+ return -EINVAL;139139+140140+ cm = kzalloc(sizeof(struct canid_match) + len, GFP_KERNEL);141141+ if (!cm)142142+ return -ENOMEM;143143+144144+ cm->rules_count = len / sizeof(struct can_filter);145145+146146+ /*147147+ * We need two for() loops for copying rules into two contiguous148148+ * areas in rules_raw to process all eff rules with a simple loop.149149+ * NB: The configuration interface supports sff and eff rules.150150+ * We do not support filters here that match for the same can_id151151+ * provided in a SFF and EFF frame (e.g. 0x123 / 0x80000123).152152+ * For this (unusual case) two filters have to be specified. The153153+ * SFF/EFF separation is done with the CAN_EFF_FLAG in the can_id.154154+ */155155+156156+ /* Fill rules_raw with EFF rules first */157157+ for (i = 0; i < cm->rules_count; i++) {158158+ if (conf[i].can_id & CAN_EFF_FLAG) {159159+ memcpy(cm->rules_raw + cm->eff_rules_count,160160+ &conf[i],161161+ sizeof(struct can_filter));162162+163163+ cm->eff_rules_count++;164164+ }165165+ }166166+167167+ /* append SFF frame rules */168168+ for (i = 0; i < cm->rules_count; i++) {169169+ if (!(conf[i].can_id & CAN_EFF_FLAG)) {170170+ memcpy(cm->rules_raw171171+ + cm->eff_rules_count172172+ + cm->sff_rules_count,173173+ &conf[i], sizeof(struct can_filter));174174+175175+ cm->sff_rules_count++;176176+177177+ em_canid_sff_match_add(cm,178178+ conf[i].can_id, conf[i].can_mask);179179+ }180180+ }181181+182182+ m->datalen = sizeof(struct canid_match) + len;183183+ m->data = (unsigned long)cm;184184+185185+ if (cm_old != NULL) {186186+ pr_err("canid: Configuring an existing ematch!\n");187187+ kfree(cm_old);188188+ }189189+190190+ return 0;191191+}192192+193193+static void em_canid_destroy(struct tcf_proto *tp, struct tcf_ematch *m)194194+{195195+ struct canid_match *cm = em_canid_priv(m);196196+197197+ kfree(cm);198198+}199199+200200+static int em_canid_dump(struct sk_buff *skb, struct tcf_ematch *m)201201+{202202+ struct canid_match *cm = em_canid_priv(m);203203+204204+ /*205205+ * When configuring this ematch 'rules_count' is set not to exceed206206+ * 'rules_raw' array size207207+ */208208+ if (nla_put_nohdr(skb, sizeof(struct can_filter) * cm->rules_count,209209+ &cm->rules_raw) < 0)210210+ return -EMSGSIZE;211211+212212+ return 0;213213+}214214+215215+static struct tcf_ematch_ops em_canid_ops = {216216+ .kind = TCF_EM_CANID,217217+ .change = em_canid_change,218218+ .match = em_canid_match,219219+ .destroy = em_canid_destroy,220220+ .dump = em_canid_dump,221221+ .owner = THIS_MODULE,222222+ .link = LIST_HEAD_INIT(em_canid_ops.link)223223+};224224+225225+static int __init init_em_canid(void)226226+{227227+ return tcf_em_register(&em_canid_ops);228228+}229229+230230+static void __exit exit_em_canid(void)231231+{232232+ tcf_em_unregister(&em_canid_ops);233233+}234234+235235+MODULE_LICENSE("GPL");236236+237237+module_init(init_em_canid);238238+module_exit(exit_em_canid);239239+240240+MODULE_ALIAS_TCF_EMATCH(TCF_EM_CANID);