]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Added feature to list created gateway jobs.
authorhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Mon, 22 Feb 2010 09:57:12 +0000 (09:57 +0000)
committerhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Mon, 22 Feb 2010 09:57:12 +0000 (09:57 +0000)
Also added some fixes and removed debug printf's.

git-svn-id: svn://svn.berlios.de//socketcan/trunk@1140 030b6a49-0b11-0410-94ab-b0dab22257f2

can-utils/cangw.c
kernel/2.6/include/socketcan/can/gw.h
kernel/2.6/net/can/gw.c

index 0d33333f14c8715b50cbe0c061197ca8d9e05168..c03535c658e84a51a943e6758fb9daf48eb90750 100644 (file)
@@ -95,13 +95,47 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
        return 0;
 }
 
+void printfilter(const void *data)
+{
+       struct can_filter *filter = (struct can_filter *)data;
+
+       printf("-f %X:%X ", filter->can_id, filter->can_mask);
+}
+
+void printmod(const char *type, const void *data)
+{
+       struct modattr mod;
+       int i;
+
+       memcpy (&mod, data, CGW_MODATTR_LEN);
+
+       printf("-m %s:", type);
+
+       if (mod.modtype & CGW_MOD_ID)
+               printf("I");
+
+       if (mod.modtype & CGW_MOD_DLC)
+               printf("L");
+
+       if (mod.modtype & CGW_MOD_DATA)
+               printf("D");
+
+       printf(":%X.%X.", mod.cf.can_id, mod.cf.can_dlc);
+
+       for (i = 0; i < 8; i++)
+               printf("%02X", mod.cf.data[i]);
+
+       printf(" ");
+}
+
+
 void print_usage(char *prg)
 {
        fprintf(stderr, "\nUsage: %s [options]\n\n", prg);
        fprintf(stderr, "Commands:  -A (add a new rule)\n");
        fprintf(stderr, "           -D (delete a rule)\n");
        fprintf(stderr, "           -F (flush - delete all rules)  [not yet implemented]\n");
-       fprintf(stderr, "           -L (list all rules)            [not yet implemented]\n");
+       fprintf(stderr, "           -L (list all rules)\n");
        fprintf(stderr, "Mandatory: -s <src_dev>  (source netdevice)\n");
        fprintf(stderr, "           -d <dst_dev>  (destination netdevice)\n");
        fprintf(stderr, "Options:   -t (preserve src_dev rx timestamp)\n");
@@ -216,8 +250,15 @@ int main(int argc, char **argv)
        } req;
 
        char rxbuf[8192]; /* netlink receive buffer */
+       char ifname[IF_NAMESIZE]; /* internface name for if_indextoname() */
        struct nlmsghdr *nlh;
        struct nlmsgerr *rte;
+       struct rtcanmsg *rtc;
+       struct rtattr *rta;
+       __u32 handled = 0;
+       __u32 dropped = 0;
+       int rtlen;
+       int len;
 
        struct can_filter filter;
        struct sockaddr_nl nladdr;
@@ -299,8 +340,13 @@ int main(int argc, char **argv)
                }
        }
 
-       if ((argc - optind != 0) || (cmd == UNSPEC) ||
-           (!req.rtcan.src_ifindex) || (!req.rtcan.dst_ifindex)) {
+       if ((argc - optind != 0) || (cmd == UNSPEC)) {
+               print_usage(basename(argv[0]));
+               exit(1);
+       }
+
+       if ((cmd == ADD || cmd == DEL) &&
+           ((!req.rtcan.src_ifindex) || (!req.rtcan.dst_ifindex))) {
                print_usage(basename(argv[0]));
                exit(1);
        }
@@ -319,6 +365,11 @@ int main(int argc, char **argv)
                req.nh.nlmsg_type  = RTM_DELROUTE;
                break;
 
+       case LIST:
+               req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+               req.nh.nlmsg_type  = RTM_GETROUTE;
+               break;
+
        default:
                printf("This function is not yet implemented.\n");
                exit(1);
@@ -335,9 +386,11 @@ int main(int argc, char **argv)
        if (have_filter)
                addattr_l(&req.nh, sizeof(req), CGW_FILTER, &filter, sizeof(filter));
 
-       // a better example code
-       // modmsg.modtype = CGW_MOD_ID;
-       // addattr_l(&req.n, sizeof(req), CGW_MOD_SET, &modmsg, CGW_MODATTR_LEN);
+       /*
+        * a better example code
+        * modmsg.modtype = CGW_MOD_ID;
+        * addattr_l(&req.n, sizeof(req), CGW_MOD_SET, &modmsg, CGW_MODATTR_LEN);
+        */
 
        /* add up to CGW_MOD_FUNCS modification definitions */
        for (i = 0; i < modidx; i++)
@@ -355,7 +408,7 @@ int main(int argc, char **argv)
                return err;
        }
 
