]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Added funtionality to flush all GW jobs in one netlink message.
authorhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Tue, 23 Feb 2010 19:13:17 +0000 (19:13 +0000)
committerhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Tue, 23 Feb 2010 19:13:17 +0000 (19:13 +0000)
git-svn-id: svn://svn.berlios.de//socketcan/trunk@1144 030b6a49-0b11-0410-94ab-b0dab22257f2

can-utils/cangw.c
kernel/2.6/net/can/gw.c

index b7fde0d4ce3a1bf8890b3c647aff4ba18ecc4a9a..e4312dcffa6bf8d07dd68795c91cb3b095be68b2 100644 (file)
@@ -134,7 +134,7 @@ 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, "           -F (flush - delete all rules)\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");
@@ -365,6 +365,14 @@ int main(int argc, char **argv)
                req.nh.nlmsg_type  = RTM_DELROUTE;
                break;
 
+       case FLUSH:
+               req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+               req.nh.nlmsg_type  = RTM_DELROUTE;
+               /* if_index set to 0 => remove all entries */
+               req.rtcan.src_ifindex  = 0;
+               req.rtcan.dst_ifindex  = 0;
+               break;
+
        case LIST:
                req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
                req.nh.nlmsg_type  = RTM_GETROUTE;
@@ -411,7 +419,13 @@ int main(int argc, char **argv)
        /* clean netlink receive buffer */
        bzero(rxbuf, sizeof(rxbuf));
 
-       if (cmd == ADD || cmd == DEL) {
+       if (cmd != LIST) {
+
+               /*
+                * cmd == ADD || cmd == DEL || cmd == FLUSH
+                *
+                * Parse the requested netlink acknowledge return values.
+                */
 
                err = recv(s, &rxbuf, sizeof(rxbuf), 0);
                if (err < 0) {
@@ -430,7 +444,7 @@ int main(int argc, char **argv)
 
        } else {
 
-               /* cmd == LIST (for now) */
+               /* cmd == LIST */
 
                while (1) {
                        len = recv(s, &rxbuf, sizeof(rxbuf), 0);
index b6271ba82b46d0d892fe7c76e565647d58c2eda5..42f7fe7a0ec91f48e7a320af50d5e904589be213 100644 (file)
@@ -568,6 +568,22 @@ fail:
        return err;
 }
 
+static void gw_remove_all_jobs(void)
+{
+       struct gw_job *gwj = NULL;
+       struct hlist_node *n, *nx;
+
+       spin_lock(&can_gw_list_lock);
+
+       hlist_for_each_entry_safe(gwj, n, nx, &can_gw_list, list) {
+               hlist_del(&gwj->list);
+               can_gw_unregister_filter(gwj);
+               kfree(gwj);
+       }
+
+       spin_unlock(&can_gw_list_lock);
+}
+
 static int gw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
 {
        struct gw_job *gwj = NULL;
@@ -584,6 +600,12 @@ static int gw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
         if (r->can_family != AF_CAN)
                 return -EPFNOSUPPORT;
 
+       /* if_index set to 0 => remove all entries */
+       if (!r->src_ifindex && !r->dst_ifindex) {
+               gw_remove_all_jobs();
+               return 0;
+       }
+
        if (r->can_txflags & CAN_GW_TXFLAGS_ECHO)
                flags |= CAN_TX_ECHO;
 
@@ -654,22 +676,11 @@ static __init int gw_module_init(void)
 
 static __exit void gw_module_exit(void)
 {
-       struct gw_job *gwj = NULL;
-       struct hlist_node *n, *nx;
-
        rtnl_unregister_all(PF_CAN);
 
        unregister_netdevice_notifier(&notifier);
 
-       spin_lock(&can_gw_list_lock);
-
-       hlist_for_each_entry_safe(gwj, n, nx, &can_gw_list, list) {
-               hlist_del(&gwj->list);
-               can_gw_unregister_filter(gwj);
-               kfree(gwj);
-       }
-
-       spin_unlock(&can_gw_list_lock);
+       gw_remove_all_jobs();
 
        rcu_barrier(); /* Wait for completion of call_rcu()'s */