iw dev <devname> get mesh_stats [<stats>] gets statistics of the mesh network.
It will use the new %NL80211_CMD_GET_MESH_STATS command.

Signed-off-by: Ashok Nagarajan <[email protected]>
---
 mesh.c |  117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 util.c |    2 +
 2 files changed, 119 insertions(+), 0 deletions(-)

diff --git a/mesh.c b/mesh.c
index 4fdad6a..32135ae 100644
--- a/mesh.c
+++ b/mesh.c
@@ -23,6 +23,14 @@ typedef struct _any_t {
        } u;
 } _any;
 
+/* describes a mesh stats */
+struct mesh_stats_descr {
+       const char *name;
+       enum nl80211_mesh_stats mesh_stats_num;
+       int (*nla_put_fn)(struct nl_msg*, int, _any*);
+       void (*nla_print_fn)(struct nlattr *);
+};
+
 /* describes a mesh parameter */
 struct mesh_param_descr {
        const char *name;
@@ -150,6 +158,38 @@ static void _print_s32_in_dBm(struct nlattr *a)
        printf("%d dBm", (int32_t) nla_get_u32(a));
 }
 
+/* The current mesh stats */
+const static struct mesh_stats_descr _mesh_stats_descrs[] =
+{
+       {"mesh_fwded_mcast",
+       NL80211_MESH_STATS_FWDED_MCAST,
+       _my_nla_put_u32, _print_u32},
+       {"mesh_fwded_unicast",
+       NL80211_MESH_STATS_FWDED_UNICAST,
+       _my_nla_put_u32, _print_u32},
+       {"mesh_fwded_frames",
+       NL80211_MESH_STATS_FWDED_FRAMES,
+       _my_nla_put_u32, _print_u32},
+       {"mesh_dropped_frames_ttl",
+       NL80211_MESH_STATS_DROPPED_FRAMES_TTL,
+       _my_nla_put_u32, _print_u32},
+       {"mesh_dropped_frames_no_route",
+       NL80211_MESH_STATS_DROPPED_FRAMES_NO_ROUTE,
+       _my_nla_put_u32, _print_u32},
+       {"mesh_dropped_frames_congestion",
+       NL80211_MESH_STATS_DROPPED_FRAMES_CONGESTION,
+       _my_nla_put_u32, _print_u32},
+};
+
+static void print_all_mesh_stats_descr(void)
+{
+       int i;
+
+       printf("Possible mesh stats are:\n");
+
+       for (i = 0; i < ARRAY_SIZE(_mesh_stats_descrs); i++)
+               printf(" - %s\n", _mesh_stats_descrs[i].name);
+}
 
 /* The current mesh parameters */
 const static struct mesh_param_descr _mesh_param_descrs[] =
@@ -229,6 +269,19 @@ static void print_all_mesh_param_descr(void)
                printf(" - %s\n", _mesh_param_descrs[i].name);
 }
 
+static const struct mesh_stats_descr *find_mesh_stats(const char *name)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(_mesh_stats_descrs); i++) {
+               if (strcmp(_mesh_stats_descrs[i].name, name) == 0)
+                       return _mesh_stats_descrs + i;
+       }
+
+       print_all_mesh_stats_descr();
+       return NULL;
+}
+
 static const struct mesh_param_descr *find_mesh_param(const char *name)
 {
        int i;
@@ -351,6 +404,70 @@ static int print_mesh_param_handler(struct nl_msg *msg, 
void *arg)
        return NL_SKIP;
 }
 
+static int print_mesh_stats_handler(struct nl_msg *msg, void *arg)
+{
+       const struct mesh_stats_descr *mdescr = arg;
+       struct nlattr *attrs[NL80211_ATTR_MAX + 1];
+       struct nlattr *parent_attr;
+       struct nlattr *mesh_stats[NL80211_MESH_STATS_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+
+       /* locate NL80211_ATTR_MESH_STATS */
+       nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+       parent_attr = attrs[NL80211_ATTR_MESH_STATS];
+       if (!parent_attr)
+               return -EINVAL;
+
+       if (nla_parse_nested(mesh_stats, NL80211_MESH_STATS_ATTR_MAX,
+                            parent_attr, NULL))
+               return -EINVAL;
+
+       /* Print all mesh stats if no parameter is passed */
+       if (!mdescr) {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(_mesh_stats_descrs); i++) {
+                       mdescr = &_mesh_stats_descrs[i];
+                       printf("%s = ", mdescr->name);
+                       
mdescr->nla_print_fn(mesh_stats[mdescr->mesh_stats_num]);
+                       printf("\n");
+               }
+               return NL_SKIP;
+       }
+
+       /* Print the mesh stat requested */
+       mdescr->nla_print_fn(mesh_stats[mdescr->mesh_stats_num]);
+       printf("\n");
+       return NL_SKIP;
+}
+
+static int get_interface_meshstats(struct nl80211_state *state,
+                                  struct nl_cb *cb,
+                                  struct nl_msg *msg,
+                                  int argc, char **argv,
+                                  enum id_input id)
+{
+       const struct mesh_stats_descr *mdescr = NULL;
+
+       if (argc > 1)
+               return 1;
+
+       if (argc == 1) {
+               mdescr = find_mesh_stats(argv[0]);
+               if (!mdescr)
+                       return 2;
+       }
+
+       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
+                 print_mesh_stats_handler, (void *)mdescr);
+       return 0;
+}
+
+COMMAND(get, mesh_stats, "[<stats>]",
+       NL80211_CMD_GET_MESH_STATS, 0, CIB_NETDEV, get_interface_meshstats,
+       "Retrieve mesh statistics (run command without any to see available 
ones).");
+
 static int get_interface_meshparam(struct nl80211_state *state,
                                   struct nl_cb *cb,
                                   struct nl_msg *msg,
diff --git a/util.c b/util.c
index e40a2d5..6ceb9d4 100644
--- a/util.c
+++ b/util.c
@@ -236,6 +236,8 @@ static const char *commands[NL80211_CMD_MAX + 1] = {
        [NL80211_CMD_UNEXPECTED_4ADDR_FRAME] = "unexpected_4addr_frame",
        [NL80211_CMD_SET_NOACK_MAP] = "set_noack_map",
        [NL80211_CMD_CH_SWITCH_NOTIFY] = "ch_switch_notify",
+       [NL80211_CMD_GET_MESH_STATS] = "get_mesh_stats",
+
 };
 
 static char cmdbuf[100];
-- 
1.7.5.4

_______________________________________________
Devel mailing list
[email protected]
http://lists.open80211s.org/cgi-bin/mailman/listinfo/devel

Reply via email to