-       // clean netlink receive buffer
+       /* clean netlink receive buffer */
        bzero(rxbuf, sizeof(rxbuf));
 
        if (cmd == ADD || cmd == DEL) {
@@ -374,6 +427,86 @@ int main(int argc, char **argv)
                err = rte->error;
                if (err < 0)
                        fprintf(stderr, "netlink error %d (%s)\n", err, strerror(abs(err)));
+
+       } else {
+
+               /* cmd == LIST (for now) */
+
+               while (1) {
+                       len = recv(s, &rxbuf, sizeof(rxbuf), 0);
+                       if (len < 0) {
+                               perror("netlink recv");
+                               return len;
+                       }
+                       nlh = (struct nlmsghdr *)rxbuf;
+                       if (nlh->nlmsg_type == NLMSG_DONE) 
+                               break;
+
+                       rtc = (struct rtcanmsg *)NLMSG_DATA(nlh);
+                       if (rtc->can_family != AF_CAN) {
+                               printf("received msg from unknown family %d\n", rtc->can_family);
+                               return -EINVAL;
+                       }
+
+                       /*
+                        * print list in a representation that
+                        * can be used directly for start scripts
+                        */
+
+                       printf("%s -A ", basename(argv[0]));
+                       printf("-s %s ", if_indextoname(rtc->src_ifindex, ifname));
+                       printf("-d %s ", if_indextoname(rtc->dst_ifindex, ifname));
+
+                       if (rtc->can_txflags & CAN_GW_TXFLAGS_ECHO)
+                               printf("-e ");
+
+                       if (rtc->can_txflags & CAN_GW_TXFLAGS_SRC_TSTAMP)
+                               printf("-t ");
+
+                       /* check for attributes */
+                       rta = (struct rtattr *) RTM_RTA(rtc);
+                       rtlen = RTM_PAYLOAD(nlh);
+                       for(;RTA_OK(rta, rtlen);rta=RTA_NEXT(rta,rtlen))
+                       {
+                               switch(rta->rta_type) {
+
+                               case CGW_FILTER:
+                                       printfilter(RTA_DATA(rta));
+                                       break;
+
+                               case CGW_MOD_AND:
+                                       printmod("AND", RTA_DATA(rta));
+                                       break;
+
+                               case CGW_MOD_OR:
+                                       printmod("OR", RTA_DATA(rta));
+                                       break;
+
+                               case CGW_MOD_XOR:
+                                       printmod("XOR", RTA_DATA(rta));
+                                       break;
+
+                               case CGW_MOD_SET:
+                                       printmod("SET", RTA_DATA(rta));
+                                       break;
+
+                               case CGW_HANDLED:
+                                       handled = *(__u32 *)RTA_DATA(rta);
+                                       break;
+
+                               case CGW_DROPPED:
+                                       dropped = *(__u32 *)RTA_DATA(rta);
+                                       break;
+
+                               default:
+                                       printf("Unknown attribute %d!", rta->rta_type);
+                                       return -EINVAL;
+                                       break;
+                               }
+                       }
+
+                       printf("# %d handled %d dropped\n", handled, dropped); /* end of entry */
+               }
        }
 
        close(s);
index df02ee7ccf808b87ea7f731368085a5bccdb0d09..5a963ed54352c27e60389bddf4f1958d35b2228b 100644 (file)
@@ -37,6 +37,8 @@ enum {
        CGW_MOD_OR,     /* CAN frame modification binary OR */
        CGW_MOD_XOR,    /* CAN frame modification binary XOR */
        CGW_MOD_SET,    /* CAN frame modification set alternate values */
+       CGW_HANDLED,    /* number of handled CAN frames */
+       CGW_DROPPED,    /* number of dropped CAN frames */
        __CGW_MAX
 };
 
