]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/batman-adv/originator.c
batman-adv: remove useless blank lines before and after brackets
[karo-tx-linux.git] / net / batman-adv / originator.c
1 /* Copyright (C) 2009-2012 B.A.T.M.A.N. contributors:
2  *
3  * Marek Lindner, Simon Wunderlich
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public
7  * License as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA
18  */
19
20 #include "main.h"
21 #include "distributed-arp-table.h"
22 #include "originator.h"
23 #include "hash.h"
24 #include "translation-table.h"
25 #include "routing.h"
26 #include "gateway_client.h"
27 #include "hard-interface.h"
28 #include "unicast.h"
29 #include "soft-interface.h"
30 #include "bridge_loop_avoidance.h"
31
32 /* hash class keys */
33 static struct lock_class_key batadv_orig_hash_lock_class_key;
34
35 static void batadv_purge_orig(struct work_struct *work);
36
37 static void batadv_start_purge_timer(struct batadv_priv *bat_priv)
38 {
39         INIT_DELAYED_WORK(&bat_priv->orig_work, batadv_purge_orig);
40         queue_delayed_work(batadv_event_workqueue,
41                            &bat_priv->orig_work, msecs_to_jiffies(1000));
42 }
43
44 /* returns 1 if they are the same originator */
45 static int batadv_compare_orig(const struct hlist_node *node, const void *data2)
46 {
47         const void *data1 = container_of(node, struct batadv_orig_node,
48                                          hash_entry);
49
50         return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
51 }
52
53 int batadv_originator_init(struct batadv_priv *bat_priv)
54 {
55         if (bat_priv->orig_hash)
56                 return 0;
57
58         bat_priv->orig_hash = batadv_hash_new(1024);
59
60         if (!bat_priv->orig_hash)
61                 goto err;
62
63         batadv_hash_set_lock_class(bat_priv->orig_hash,
64                                    &batadv_orig_hash_lock_class_key);
65
66         batadv_start_purge_timer(bat_priv);
67         return 0;
68
69 err:
70         return -ENOMEM;
71 }
72
73 void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node)
74 {
75         if (atomic_dec_and_test(&neigh_node->refcount))
76                 kfree_rcu(neigh_node, rcu);
77 }
78
79 /* increases the refcounter of a found router */
80 struct batadv_neigh_node *
81 batadv_orig_node_get_router(struct batadv_orig_node *orig_node)
82 {
83         struct batadv_neigh_node *router;
84
85         rcu_read_lock();
86         router = rcu_dereference(orig_node->router);
87
88         if (router && !atomic_inc_not_zero(&router->refcount))
89                 router = NULL;
90
91         rcu_read_unlock();
92         return router;
93 }
94
95 struct batadv_neigh_node *
96 batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
97                       const uint8_t *neigh_addr, uint32_t seqno)
98 {
99         struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
100         struct batadv_neigh_node *neigh_node;
101
102         neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
103         if (!neigh_node)
104                 goto out;
105
106         INIT_HLIST_NODE(&neigh_node->list);
107
108         memcpy(neigh_node->addr, neigh_addr, ETH_ALEN);
109         spin_lock_init(&neigh_node->lq_update_lock);
110
111         /* extra reference for return */
112         atomic_set(&neigh_node->refcount, 2);
113
114         batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
115                    "Creating new neighbor %pM, initial seqno %d\n",
116                    neigh_addr, seqno);
117
118 out:
119         return neigh_node;
120 }
121
122 static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
123 {
124         struct hlist_node *node, *node_tmp;
125         struct batadv_neigh_node *neigh_node, *tmp_neigh_node;
126         struct batadv_orig_node *orig_node;
127
128         orig_node = container_of(rcu, struct batadv_orig_node, rcu);
129
130         spin_lock_bh(&orig_node->neigh_list_lock);
131
132         /* for all bonding members ... */
133         list_for_each_entry_safe(neigh_node, tmp_neigh_node,
134                                  &orig_node->bond_list, bonding_list) {
135                 list_del_rcu(&neigh_node->bonding_list);
136                 batadv_neigh_node_free_ref(neigh_node);
137         }
138
139         /* for all neighbors towards this originator ... */
140         hlist_for_each_entry_safe(neigh_node, node, node_tmp,
141                                   &orig_node->neigh_list, list) {
142                 hlist_del_rcu(&neigh_node->list);
143                 batadv_neigh_node_free_ref(neigh_node);
144         }
145
146         spin_unlock_bh(&orig_node->neigh_list_lock);
147
148         batadv_frag_list_free(&orig_node->frag_list);
149         batadv_tt_global_del_orig(orig_node->bat_priv, orig_node,
150                                   "originator timed out");
151
152         kfree(orig_node->tt_buff);
153         kfree(orig_node->bcast_own);
154         kfree(orig_node->bcast_own_sum);
155         kfree(orig_node);
156 }
157
158 void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node)
159 {
160         if (atomic_dec_and_test(&orig_node->refcount))
161                 call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu);
162 }
163
164 void batadv_originator_free(struct batadv_priv *bat_priv)
165 {
166         struct batadv_hashtable *hash = bat_priv->orig_hash;
167         struct hlist_node *node, *node_tmp;
168         struct hlist_head *head;
169         spinlock_t *list_lock; /* spinlock to protect write access */
170         struct batadv_orig_node *orig_node;
171         uint32_t i;
172
173         if (!hash)
174                 return;
175
176         cancel_delayed_work_sync(&bat_priv->orig_work);
177
178         bat_priv->orig_hash = NULL;
179
180         for (i = 0; i < hash->size; i++) {
181                 head = &hash->table[i];
182                 list_lock = &hash->list_locks[i];
183
184                 spin_lock_bh(list_lock);
185                 hlist_for_each_entry_safe(orig_node, node, node_tmp,
186                                           head, hash_entry) {
187                         hlist_del_rcu(node);
188                         batadv_orig_node_free_ref(orig_node);
189                 }
190                 spin_unlock_bh(list_lock);
191         }
192
193         batadv_hash_destroy(hash);
194 }
195
196 /* this function finds or creates an originator entry for the given
197  * address if it does not exits
198  */
199 struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
200                                               const uint8_t *addr)
201 {
202         struct batadv_orig_node *orig_node;
203         int size;
204         int hash_added;
205         unsigned long reset_time;
206
207         orig_node = batadv_orig_hash_find(bat_priv, addr);
208         if (orig_node)
209                 return orig_node;
210
211         batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
212                    "Creating new originator: %pM\n", addr);
213
214         orig_node = kzalloc(sizeof(*orig_node), GFP_ATOMIC);
215         if (!orig_node)
216                 return NULL;
217
218         INIT_HLIST_HEAD(&orig_node->neigh_list);
219         INIT_LIST_HEAD(&orig_node->bond_list);
220         spin_lock_init(&orig_node->ogm_cnt_lock);
221         spin_lock_init(&orig_node->bcast_seqno_lock);
222         spin_lock_init(&orig_node->neigh_list_lock);
223         spin_lock_init(&orig_node->tt_buff_lock);
224
225         /* extra reference for return */
226         atomic_set(&orig_node->refcount, 2);
227
228         orig_node->tt_initialised = false;
229         orig_node->bat_priv = bat_priv;
230         memcpy(orig_node->orig, addr, ETH_ALEN);
231         batadv_dat_init_orig_node_addr(orig_node);
232         orig_node->router = NULL;
233         orig_node->tt_crc = 0;
234         atomic_set(&orig_node->last_ttvn, 0);
235         orig_node->tt_buff = NULL;
236         orig_node->tt_buff_len = 0;
237         atomic_set(&orig_node->tt_size, 0);
238         reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
239         orig_node->bcast_seqno_reset = reset_time;
240         orig_node->batman_seqno_reset = reset_time;
241
242         atomic_set(&orig_node->bond_candidates, 0);
243
244         size = bat_priv->num_ifaces * sizeof(unsigned long) * BATADV_NUM_WORDS;
245
246         orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
247         if (!orig_node->bcast_own)
248                 goto free_orig_node;
249
250         size = bat_priv->num_ifaces * sizeof(uint8_t);
251         orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
252
253         INIT_LIST_HEAD(&orig_node->frag_list);
254         orig_node->last_frag_packet = 0;
255
256         if (!orig_node->bcast_own_sum)
257                 goto free_bcast_own;
258
259         hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
260                                      batadv_choose_orig, orig_node,
261                                      &orig_node->hash_entry);
262         if (hash_added != 0)
263                 goto free_bcast_own_sum;
264
265         return orig_node;
266 free_bcast_own_sum:
267         kfree(orig_node->bcast_own_sum);
268 free_bcast_own:
269         kfree(orig_node->bcast_own);
270 free_orig_node:
271         kfree(orig_node);
272         return NULL;
273 }
274
275 static bool
276 batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
277                             struct batadv_orig_node *orig_node,
278                             struct batadv_neigh_node **best_neigh_node)
279 {
280         struct hlist_node *node, *node_tmp;
281         struct batadv_neigh_node *neigh_node;
282         bool neigh_purged = false;
283         unsigned long last_seen;
284         struct batadv_hard_iface *if_incoming;
285
286         *best_neigh_node = NULL;
287
288         spin_lock_bh(&orig_node->neigh_list_lock);
289
290         /* for all neighbors towards this originator ... */
291         hlist_for_each_entry_safe(neigh_node, node, node_tmp,
292                                   &orig_node->neigh_list, list) {
293                 last_seen = neigh_node->last_seen;
294                 if_incoming = neigh_node->if_incoming;
295
296                 if ((batadv_has_timed_out(last_seen, BATADV_PURGE_TIMEOUT)) ||
297                     (if_incoming->if_status == BATADV_IF_INACTIVE) ||
298                     (if_incoming->if_status == BATADV_IF_NOT_IN_USE) ||
299                     (if_incoming->if_status == BATADV_IF_TO_BE_REMOVED)) {
300                         if ((if_incoming->if_status == BATADV_IF_INACTIVE) ||
301                             (if_incoming->if_status == BATADV_IF_NOT_IN_USE) ||
302                             (if_incoming->if_status == BATADV_IF_TO_BE_REMOVED))
303                                 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
304                                            "neighbor purge: originator %pM, neighbor: %pM, iface: %s\n",
305                                            orig_node->orig, neigh_node->addr,
306                                            if_incoming->net_dev->name);
307                         else
308                                 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
309                                            "neighbor timeout: originator %pM, neighbor: %pM, last_seen: %u\n",
310                                            orig_node->orig, neigh_node->addr,
311                                            jiffies_to_msecs(last_seen));
312
313                         neigh_purged = true;
314
315                         hlist_del_rcu(&neigh_node->list);
316                         batadv_bonding_candidate_del(orig_node, neigh_node);
317                         batadv_neigh_node_free_ref(neigh_node);
318                 } else {
319                         if ((!*best_neigh_node) ||
320                             (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
321                                 *best_neigh_node = neigh_node;
322                 }
323         }
324
325         spin_unlock_bh(&orig_node->neigh_list_lock);
326         return neigh_purged;
327 }
328
329 static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
330                                    struct batadv_orig_node *orig_node)
331 {
332         struct batadv_neigh_node *best_neigh_node;
333
334         if (batadv_has_timed_out(orig_node->last_seen,
335                                  2 * BATADV_PURGE_TIMEOUT)) {
336                 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
337                            "Originator timeout: originator %pM, last_seen %u\n",
338                            orig_node->orig,
339                            jiffies_to_msecs(orig_node->last_seen));
340                 return true;
341         } else {
342                 if (batadv_purge_orig_neighbors(bat_priv, orig_node,
343                                                 &best_neigh_node))
344                         batadv_update_route(bat_priv, orig_node,
345                                             best_neigh_node);
346         }
347
348         return false;
349 }
350
351 static void _batadv_purge_orig(struct batadv_priv *bat_priv)
352 {
353         struct batadv_hashtable *hash = bat_priv->orig_hash;
354         struct hlist_node *node, *node_tmp;
355         struct hlist_head *head;
356         spinlock_t *list_lock; /* spinlock to protect write access */
357         struct batadv_orig_node *orig_node;
358         uint32_t i;
359
360         if (!hash)
361                 return;
362
363         /* for all origins... */
364         for (i = 0; i < hash->size; i++) {
365                 head = &hash->table[i];
366                 list_lock = &hash->list_locks[i];
367
368                 spin_lock_bh(list_lock);
369                 hlist_for_each_entry_safe(orig_node, node, node_tmp,
370                                           head, hash_entry) {
371                         if (batadv_purge_orig_node(bat_priv, orig_node)) {
372                                 if (orig_node->gw_flags)
373                                         batadv_gw_node_delete(bat_priv,
374                                                               orig_node);
375                                 hlist_del_rcu(node);
376                                 batadv_orig_node_free_ref(orig_node);
377                                 continue;
378                         }
379
380                         if (batadv_has_timed_out(orig_node->last_frag_packet,
381                                                  BATADV_FRAG_TIMEOUT))
382                                 batadv_frag_list_free(&orig_node->frag_list);
383                 }
384                 spin_unlock_bh(list_lock);
385         }
386
387         batadv_gw_node_purge(bat_priv);
388         batadv_gw_election(bat_priv);
389 }
390
391 static void batadv_purge_orig(struct work_struct *work)
392 {
393         struct delayed_work *delayed_work;
394         struct batadv_priv *bat_priv;
395
396         delayed_work = container_of(work, struct delayed_work, work);
397         bat_priv = container_of(delayed_work, struct batadv_priv, orig_work);
398         _batadv_purge_orig(bat_priv);
399         batadv_start_purge_timer(bat_priv);
400 }
401
402 void batadv_purge_orig_ref(struct batadv_priv *bat_priv)
403 {
404         _batadv_purge_orig(bat_priv);
405 }
406
407 int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
408 {
409         struct net_device *net_dev = (struct net_device *)seq->private;
410         struct batadv_priv *bat_priv = netdev_priv(net_dev);
411         struct batadv_hashtable *hash = bat_priv->orig_hash;
412         struct hlist_node *node, *node_tmp;
413         struct hlist_head *head;
414         struct batadv_hard_iface *primary_if;
415         struct batadv_orig_node *orig_node;
416         struct batadv_neigh_node *neigh_node, *neigh_node_tmp;
417         int batman_count = 0;
418         int last_seen_secs;
419         int last_seen_msecs;
420         unsigned long last_seen_jiffies;
421         uint32_t i;
422
423         primary_if = batadv_seq_print_text_primary_if_get(seq);
424         if (!primary_if)
425                 goto out;
426
427         seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
428                    BATADV_SOURCE_VERSION, primary_if->net_dev->name,
429                    primary_if->net_dev->dev_addr, net_dev->name);
430         seq_printf(seq, "  %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
431                    "Originator", "last-seen", "#", BATADV_TQ_MAX_VALUE,
432                    "Nexthop", "outgoingIF", "Potential nexthops");
433
434         for (i = 0; i < hash->size; i++) {
435                 head = &hash->table[i];
436
437                 rcu_read_lock();
438                 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
439                         neigh_node = batadv_orig_node_get_router(orig_node);
440                         if (!neigh_node)
441                                 continue;
442
443                         if (neigh_node->tq_avg == 0)
444                                 goto next;
445
446                         last_seen_jiffies = jiffies - orig_node->last_seen;
447                         last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
448                         last_seen_secs = last_seen_msecs / 1000;
449                         last_seen_msecs = last_seen_msecs % 1000;
450
451                         seq_printf(seq, "%pM %4i.%03is   (%3i) %pM [%10s]:",
452                                    orig_node->orig, last_seen_secs,
453                                    last_seen_msecs, neigh_node->tq_avg,
454                                    neigh_node->addr,
455                                    neigh_node->if_incoming->net_dev->name);
456
457                         hlist_for_each_entry_rcu(neigh_node_tmp, node_tmp,
458                                                  &orig_node->neigh_list, list) {
459                                 seq_printf(seq, " %pM (%3i)",
460                                            neigh_node_tmp->addr,
461                                            neigh_node_tmp->tq_avg);
462                         }
463
464                         seq_printf(seq, "\n");
465                         batman_count++;
466
467 next:
468                         batadv_neigh_node_free_ref(neigh_node);
469                 }
470                 rcu_read_unlock();
471         }
472
473         if (batman_count == 0)
474                 seq_printf(seq, "No batman nodes in range ...\n");
475
476 out:
477         if (primary_if)
478                 batadv_hardif_free_ref(primary_if);
479         return 0;
480 }
481
482 static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node,
483                                    int max_if_num)
484 {
485         void *data_ptr;
486         size_t data_size, old_size;
487
488         data_size = max_if_num * sizeof(unsigned long) * BATADV_NUM_WORDS;
489         old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS;
490         data_ptr = kmalloc(data_size, GFP_ATOMIC);
491         if (!data_ptr)
492                 return -ENOMEM;
493
494         memcpy(data_ptr, orig_node->bcast_own, old_size);
495         kfree(orig_node->bcast_own);
496         orig_node->bcast_own = data_ptr;
497
498         data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
499         if (!data_ptr)
500                 return -ENOMEM;
501
502         memcpy(data_ptr, orig_node->bcast_own_sum,
503                (max_if_num - 1) * sizeof(uint8_t));
504         kfree(orig_node->bcast_own_sum);
505         orig_node->bcast_own_sum = data_ptr;
506
507         return 0;
508 }
509
510 int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
511                             int max_if_num)
512 {
513         struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
514         struct batadv_hashtable *hash = bat_priv->orig_hash;
515         struct hlist_node *node;
516         struct hlist_head *head;
517         struct batadv_orig_node *orig_node;
518         uint32_t i;
519         int ret;
520
521         /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
522          * if_num
523          */
524         for (i = 0; i < hash->size; i++) {
525                 head = &hash->table[i];
526
527                 rcu_read_lock();
528                 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
529                         spin_lock_bh(&orig_node->ogm_cnt_lock);
530                         ret = batadv_orig_node_add_if(orig_node, max_if_num);
531                         spin_unlock_bh(&orig_node->ogm_cnt_lock);
532
533                         if (ret == -ENOMEM)
534                                 goto err;
535                 }
536                 rcu_read_unlock();
537         }
538
539         return 0;
540
541 err:
542         rcu_read_unlock();
543         return -ENOMEM;
544 }
545
546 static int batadv_orig_node_del_if(struct batadv_orig_node *orig_node,
547                                    int max_if_num, int del_if_num)
548 {
549         void *data_ptr = NULL;
550         int chunk_size;
551
552         /* last interface was removed */
553         if (max_if_num == 0)
554                 goto free_bcast_own;
555
556         chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS;
557         data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
558         if (!data_ptr)
559                 return -ENOMEM;
560
561         /* copy first part */
562         memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size);
563
564         /* copy second part */
565         memcpy((char *)data_ptr + del_if_num * chunk_size,
566                orig_node->bcast_own + ((del_if_num + 1) * chunk_size),
567                (max_if_num - del_if_num) * chunk_size);
568
569 free_bcast_own:
570         kfree(orig_node->bcast_own);
571         orig_node->bcast_own = data_ptr;
572
573         if (max_if_num == 0)
574                 goto free_own_sum;
575
576         data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
577         if (!data_ptr)
578                 return -ENOMEM;
579
580         memcpy(data_ptr, orig_node->bcast_own_sum,
581                del_if_num * sizeof(uint8_t));
582
583         memcpy((char *)data_ptr + del_if_num * sizeof(uint8_t),
584                orig_node->bcast_own_sum + ((del_if_num + 1) * sizeof(uint8_t)),
585                (max_if_num - del_if_num) * sizeof(uint8_t));
586
587 free_own_sum:
588         kfree(orig_node->bcast_own_sum);
589         orig_node->bcast_own_sum = data_ptr;
590
591         return 0;
592 }
593
594 int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
595                             int max_if_num)
596 {
597         struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
598         struct batadv_hashtable *hash = bat_priv->orig_hash;
599         struct hlist_node *node;
600         struct hlist_head *head;
601         struct batadv_hard_iface *hard_iface_tmp;
602         struct batadv_orig_node *orig_node;
603         uint32_t i;
604         int ret;
605
606         /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
607          * if_num
608          */
609         for (i = 0; i < hash->size; i++) {
610                 head = &hash->table[i];
611
612                 rcu_read_lock();
613                 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
614                         spin_lock_bh(&orig_node->ogm_cnt_lock);
615                         ret = batadv_orig_node_del_if(orig_node, max_if_num,
616                                                       hard_iface->if_num);
617                         spin_unlock_bh(&orig_node->ogm_cnt_lock);
618
619                         if (ret == -ENOMEM)
620                                 goto err;
621                 }
622                 rcu_read_unlock();
623         }
624
625         /* renumber remaining batman interfaces _inside_ of orig_hash_lock */
626         rcu_read_lock();
627         list_for_each_entry_rcu(hard_iface_tmp, &batadv_hardif_list, list) {
628                 if (hard_iface_tmp->if_status == BATADV_IF_NOT_IN_USE)
629                         continue;
630
631                 if (hard_iface == hard_iface_tmp)
632                         continue;
633
634                 if (hard_iface->soft_iface != hard_iface_tmp->soft_iface)
635                         continue;
636
637                 if (hard_iface_tmp->if_num > hard_iface->if_num)
638                         hard_iface_tmp->if_num--;
639         }
640         rcu_read_unlock();
641
642         hard_iface->if_num = -1;
643         return 0;
644
645 err:
646         rcu_read_unlock();
647         return -ENOMEM;
648 }