aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2012-05-16 14:23:23 -0400
committerAntonio Quartulli <ordex@autistici.org>2012-06-28 02:44:49 -0400
commit28afd3c0756e0f052a09710c7daa0b9e27700a02 (patch)
tree650728e68dcb932145115a05288b2a7cb74819af
parent3e34819e0eafaa6c873e9704bb478c0cdd6bb481 (diff)
batman-adv: Directly print to seq_file in vis
The vis output doesn't need to be buffered in an character buffer before it can be send to the userspace program that reads from the vis debug file. Signed-off-by: Sven Eckelmann <sven@narfation.org>
-rw-r--r--net/batman-adv/vis.c224
1 files changed, 81 insertions, 143 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 6b7a1c05e45e..3095c41a67ad 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -140,72 +140,117 @@ static void batadv_vis_data_insert_interface(const uint8_t *interface,
140 hlist_add_head(&entry->list, if_list); 140 hlist_add_head(&entry->list, if_list);
141} 141}
142 142
143static ssize_t batadv_vis_prim_sec(char *buff, const struct hlist_head *if_list) 143static void batadv_vis_data_read_prim_sec(struct seq_file *seq,
144 const struct hlist_head *if_list)
144{ 145{
145 struct if_list_entry *entry; 146 struct if_list_entry *entry;
146 struct hlist_node *pos; 147 struct hlist_node *pos;
147 size_t len = 0;
148 148
149 hlist_for_each_entry(entry, pos, if_list, list) { 149 hlist_for_each_entry(entry, pos, if_list, list) {
150 if (entry->primary) 150 if (entry->primary)
151 len += sprintf(buff + len, "PRIMARY, "); 151 seq_printf(seq, "PRIMARY, ");
152 else 152 else
153 len += sprintf(buff + len, "SEC %pM, ", entry->addr); 153 seq_printf(seq, "SEC %pM, ", entry->addr);
154 } 154 }
155}
156
157/* read an entry */
158static ssize_t batadv_vis_data_read_entry(struct seq_file *seq,
159 const struct vis_info_entry *entry,
160 const uint8_t *src, bool primary)
161{
162 if (primary && entry->quality == 0)
163 return seq_printf(seq, "TT %pM, ", entry->dest);
164 else if (batadv_compare_eth(entry->src, src))
165 return seq_printf(seq, "TQ %pM %d, ", entry->dest,
166 entry->quality);
167
168 return 0;
169}
170
171static void batadv_vis_data_insert_interfaces(struct hlist_head *list,
172 struct vis_packet *packet,
173 struct vis_info_entry *entries)
174{
175 int i;
176
177 for (i = 0; i < packet->entries; i++) {
178 if (entries[i].quality == 0)
179 continue;
155 180
156 return len; 181 if (batadv_compare_eth(entries[i].src, packet->vis_orig))
182 continue;
183
184 batadv_vis_data_insert_interface(entries[i].src, list, false);
185 }
157} 186}
158 187
159static size_t batadv_vis_cnt_prim_sec(struct hlist_head *if_list) 188static void batadv_vis_data_read_entries(struct seq_file *seq,
189 struct hlist_head *list,
190 struct vis_packet *packet,
191 struct vis_info_entry *entries)
160{ 192{
193 int i;
161 struct if_list_entry *entry; 194 struct if_list_entry *entry;
162 struct hlist_node *pos; 195 struct hlist_node *pos;
163 size_t count = 0;
164 196
165 hlist_for_each_entry(entry, pos, if_list, list) { 197 hlist_for_each_entry(entry, pos, list, list) {
166 if (entry->primary) 198 seq_printf(seq, "%pM,", entry->addr);
167 count += 9; 199
168 else 200 for (i = 0; i < packet->entries; i++)
169 count += 23; 201 batadv_vis_data_read_entry(seq, &entries[i],
170 } 202 entry->addr, entry->primary);
171 203
172 return count; 204 /* add primary/secondary records */
205 if (batadv_compare_eth(entry->addr, packet->vis_orig))
206 batadv_vis_data_read_prim_sec(seq, list);
207
208 seq_printf(seq, "\n");
209 }
173} 210}
174 211
175/* read an entry */ 212static void batadv_vis_seq_print_text_bucket(struct seq_file *seq,
176static ssize_t batadv_vis_data_read_entry(char *buff, 213 const struct hlist_head *head)
177 const struct vis_info_entry *entry,
178 const uint8_t *src, bool primary)
179{ 214{
180 /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ 215 struct hlist_node *node;
181 if (primary && entry->quality == 0) 216 struct vis_info *info;
182 return sprintf(buff, "TT %pM, ", entry->dest); 217 struct vis_packet *packet;
183 else if (batadv_compare_eth(entry->src, src)) 218 uint8_t *entries_pos;
184 return sprintf(buff, "TQ %pM %d, ", entry->dest, 219 struct vis_info_entry *entries;
185 entry->quality); 220 struct if_list_entry *entry;
221 struct hlist_node *pos, *n;
186 222
187 return 0; 223 HLIST_HEAD(vis_if_list);
224
225 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
226 packet = (struct vis_packet *)info->skb_packet->data;
227 entries_pos = (uint8_t *)packet + sizeof(*packet);
228 entries = (struct vis_info_entry *)entries_pos;
229
230 batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list,
231 true);
232 batadv_vis_data_insert_interfaces(&vis_if_list, packet,
233 entries);
234 batadv_vis_data_read_entries(seq, &vis_if_list, packet,
235 entries);
236
237 hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
238 hlist_del(&entry->list);
239 kfree(entry);
240 }
241 }
188} 242}
189 243
190int batadv_vis_seq_print_text(struct seq_file *seq, void *offset) 244int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
191{ 245{
192 struct hard_iface *primary_if; 246 struct hard_iface *primary_if;
193 struct hlist_node *node;
194 struct hlist_head *head; 247 struct hlist_head *head;
195 struct vis_info *info;
196 struct vis_packet *packet;
197 struct vis_info_entry *entries;
198 struct net_device *net_dev = (struct net_device *)seq->private; 248 struct net_device *net_dev = (struct net_device *)seq->private;
199 struct bat_priv *bat_priv = netdev_priv(net_dev); 249 struct bat_priv *bat_priv = netdev_priv(net_dev);
200 struct hashtable_t *hash = bat_priv->vis_hash; 250 struct hashtable_t *hash = bat_priv->vis_hash;
201 HLIST_HEAD(vis_if_list);
202 struct if_list_entry *entry;
203 struct hlist_node *pos, *n;
204 uint32_t i; 251 uint32_t i;
205 int j, ret = 0; 252 int ret = 0;
206 int vis_server = atomic_read(&bat_priv->vis_mode); 253 int vis_server = atomic_read(&bat_priv->vis_mode);
207 size_t buff_pos, buf_size;
208 char *buff;
209 254
210 primary_if = batadv_primary_if_get_selected(bat_priv); 255 primary_if = batadv_primary_if_get_selected(bat_priv);
211 if (!primary_if) 256 if (!primary_if)
@@ -214,120 +259,13 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
214 if (vis_server == VIS_TYPE_CLIENT_UPDATE) 259 if (vis_server == VIS_TYPE_CLIENT_UPDATE)
215 goto out; 260 goto out;
216 261
217 buf_size = 1;
218 /* Estimate length */
219 spin_lock_bh(&bat_priv->vis_hash_lock); 262 spin_lock_bh(&bat_priv->vis_hash_lock);
220 for (i = 0; i < hash->size; i++) { 263 for (i = 0; i < hash->size; i++) {
221 head = &hash->table[i]; 264 head = &hash->table[i];
222 265 batadv_vis_seq_print_text_bucket(seq, head);
223 rcu_read_lock();
224 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
225 packet = (struct vis_packet *)info->skb_packet->data;
226 entries = (struct vis_info_entry *)
227 ((char *)packet + sizeof(*packet));
228
229 batadv_vis_data_insert_interface(packet->vis_orig,
230 &vis_if_list, true);
231
232 for (j = 0; j < packet->entries; j++) {
233 if (entries[j].quality == 0)
234 continue;
235 if (batadv_compare_eth(entries[j].src,
236 packet->vis_orig))
237 continue;
238 batadv_vis_data_insert_interface(entries[j].src,
239 &vis_if_list,
240 false);
241 }
242
243 hlist_for_each_entry(entry, pos, &vis_if_list, list) {
244 buf_size += 18 + 26 * packet->entries;
245
246 /* add primary/secondary records */
247 if (batadv_compare_eth(entry->addr,
248 packet->vis_orig))
249 buf_size +=
250 batadv_vis_cnt_prim_sec(&vis_if_list);
251
252 buf_size += 1;
253 }
254
255 hlist_for_each_entry_safe(entry, pos, n, &vis_if_list,
256 list) {
257 hlist_del(&entry->list);
258 kfree(entry);
259 }
260 }
261 rcu_read_unlock();
262 } 266 }
263
264 buff = kmalloc(buf_size, GFP_ATOMIC);
265 if (!buff) {
266 spin_unlock_bh(&bat_priv->vis_hash_lock);
267 ret = -ENOMEM;
268 goto out;
269 }
270 buff[0] = '\0';
271 buff_pos = 0;
272
273 for (i = 0; i < hash->size; i++) {
274 head = &hash->table[i];
275
276 rcu_read_lock();
277 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
278 packet = (struct vis_packet *)info->skb_packet->data;
279 entries = (struct vis_info_entry *)
280 ((char *)packet + sizeof(*packet));
281
282 batadv_vis_data_insert_interface(packet->vis_orig,
283 &vis_if_list, true);
284
285 for (j = 0; j < packet->entries; j++) {
286 if (entries[j].quality == 0)
287 continue;
288 if (batadv_compare_eth(entries[j].src,
289 packet->vis_orig))
290 continue;
291 batadv_vis_data_insert_interface(entries[j].src,
292 &vis_if_list,
293 false);
294 }
295
296 hlist_for_each_entry(entry, pos, &vis_if_list, list) {
297 buff_pos += sprintf(buff + buff_pos, "%pM,",
298 entry->addr);
299
300 for (j = 0; j < packet->entries; j++)
301 buff_pos += batadv_vis_data_read_entry(
302 buff + buff_pos,
303 &entries[j],
304 entry->addr,
305 entry->primary);
306
307 /* add primary/secondary records */
308 if (batadv_compare_eth(entry->addr,
309 packet->vis_orig))
310 buff_pos +=
311 batadv_vis_prim_sec(buff + buff_pos,
312 &vis_if_list);
313
314 buff_pos += sprintf(buff + buff_pos, "\n");
315 }
316
317 hlist_for_each_entry_safe(entry, pos, n, &vis_if_list,
318 list) {
319 hlist_del(&entry->list);
320 kfree(entry);
321 }
322 }
323 rcu_read_unlock();
324 }
325
326 spin_unlock_bh(&bat_priv->vis_hash_lock); 267 spin_unlock_bh(&bat_priv->vis_hash_lock);
327 268
328 seq_printf(seq, "%s", buff);
329 kfree(buff);
330
331out: 269out:
332 if (primary_if) 270 if (primary_if)
333 batadv_hardif_free_ref(primary_if); 271 batadv_hardif_free_ref(primary_if);