1 // SPDX-License-Identifier: GPL-2.0-only
5 * (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
6 * Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
9 #include <net/6lowpan.h>
11 #include "6lowpan_i.h"
13 #define LOWPAN_DEBUGFS_CTX_PFX_NUM_ARGS 8
15 static struct dentry
*lowpan_debugfs
;
17 static int lowpan_ctx_flag_active_set(void *data
, u64 val
)
19 struct lowpan_iphc_ctx
*ctx
= data
;
21 if (val
!= 0 && val
!= 1)
25 set_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE
, &ctx
->flags
);
27 clear_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE
, &ctx
->flags
);
32 static int lowpan_ctx_flag_active_get(void *data
, u64
*val
)
34 *val
= lowpan_iphc_ctx_is_active(data
);
38 DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_flag_active_fops
,
39 lowpan_ctx_flag_active_get
,
40 lowpan_ctx_flag_active_set
, "%llu\n");
42 static int lowpan_ctx_flag_c_set(void *data
, u64 val
)
44 struct lowpan_iphc_ctx
*ctx
= data
;
46 if (val
!= 0 && val
!= 1)
50 set_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION
, &ctx
->flags
);
52 clear_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION
, &ctx
->flags
);
57 static int lowpan_ctx_flag_c_get(void *data
, u64
*val
)
59 *val
= lowpan_iphc_ctx_is_compression(data
);
63 DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_flag_c_fops
, lowpan_ctx_flag_c_get
,
64 lowpan_ctx_flag_c_set
, "%llu\n");
66 static int lowpan_ctx_plen_set(void *data
, u64 val
)
68 struct lowpan_iphc_ctx
*ctx
= data
;
69 struct lowpan_iphc_ctx_table
*t
=
70 container_of(ctx
, struct lowpan_iphc_ctx_table
, table
[ctx
->id
]);
75 spin_lock_bh(&t
->lock
);
77 spin_unlock_bh(&t
->lock
);
82 static int lowpan_ctx_plen_get(void *data
, u64
*val
)
84 struct lowpan_iphc_ctx
*ctx
= data
;
85 struct lowpan_iphc_ctx_table
*t
=
86 container_of(ctx
, struct lowpan_iphc_ctx_table
, table
[ctx
->id
]);
88 spin_lock_bh(&t
->lock
);
90 spin_unlock_bh(&t
->lock
);
94 DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_plen_fops
, lowpan_ctx_plen_get
,
95 lowpan_ctx_plen_set
, "%llu\n");
97 static int lowpan_ctx_pfx_show(struct seq_file
*file
, void *offset
)
99 struct lowpan_iphc_ctx
*ctx
= file
->private;
100 struct lowpan_iphc_ctx_table
*t
=
101 container_of(ctx
, struct lowpan_iphc_ctx_table
, table
[ctx
->id
]);
103 spin_lock_bh(&t
->lock
);
104 seq_printf(file
, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
105 be16_to_cpu(ctx
->pfx
.s6_addr16
[0]),
106 be16_to_cpu(ctx
->pfx
.s6_addr16
[1]),
107 be16_to_cpu(ctx
->pfx
.s6_addr16
[2]),
108 be16_to_cpu(ctx
->pfx
.s6_addr16
[3]),
109 be16_to_cpu(ctx
->pfx
.s6_addr16
[4]),
110 be16_to_cpu(ctx
->pfx
.s6_addr16
[5]),
111 be16_to_cpu(ctx
->pfx
.s6_addr16
[6]),
112 be16_to_cpu(ctx
->pfx
.s6_addr16
[7]));
113 spin_unlock_bh(&t
->lock
);
118 static int lowpan_ctx_pfx_open(struct inode
*inode
, struct file
*file
)
120 return single_open(file
, lowpan_ctx_pfx_show
, inode
->i_private
);
123 static ssize_t
lowpan_ctx_pfx_write(struct file
*fp
,
124 const char __user
*user_buf
, size_t count
,
128 struct seq_file
*file
= fp
->private_data
;
129 struct lowpan_iphc_ctx
*ctx
= file
->private;
130 struct lowpan_iphc_ctx_table
*t
=
131 container_of(ctx
, struct lowpan_iphc_ctx_table
, table
[ctx
->id
]);
132 int status
= count
, n
, i
;
133 unsigned int addr
[8];
135 if (copy_from_user(&buf
, user_buf
, min_t(size_t, sizeof(buf
) - 1,
141 n
= sscanf(buf
, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
142 &addr
[0], &addr
[1], &addr
[2], &addr
[3], &addr
[4],
143 &addr
[5], &addr
[6], &addr
[7]);
144 if (n
!= LOWPAN_DEBUGFS_CTX_PFX_NUM_ARGS
) {
149 spin_lock_bh(&t
->lock
);
150 for (i
= 0; i
< 8; i
++)
151 ctx
->pfx
.s6_addr16
[i
] = cpu_to_be16(addr
[i
] & 0xffff);
152 spin_unlock_bh(&t
->lock
);
158 static const struct file_operations lowpan_ctx_pfx_fops
= {
159 .open
= lowpan_ctx_pfx_open
,
161 .write
= lowpan_ctx_pfx_write
,
163 .release
= single_release
,
166 static void lowpan_dev_debugfs_ctx_init(struct net_device
*dev
,
167 struct dentry
*ctx
, u8 id
)
169 struct lowpan_dev
*ldev
= lowpan_dev(dev
);
173 if (WARN_ON_ONCE(id
>= LOWPAN_IPHC_CTX_TABLE_SIZE
))
176 sprintf(buf
, "%d", id
);
178 root
= debugfs_create_dir(buf
, ctx
);
180 debugfs_create_file("active", 0644, root
, &ldev
->ctx
.table
[id
],
181 &lowpan_ctx_flag_active_fops
);
183 debugfs_create_file("compression", 0644, root
, &ldev
->ctx
.table
[id
],
184 &lowpan_ctx_flag_c_fops
);
186 debugfs_create_file("prefix", 0644, root
, &ldev
->ctx
.table
[id
],
187 &lowpan_ctx_pfx_fops
);
189 debugfs_create_file("prefix_len", 0644, root
, &ldev
->ctx
.table
[id
],
190 &lowpan_ctx_plen_fops
);
193 static int lowpan_context_show(struct seq_file
*file
, void *offset
)
195 struct lowpan_iphc_ctx_table
*t
= file
->private;
198 seq_printf(file
, "%3s|%-43s|%c\n", "cid", "prefix", 'C');
199 seq_puts(file
, "-------------------------------------------------\n");
201 spin_lock_bh(&t
->lock
);
202 for (i
= 0; i
< LOWPAN_IPHC_CTX_TABLE_SIZE
; i
++) {
203 if (!lowpan_iphc_ctx_is_active(&t
->table
[i
]))
206 seq_printf(file
, "%3d|%39pI6c/%-3d|%d\n", t
->table
[i
].id
,
207 &t
->table
[i
].pfx
, t
->table
[i
].plen
,
208 lowpan_iphc_ctx_is_compression(&t
->table
[i
]));
210 spin_unlock_bh(&t
->lock
);
214 DEFINE_SHOW_ATTRIBUTE(lowpan_context
);
216 static int lowpan_short_addr_get(void *data
, u64
*val
)
218 struct wpan_dev
*wdev
= data
;
221 *val
= le16_to_cpu(wdev
->short_addr
);
227 DEFINE_DEBUGFS_ATTRIBUTE(lowpan_short_addr_fops
, lowpan_short_addr_get
, NULL
,
230 static void lowpan_dev_debugfs_802154_init(const struct net_device
*dev
,
231 struct lowpan_dev
*ldev
)
235 if (!lowpan_is_ll(dev
, LOWPAN_LLTYPE_IEEE802154
))
238 root
= debugfs_create_dir("ieee802154", ldev
->iface_debugfs
);
240 debugfs_create_file("short_addr", 0444, root
,
241 lowpan_802154_dev(dev
)->wdev
->ieee802154_ptr
,
242 &lowpan_short_addr_fops
);
245 void lowpan_dev_debugfs_init(struct net_device
*dev
)
247 struct lowpan_dev
*ldev
= lowpan_dev(dev
);
248 struct dentry
*contexts
;
251 /* creating the root */
252 ldev
->iface_debugfs
= debugfs_create_dir(dev
->name
, lowpan_debugfs
);
254 contexts
= debugfs_create_dir("contexts", ldev
->iface_debugfs
);
256 debugfs_create_file("show", 0644, contexts
, &lowpan_dev(dev
)->ctx
,
257 &lowpan_context_fops
);
259 for (i
= 0; i
< LOWPAN_IPHC_CTX_TABLE_SIZE
; i
++)
260 lowpan_dev_debugfs_ctx_init(dev
, contexts
, i
);
262 lowpan_dev_debugfs_802154_init(dev
, ldev
);
265 void lowpan_dev_debugfs_exit(struct net_device
*dev
)
267 debugfs_remove_recursive(lowpan_dev(dev
)->iface_debugfs
);
270 void __init
lowpan_debugfs_init(void)
272 lowpan_debugfs
= debugfs_create_dir("6lowpan", NULL
);
275 void lowpan_debugfs_exit(void)
277 debugfs_remove_recursive(lowpan_debugfs
);