index 35e80572b63147b86b22db1eee11f557a8938a03..7b999c70d78dedd0e23d2e6e10dff0ec716c7390 100644 (file)
@@ -61,7 +61,7 @@
 #include <socketcan/can/version.h> /* for RCSID. Removed by mkpatch script */
 RCSID("$Id$");
 
-#define CAN_GW_VERSION "20100218"
+#define CAN_GW_VERSION "20100222"
 static __initdata const char banner[] =
        KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
 
@@ -91,6 +91,12 @@ struct can_can_gw {
                struct can_frame xor;
                struct can_frame set;
        } modframe;
+       struct {
+               u8 and;
+               u8 or;
+               u8 xor;
+               u8 set;
+       } modtype;
        void (*modfunc[MAX_MODFUNCTIONS])(struct can_frame *cf,
                                          struct can_can_gw *mod);
 };
@@ -177,7 +183,7 @@ static void gw_rcv(struct sk_buff *skb, void *data)
        if (skb->sk == GW_SK_MAGIC)
                return;
 
-       if (!netif_running(gwj->dst_dev)) {
+       if (!(gwj->dst_dev->flags & IFF_UP)) {
                gwj->dropped_frames++;
                return;
        }
@@ -269,14 +275,118 @@ static int gw_notifier(struct notifier_block *nb,
        return NOTIFY_DONE;
 }
 
-/*
- * Dump information about all ports, in response to GETROUTE
- */
+static int gw_put_job(struct sk_buff *skb, struct gw_job *gwj)
+{
+       struct {
+               struct can_frame cf;
+               u8 modtype;
+       } __attribute__((packed)) mb;
+
+       struct rtcanmsg *rtcan;
+       struct nlmsghdr *nlh = nlmsg_put(skb, 0, 0, 0, sizeof(*rtcan), 0);
+       if (!nlh)
+               return -EMSGSIZE;
+
+       rtcan = nlmsg_data(nlh);
+       rtcan->can_family = AF_CAN;
+       rtcan->src_ifindex = gwj->src_dev->ifindex;
+       rtcan->dst_ifindex = gwj->dst_dev->ifindex;
+       rtcan->can_txflags = 0;
+
+       if (gwj->flags & CAN_TX_ECHO)
+               rtcan->can_txflags |= CAN_GW_TXFLAGS_ECHO;
+
+       if (gwj->flags & CAN_TX_SRC_TSTAMP)
+               rtcan->can_txflags |= CAN_GW_TXFLAGS_SRC_TSTAMP;
+
+       /* check non default settings of attributes */
+       if (gwj->handled_frames) {
+               if (nla_put_u32(skb, CGW_HANDLED, gwj->handled_frames) < 0)
+                       goto cancel;
+               else
+                       nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
+       }
+
+       if (gwj->dropped_frames) {
+               if (nla_put_u32(skb, CGW_DROPPED, gwj->dropped_frames) < 0)
+                       goto cancel;
+               else
+                       nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
+       }
+
+       if (gwj->ccgw.filter.can_id || gwj->ccgw.filter.can_mask) {
+               if (nla_put(skb, CGW_FILTER, sizeof(struct can_filter),
+                           &gwj->ccgw.filter) < 0)
+                       goto cancel;
+               else
+                       nlh->nlmsg_len += NLA_HDRLEN +
+                               NLA_ALIGN(sizeof(struct can_filter));
+       }
+
+       if (gwj->ccgw.modtype.and) {
+               memcpy(&mb.cf, &gwj->ccgw.modframe.and, sizeof(mb.cf));
+               mb.modtype = gwj->ccgw.modtype.and;
+               if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0)
+                       goto cancel;
+               else
+                       nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
+       }
+
+       if (gwj->ccgw.modtype.or) {
+               memcpy(&mb.cf, &gwj->ccgw.modframe.or, sizeof(mb.cf));
+               mb.modtype = gwj->ccgw.modtype.or;
+               if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0)
+                       goto cancel;
+               else
+                       nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
+       }
+
+       if (gwj->ccgw.modtype.xor) {
+               memcpy(&mb.cf, &gwj->ccgw.modframe.xor, sizeof(mb.cf));
+               mb.modtype = gwj->ccgw.modtype.xor;
+               if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0)
+                       goto cancel;
+               else
+                       nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
+       }
+
+       if (gwj->ccgw.modtype.set) {
+               memcpy(&mb.cf, &gwj->ccgw.modframe.set, sizeof(mb.cf));
+               mb.modtype = gwj->ccgw.modtype.set;
+               if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0)
+                       goto cancel;
+               else
+                       nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
+       }
+
+       return skb->len;
+
+cancel:
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
+}
+
+/* Dump information about all CAN gateway jobs, in response to RTM_GETROUTE */
 static int gw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       printk(KERN_INFO "%s (TODO)\n", __FUNCTION__);
