aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);