linux/net/mac80211/debugfs_sta.c
<<
>>
Prefs
   1/*
   2 * Copyright 2003-2005  Devicescape Software, Inc.
   3 * Copyright (c) 2006   Jiri Benc <jbenc@suse.cz>
   4 * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/debugfs.h>
  12#include <linux/ieee80211.h>
  13#include "ieee80211_i.h"
  14#include "debugfs.h"
  15#include "debugfs_sta.h"
  16#include "sta_info.h"
  17
  18/* sta attributtes */
  19
  20#define STA_READ(name, buflen, field, format_string)                    \
  21static ssize_t sta_ ##name## _read(struct file *file,                   \
  22                                   char __user *userbuf,                \
  23                                   size_t count, loff_t *ppos)          \
  24{                                                                       \
  25        int res;                                                        \
  26        struct sta_info *sta = file->private_data;                      \
  27        char buf[buflen];                                               \
  28        res = scnprintf(buf, buflen, format_string, sta->field);        \
  29        return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
  30}
  31#define STA_READ_D(name, field) STA_READ(name, 20, field, "%d\n")
  32#define STA_READ_U(name, field) STA_READ(name, 20, field, "%u\n")
  33#define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
  34#define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
  35
  36#define STA_OPS(name)                                                   \
  37static const struct file_operations sta_ ##name## _ops = {              \
  38        .read = sta_##name##_read,                                      \
  39        .open = mac80211_open_file_generic,                             \
  40}
  41
  42#define STA_OPS_WR(name)                                                \
  43static const struct file_operations sta_ ##name## _ops = {              \
  44        .read = sta_##name##_read,                                      \
  45        .write = sta_##name##_write,                                    \
  46        .open = mac80211_open_file_generic,                             \
  47}
  48
  49#define STA_FILE(name, field, format)                                   \
  50                STA_READ_##format(name, field)                          \
  51                STA_OPS(name)
  52
  53STA_FILE(aid, aid, D);
  54STA_FILE(dev, sdata->dev->name, S);
  55STA_FILE(rx_packets, rx_packets, LU);
  56STA_FILE(tx_packets, tx_packets, LU);
  57STA_FILE(rx_bytes, rx_bytes, LU);
  58STA_FILE(tx_bytes, tx_bytes, LU);
  59STA_FILE(rx_duplicates, num_duplicates, LU);
  60STA_FILE(rx_fragments, rx_fragments, LU);
  61STA_FILE(rx_dropped, rx_dropped, LU);
  62STA_FILE(tx_fragments, tx_fragments, LU);
  63STA_FILE(tx_filtered, tx_filtered_count, LU);
  64STA_FILE(tx_retry_failed, tx_retry_failed, LU);
  65STA_FILE(tx_retry_count, tx_retry_count, LU);
  66STA_FILE(last_rssi, last_rssi, D);
  67STA_FILE(last_signal, last_signal, D);
  68STA_FILE(last_noise, last_noise, D);
  69STA_FILE(channel_use, channel_use, D);
  70STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
  71
  72static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
  73                              size_t count, loff_t *ppos)
  74{
  75        char buf[100];
  76        struct sta_info *sta = file->private_data;
  77        int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
  78                sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
  79                sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
  80                sta->flags & WLAN_STA_PS ? "PS\n" : "",
  81                sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
  82                sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
  83                sta->flags & WLAN_STA_WME ? "WME\n" : "",
  84                sta->flags & WLAN_STA_WDS ? "WDS\n" : "");
  85        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
  86}
  87STA_OPS(flags);
  88
  89static ssize_t sta_num_ps_buf_frames_read(struct file *file,
  90                                          char __user *userbuf,
  91                                          size_t count, loff_t *ppos)
  92{
  93        char buf[20];
  94        struct sta_info *sta = file->private_data;
  95        int res = scnprintf(buf, sizeof(buf), "%u\n",
  96                            skb_queue_len(&sta->ps_tx_buf));
  97        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
  98}
  99STA_OPS(num_ps_buf_frames);
 100
 101static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
 102                                    size_t count, loff_t *ppos)
 103{
 104        char buf[20];
 105        struct sta_info *sta = file->private_data;
 106        int res = scnprintf(buf, sizeof(buf), "%d\n",
 107                            jiffies_to_msecs(jiffies - sta->last_rx));
 108        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
 109}
 110STA_OPS(inactive_ms);
 111
 112static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
 113                                      size_t count, loff_t *ppos)
 114{
 115        char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
 116        int i;
 117        struct sta_info *sta = file->private_data;
 118        for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
 119                p += scnprintf(p, sizeof(buf)+buf-p, "%x ",
 120                               le16_to_cpu(sta->last_seq_ctrl[i]));
 121        p += scnprintf(p, sizeof(buf)+buf-p, "\n");
 122        return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
 123}
 124STA_OPS(last_seq_ctrl);
 125
 126#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 127static ssize_t sta_wme_rx_queue_read(struct file *file, char __user *userbuf,
 128                                     size_t count, loff_t *ppos)
 129{
 130        char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
 131        int i;
 132        struct sta_info *sta = file->private_data;
 133        for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
 134                p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
 135                               sta->wme_rx_queue[i]);
 136        p += scnprintf(p, sizeof(buf)+buf-p, "\n");
 137        return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
 138}
 139STA_OPS(wme_rx_queue);
 140
 141static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf,
 142                                     size_t count, loff_t *ppos)
 143{
 144        char buf[15*NUM_TX_DATA_QUEUES], *p = buf;
 145        int i;
 146        struct sta_info *sta = file->private_data;
 147        for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
 148                p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
 149                               sta->wme_tx_queue[i]);
 150        p += scnprintf(p, sizeof(buf)+buf-p, "\n");
 151        return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
 152}
 153STA_OPS(wme_tx_queue);
 154#endif
 155
 156static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
 157                                        size_t count, loff_t *ppos)
 158{
 159        char buf[768], *p = buf;
 160        int i;
 161        struct sta_info *sta = file->private_data;
 162        p += scnprintf(p, sizeof(buf)+buf-p, "Agg state for STA is:\n");
 163        p += scnprintf(p, sizeof(buf)+buf-p, " STA next dialog_token is %d \n "
 164                        "TIDs info is: \n TID :",
 165                        (sta->ampdu_mlme.dialog_token_allocator + 1));
 166        for (i = 0; i < STA_TID_NUM; i++)
 167                p += scnprintf(p, sizeof(buf)+buf-p, "%5d", i);
 168
 169        p += scnprintf(p, sizeof(buf)+buf-p, "\n RX  :");
 170        for (i = 0; i < STA_TID_NUM; i++)
 171                p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
 172                        sta->ampdu_mlme.tid_state_rx[i]);
 173
 174        p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
 175        for (i = 0; i < STA_TID_NUM; i++)
 176                p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
 177                        sta->ampdu_mlme.tid_state_rx[i]?
 178                        sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
 179
 180        p += scnprintf(p, sizeof(buf)+buf-p, "\n TX  :");
 181        for (i = 0; i < STA_TID_NUM; i++)
 182                p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
 183                        sta->ampdu_mlme.tid_state_tx[i]);
 184
 185        p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
 186        for (i = 0; i < STA_TID_NUM; i++)
 187                p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
 188                        sta->ampdu_mlme.tid_state_tx[i]?
 189                        sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
 190
 191        p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :");
 192        for (i = 0; i < STA_TID_NUM; i++)
 193                p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
 194                        sta->ampdu_mlme.tid_state_tx[i]?
 195                        sta->ampdu_mlme.tid_tx[i]->ssn : 0);
 196
 197        p += scnprintf(p, sizeof(buf)+buf-p, "\n");
 198
 199        return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
 200}
 201
 202static ssize_t sta_agg_status_write(struct file *file,
 203                const char __user *user_buf, size_t count, loff_t *ppos)
 204{
 205        struct sta_info *sta = file->private_data;
 206        struct net_device *dev = sta->sdata->dev;
 207        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 208        struct ieee80211_hw *hw = &local->hw;
 209        u8 *da = sta->addr;
 210        static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0,
 211                                        0, 0, 0, 0, 0, 0, 0, 0};
 212        static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1,
 213                                        1, 1, 1, 1, 1, 1, 1, 1};
 214        char *endp;
 215        char buf[32];
 216        int buf_size, rs;
 217        unsigned int tid_num;
 218        char state[4];
 219
 220        memset(buf, 0x00, sizeof(buf));
 221        buf_size = min(count, (sizeof(buf)-1));
 222        if (copy_from_user(buf, user_buf, buf_size))
 223                return -EFAULT;
 224
 225        tid_num = simple_strtoul(buf, &endp, 0);
 226        if (endp == buf)
 227                return -EINVAL;
 228
 229        if ((tid_num >= 100) && (tid_num <= 115)) {
 230                /* toggle Rx aggregation command */
 231                tid_num = tid_num - 100;
 232                if (tid_static_rx[tid_num] == 1) {
 233                        strcpy(state, "off ");
 234                        ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0,
 235                                        WLAN_REASON_QSTA_REQUIRE_SETUP);
 236                        sta->ampdu_mlme.tid_state_rx[tid_num] |=
 237                                        HT_AGG_STATE_DEBUGFS_CTL;
 238                        tid_static_rx[tid_num] = 0;
 239                } else {
 240                        strcpy(state, "on ");
 241                        sta->ampdu_mlme.tid_state_rx[tid_num] &=
 242                                        ~HT_AGG_STATE_DEBUGFS_CTL;
 243                        tid_static_rx[tid_num] = 1;
 244                }
 245                printk(KERN_DEBUG "debugfs - try switching tid %u %s\n",
 246                                tid_num, state);
 247        } else if ((tid_num >= 0) && (tid_num <= 15)) {
 248                /* toggle Tx aggregation command */
 249                if (tid_static_tx[tid_num] == 0) {
 250                        strcpy(state, "on ");
 251                        rs =  ieee80211_start_tx_ba_session(hw, da, tid_num);
 252                        if (rs == 0)
 253                                tid_static_tx[tid_num] = 1;
 254                } else {
 255                        strcpy(state, "off");
 256                        rs =  ieee80211_stop_tx_ba_session(hw, da, tid_num, 1);
 257                        if (rs == 0)
 258                                tid_static_tx[tid_num] = 0;
 259                }
 260                printk(KERN_DEBUG "debugfs - switching tid %u %s, return=%d\n",
 261                                tid_num, state, rs);
 262        }
 263
 264        return count;
 265}
 266STA_OPS_WR(agg_status);
 267
 268#define DEBUGFS_ADD(name) \
 269        sta->debugfs.name = debugfs_create_file(#name, 0400, \
 270                sta->debugfs.dir, sta, &sta_ ##name## _ops);
 271
 272#define DEBUGFS_DEL(name) \
 273        debugfs_remove(sta->debugfs.name);\
 274        sta->debugfs.name = NULL;
 275
 276
 277void ieee80211_sta_debugfs_add(struct sta_info *sta)
 278{
 279        struct dentry *stations_dir = sta->local->debugfs.stations;
 280        DECLARE_MAC_BUF(mbuf);
 281        u8 *mac;
 282
 283        if (!stations_dir)
 284                return;
 285
 286        mac = print_mac(mbuf, sta->addr);
 287
 288        sta->debugfs.dir = debugfs_create_dir(mac, stations_dir);
 289        if (!sta->debugfs.dir)
 290                return;
 291
 292        DEBUGFS_ADD(flags);
 293        DEBUGFS_ADD(num_ps_buf_frames);
 294        DEBUGFS_ADD(inactive_ms);
 295        DEBUGFS_ADD(last_seq_ctrl);
 296#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 297        DEBUGFS_ADD(wme_rx_queue);
 298        DEBUGFS_ADD(wme_tx_queue);
 299#endif
 300        DEBUGFS_ADD(agg_status);
 301}
 302
 303void ieee80211_sta_debugfs_remove(struct sta_info *sta)
 304{
 305        DEBUGFS_DEL(flags);
 306        DEBUGFS_DEL(num_ps_buf_frames);
 307        DEBUGFS_DEL(inactive_ms);
 308        DEBUGFS_DEL(last_seq_ctrl);
 309#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 310        DEBUGFS_DEL(wme_rx_queue);
 311        DEBUGFS_DEL(wme_tx_queue);
 312#endif
 313        DEBUGFS_DEL(agg_status);
 314
 315        debugfs_remove(sta->debugfs.dir);
 316        sta->debugfs.dir = NULL;
 317}
 318
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.