Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  * Authors:
0005  * (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
0006  * Copyright (c)  2015 Nordic Semiconductor. All Rights Reserved.
0007  */
0008 
0009 #include <net/6lowpan.h>
0010 
0011 #include "6lowpan_i.h"
0012 
0013 #define LOWPAN_DEBUGFS_CTX_PFX_NUM_ARGS 8
0014 
0015 static struct dentry *lowpan_debugfs;
0016 
0017 static int lowpan_ctx_flag_active_set(void *data, u64 val)
0018 {
0019     struct lowpan_iphc_ctx *ctx = data;
0020 
0021     if (val != 0 && val != 1)
0022         return -EINVAL;
0023 
0024     if (val)
0025         set_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, &ctx->flags);
0026     else
0027         clear_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, &ctx->flags);
0028 
0029     return 0;
0030 }
0031 
0032 static int lowpan_ctx_flag_active_get(void *data, u64 *val)
0033 {
0034     *val = lowpan_iphc_ctx_is_active(data);
0035     return 0;
0036 }
0037 
0038 DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_flag_active_fops,
0039              lowpan_ctx_flag_active_get,
0040              lowpan_ctx_flag_active_set, "%llu\n");
0041 
0042 static int lowpan_ctx_flag_c_set(void *data, u64 val)
0043 {
0044     struct lowpan_iphc_ctx *ctx = data;
0045 
0046     if (val != 0 && val != 1)
0047         return -EINVAL;
0048 
0049     if (val)
0050         set_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION, &ctx->flags);
0051     else
0052         clear_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION, &ctx->flags);
0053 
0054     return 0;
0055 }
0056 
0057 static int lowpan_ctx_flag_c_get(void *data, u64 *val)
0058 {
0059     *val = lowpan_iphc_ctx_is_compression(data);
0060     return 0;
0061 }
0062 
0063 DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_flag_c_fops, lowpan_ctx_flag_c_get,
0064              lowpan_ctx_flag_c_set, "%llu\n");
0065 
0066 static int lowpan_ctx_plen_set(void *data, u64 val)
0067 {
0068     struct lowpan_iphc_ctx *ctx = data;
0069     struct lowpan_iphc_ctx_table *t =
0070         container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
0071 
0072     if (val > 128)
0073         return -EINVAL;
0074 
0075     spin_lock_bh(&t->lock);
0076     ctx->plen = val;
0077     spin_unlock_bh(&t->lock);
0078 
0079     return 0;
0080 }
0081 
0082 static int lowpan_ctx_plen_get(void *data, u64 *val)
0083 {
0084     struct lowpan_iphc_ctx *ctx = data;
0085     struct lowpan_iphc_ctx_table *t =
0086         container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
0087 
0088     spin_lock_bh(&t->lock);
0089     *val = ctx->plen;
0090     spin_unlock_bh(&t->lock);
0091     return 0;
0092 }
0093 
0094 DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_plen_fops, lowpan_ctx_plen_get,
0095              lowpan_ctx_plen_set, "%llu\n");
0096 
0097 static int lowpan_ctx_pfx_show(struct seq_file *file, void *offset)
0098 {
0099     struct lowpan_iphc_ctx *ctx = file->private;
0100     struct lowpan_iphc_ctx_table *t =
0101         container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
0102 
0103     spin_lock_bh(&t->lock);
0104     seq_printf(file, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
0105            be16_to_cpu(ctx->pfx.s6_addr16[0]),
0106            be16_to_cpu(ctx->pfx.s6_addr16[1]),
0107            be16_to_cpu(ctx->pfx.s6_addr16[2]),
0108            be16_to_cpu(ctx->pfx.s6_addr16[3]),
0109            be16_to_cpu(ctx->pfx.s6_addr16[4]),
0110            be16_to_cpu(ctx->pfx.s6_addr16[5]),
0111            be16_to_cpu(ctx->pfx.s6_addr16[6]),
0112            be16_to_cpu(ctx->pfx.s6_addr16[7]));
0113     spin_unlock_bh(&t->lock);
0114 
0115     return 0;
0116 }
0117 
0118 static int lowpan_ctx_pfx_open(struct inode *inode, struct file *file)
0119 {
0120     return single_open(file, lowpan_ctx_pfx_show, inode->i_private);
0121 }
0122 
0123 static ssize_t lowpan_ctx_pfx_write(struct file *fp,
0124                     const char __user *user_buf, size_t count,
0125                     loff_t *ppos)
0126 {
0127     char buf[128] = {};
0128     struct seq_file *file = fp->private_data;
0129     struct lowpan_iphc_ctx *ctx = file->private;
0130     struct lowpan_iphc_ctx_table *t =
0131         container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
0132     int status = count, n, i;
0133     unsigned int addr[8];
0134 
0135     if (copy_from_user(&buf, user_buf, min_t(size_t, sizeof(buf) - 1,
0136                          count))) {
0137         status = -EFAULT;
0138         goto out;
0139     }
0140 
0141     n = sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
0142            &addr[0], &addr[1], &addr[2], &addr[3], &addr[4],
0143            &addr[5], &addr[6], &addr[7]);
0144     if (n != LOWPAN_DEBUGFS_CTX_PFX_NUM_ARGS) {
0145         status = -EINVAL;
0146         goto out;
0147     }
0148 
0149     spin_lock_bh(&t->lock);
0150     for (i = 0; i < 8; i++)
0151         ctx->pfx.s6_addr16[i] = cpu_to_be16(addr[i] & 0xffff);
0152     spin_unlock_bh(&t->lock);
0153 
0154 out:
0155     return status;
0156 }
0157 
0158 static const struct file_operations lowpan_ctx_pfx_fops = {
0159     .open       = lowpan_ctx_pfx_open,
0160     .read       = seq_read,
0161     .write      = lowpan_ctx_pfx_write,
0162     .llseek     = seq_lseek,
0163     .release    = single_release,
0164 };
0165 
0166 static void lowpan_dev_debugfs_ctx_init(struct net_device *dev,
0167                     struct dentry *ctx, u8 id)
0168 {
0169     struct lowpan_dev *ldev = lowpan_dev(dev);
0170     struct dentry *root;
0171     char buf[32];
0172 
0173     if (WARN_ON_ONCE(id >= LOWPAN_IPHC_CTX_TABLE_SIZE))
0174         return;
0175 
0176     sprintf(buf, "%d", id);
0177 
0178     root = debugfs_create_dir(buf, ctx);
0179 
0180     debugfs_create_file("active", 0644, root, &ldev->ctx.table[id],
0181                 &lowpan_ctx_flag_active_fops);
0182 
0183     debugfs_create_file("compression", 0644, root, &ldev->ctx.table[id],
0184                 &lowpan_ctx_flag_c_fops);
0185 
0186     debugfs_create_file("prefix", 0644, root, &ldev->ctx.table[id],
0187                 &lowpan_ctx_pfx_fops);
0188 
0189     debugfs_create_file("prefix_len", 0644, root, &ldev->ctx.table[id],
0190                 &lowpan_ctx_plen_fops);
0191 }
0192 
0193 static int lowpan_context_show(struct seq_file *file, void *offset)
0194 {
0195     struct lowpan_iphc_ctx_table *t = file->private;
0196     int i;
0197 
0198     seq_printf(file, "%3s|%-43s|%c\n", "cid", "prefix", 'C');
0199     seq_puts(file, "-------------------------------------------------\n");
0200 
0201     spin_lock_bh(&t->lock);
0202     for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
0203         if (!lowpan_iphc_ctx_is_active(&t->table[i]))
0204             continue;
0205 
0206         seq_printf(file, "%3d|%39pI6c/%-3d|%d\n", t->table[i].id,
0207                &t->table[i].pfx, t->table[i].plen,
0208                lowpan_iphc_ctx_is_compression(&t->table[i]));
0209     }
0210     spin_unlock_bh(&t->lock);
0211 
0212     return 0;
0213 }
0214 DEFINE_SHOW_ATTRIBUTE(lowpan_context);
0215 
0216 static int lowpan_short_addr_get(void *data, u64 *val)
0217 {
0218     struct wpan_dev *wdev = data;
0219 
0220     rtnl_lock();
0221     *val = le16_to_cpu(wdev->short_addr);
0222     rtnl_unlock();
0223 
0224     return 0;
0225 }
0226 
0227 DEFINE_DEBUGFS_ATTRIBUTE(lowpan_short_addr_fops, lowpan_short_addr_get, NULL,
0228              "0x%04llx\n");
0229 
0230 static void lowpan_dev_debugfs_802154_init(const struct net_device *dev,
0231                       struct lowpan_dev *ldev)
0232 {
0233     struct dentry *root;
0234 
0235     if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
0236         return;
0237 
0238     root = debugfs_create_dir("ieee802154", ldev->iface_debugfs);
0239 
0240     debugfs_create_file("short_addr", 0444, root,
0241                 lowpan_802154_dev(dev)->wdev->ieee802154_ptr,
0242                 &lowpan_short_addr_fops);
0243 }
0244 
0245 void lowpan_dev_debugfs_init(struct net_device *dev)
0246 {
0247     struct lowpan_dev *ldev = lowpan_dev(dev);
0248     struct dentry *contexts;
0249     int i;
0250 
0251     /* creating the root */
0252     ldev->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs);
0253 
0254     contexts = debugfs_create_dir("contexts", ldev->iface_debugfs);
0255 
0256     debugfs_create_file("show", 0644, contexts, &lowpan_dev(dev)->ctx,
0257                 &lowpan_context_fops);
0258 
0259     for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++)
0260         lowpan_dev_debugfs_ctx_init(dev, contexts, i);
0261 
0262     lowpan_dev_debugfs_802154_init(dev, ldev);
0263 }
0264 
0265 void lowpan_dev_debugfs_exit(struct net_device *dev)
0266 {
0267     debugfs_remove_recursive(lowpan_dev(dev)->iface_debugfs);
0268 }
0269 
0270 void __init lowpan_debugfs_init(void)
0271 {
0272     lowpan_debugfs = debugfs_create_dir("6lowpan", NULL);
0273 }
0274 
0275 void lowpan_debugfs_exit(void)
0276 {
0277     debugfs_remove_recursive(lowpan_debugfs);
0278 }