+       struct gw_job *gwj = NULL;
+       struct hlist_node *n;
+       int idx = 0;
+       int ret = 0;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(gwj, n, &can_gw_list, list) {
+               if (idx >= cb->args[0]) {
+                       ret = gw_put_job(skb, gwj);
+                       if (ret > 0)
+                               cb->args[0]++;
+                       break;
+               }
+               idx++;
+       }
+       rcu_read_unlock();
 
-       return 0;
+       return ret;
 }
 
 /* check for attributes / filters for the CAN->CAN gateway */
@@ -311,6 +421,7 @@ static int can_can_parse_attr(struct nlmsghdr *nlh, struct can_can_gw *ccgw)
                nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN);
 
                canframecpy(&ccgw->modframe.and, &mb.cf);
+               ccgw->modtype.and = mb.modtype;
 
                if (mb.modtype & CGW_MOD_ID)
                        ccgw->modfunc[modidx++] = mod_and_id;
@@ -327,6 +438,7 @@ static int can_can_parse_attr(struct nlmsghdr *nlh, struct can_can_gw *ccgw)
                nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN);
 
                canframecpy(&ccgw->modframe.or, &mb.cf);
+               ccgw->modtype.or = mb.modtype;
 
                if (mb.modtype & CGW_MOD_ID)
                        ccgw->modfunc[modidx++] = mod_or_id;
@@ -343,6 +455,7 @@ static int can_can_parse_attr(struct nlmsghdr *nlh, struct can_can_gw *ccgw)
                nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN);
 
                canframecpy(&ccgw->modframe.xor, &mb.cf);
+               ccgw->modtype.xor = mb.modtype;
 
                if (mb.modtype & CGW_MOD_ID)
                        ccgw->modfunc[modidx++] = mod_xor_id;
@@ -359,6 +472,7 @@ static int can_can_parse_attr(struct nlmsghdr *nlh, struct can_can_gw *ccgw)
                nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN);
 
                canframecpy(&ccgw->modframe.set, &mb.cf);
+               ccgw->modtype.set = mb.modtype;
 
                if (mb.modtype & CGW_MOD_ID)
                        ccgw->modfunc[modidx++] = mod_set_id;
@@ -379,9 +493,6 @@ static int gw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
        struct gw_job *gwj;
        int err = 0;
 
-       printk(KERN_INFO "%s: len %d attrlen %d\n", __FUNCTION__,
-              nlmsg_len(nlh), nlmsg_attrlen(nlh, sizeof(*r)));
-
        if (nlmsg_len(nlh) < sizeof(*r))
                 return -EINVAL;
 
@@ -417,6 +528,8 @@ static int gw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
                goto put_src_dst_fail;
        }
 
+       gwj->handled_frames = 0;
+       gwj->dropped_frames = 0;
        gwj->flags = 0;
 
        if (r->can_txflags & CAN_GW_TXFLAGS_ECHO)
@@ -443,8 +556,6 @@ static int gw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
        if (err)
                goto fail;
 
-       printk(KERN_INFO "%s: added entry %p\n", __FUNCTION__, gwj);
-
        return 0;
 
 put_src_dst_fail:
@@ -465,9 +576,6 @@ static int gw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
        u32 flags = 0;
        int err = 0;
 
-       printk(KERN_INFO "%s: len %d attrlen %d\n", __FUNCTION__,
-              nlmsg_len(nlh), nlmsg_attrlen(nlh, sizeof(*r)));
-
        if (nlmsg_len(nlh) < sizeof(*r))
                 return -EINVAL;
 
@@ -508,7 +616,6 @@ static int gw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
                can_gw_unregister_filter(gwj);
                kfree(gwj);
                err = 0;
-               printk(KERN_INFO "%s: removed entry %p\n", __FUNCTION__, gwj);
                break;
        }