aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/batman-adv/bat_iv_ogm.c126
-rw-r--r--net/batman-adv/originator.c102
-rw-r--r--net/batman-adv/types.h11
3 files changed, 151 insertions, 88 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 7cdc3943103a..a2b480a90872 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -88,6 +88,129 @@ static uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[])
88} 88}
89 89
90/** 90/**
91 * batadv_iv_ogm_orig_free - free the private resources allocated for this
92 * orig_node
93 * @orig_node: the orig_node for which the resources have to be free'd
94 */
95static void batadv_iv_ogm_orig_free(struct batadv_orig_node *orig_node)
96{
97 kfree(orig_node->bat_iv.bcast_own);
98 kfree(orig_node->bat_iv.bcast_own_sum);
99}
100
101/**
102 * batadv_iv_ogm_orig_add_if - change the private structures of the orig_node to
103 * include the new hard-interface
104 * @orig_node: the orig_node that has to be changed
105 * @max_if_num: the current amount of interfaces
106 *
107 * Returns 0 on success, a negative error code otherwise.
108 */
109static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node,
110 int max_if_num)
111{
112 void *data_ptr;
113 size_t data_size, old_size;
114 int ret = -ENOMEM;
115
116 spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
117
118 data_size = max_if_num * sizeof(unsigned long) * BATADV_NUM_WORDS;
119 old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS;
120 data_ptr = kmalloc(data_size, GFP_ATOMIC);
121 if (!data_ptr)
122 goto unlock;
123
124 memcpy(data_ptr, orig_node->bat_iv.bcast_own, old_size);
125 kfree(orig_node->bat_iv.bcast_own);
126 orig_node->bat_iv.bcast_own = data_ptr;
127
128 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
129 if (!data_ptr) {
130 kfree(orig_node->bat_iv.bcast_own);
131 goto unlock;
132 }
133
134 memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
135 (max_if_num - 1) * sizeof(uint8_t));
136 kfree(orig_node->bat_iv.bcast_own_sum);
137 orig_node->bat_iv.bcast_own_sum = data_ptr;
138
139 ret = 0;
140
141unlock:
142 spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
143
144 return ret;
145}
146
147/**
148 * batadv_iv_ogm_orig_del_if - change the private structures of the orig_node to
149 * exclude the removed interface
150 * @orig_node: the orig_node that has to be changed
151 * @max_if_num: the current amount of interfaces
152 * @del_if_num: the index of the interface being removed
153 *
154 * Returns 0 on success, a negative error code otherwise.
155 */
156static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node,
157 int max_if_num, int del_if_num)
158{
159 int chunk_size, ret = -ENOMEM, if_offset;
160 void *data_ptr = NULL;
161
162 spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
163
164 /* last interface was removed */
165 if (max_if_num == 0)
166 goto free_bcast_own;
167
168 chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS;
169 data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
170 if (!data_ptr)
171 goto unlock;
172
173 /* copy first part */
174 memcpy(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size);
175
176 /* copy second part */
177 memcpy((char *)data_ptr + del_if_num * chunk_size,
178 orig_node->bat_iv.bcast_own + ((del_if_num + 1) * chunk_size),
179 (max_if_num - del_if_num) * chunk_size);
180
181free_bcast_own:
182 kfree(orig_node->bat_iv.bcast_own);
183 orig_node->bat_iv.bcast_own = data_ptr;
184
185 if (max_if_num == 0)
186 goto free_own_sum;
187
188 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
189 if (!data_ptr) {
190 kfree(orig_node->bat_iv.bcast_own);
191 goto unlock;
192 }
193
194 memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
195 del_if_num * sizeof(uint8_t));
196
197 if_offset = (del_if_num + 1) * sizeof(uint8_t);
198 memcpy((char *)data_ptr + del_if_num * sizeof(uint8_t),
199 orig_node->bat_iv.bcast_own_sum + if_offset,
200 (max_if_num - del_if_num) * sizeof(uint8_t));
201
202free_own_sum:
203 kfree(orig_node->bat_iv.bcast_own_sum);
204 orig_node->bat_iv.bcast_own_sum = data_ptr;
205
206 ret = 0;
207unlock:
208 spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
209
210 return ret;
211}
212
213/**
91 * batadv_iv_ogm_orig_get - retrieve or create (if does not exist) an originator 214 * batadv_iv_ogm_orig_get - retrieve or create (if does not exist) an originator
92 * @bat_priv: the bat priv with all the soft interface information 215 * @bat_priv: the bat priv with all the soft interface information
93 * @addr: mac address of the originator 216 * @addr: mac address of the originator
@@ -1522,6 +1645,9 @@ static struct batadv_algo_ops batadv_batman_iv __read_mostly = {
1522 .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp, 1645 .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp,
1523 .bat_neigh_is_equiv_or_better = batadv_iv_ogm_neigh_is_eob, 1646 .bat_neigh_is_equiv_or_better = batadv_iv_ogm_neigh_is_eob,
1524 .bat_orig_print = batadv_iv_ogm_orig_print, 1647 .bat_orig_print = batadv_iv_ogm_orig_print,
1648 .bat_orig_free = batadv_iv_ogm_orig_free,
1649 .bat_orig_add_if = batadv_iv_ogm_orig_add_if,
1650 .bat_orig_del_if = batadv_iv_ogm_orig_del_if,
1525}; 1651};
1526 1652
1527int __init batadv_iv_init(void) 1653int __init batadv_iv_init(void)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 9cee053f6a5c..8ab14340d10f 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -241,9 +241,10 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
241 batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, -1, 241 batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, -1,
242 "originator timed out"); 242 "originator timed out");
243 243
244 if (orig_node->bat_priv->bat_algo_ops->bat_orig_free)
245 orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node);
246
244 kfree(orig_node->tt_buff); 247 kfree(orig_node->tt_buff);
245 kfree(orig_node->bat_iv.bcast_own);
246 kfree(orig_node->bat_iv.bcast_own_sum);
247 kfree(orig_node); 248 kfree(orig_node);
248} 249}
249 250
@@ -538,38 +539,11 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
538 return 0; 539 return 0;
539} 540}
540 541
541static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node,
542 int max_if_num)
543{
544 void *data_ptr;
545 size_t data_size, old_size;
546
547 data_size = max_if_num * sizeof(unsigned long) * BATADV_NUM_WORDS;
548 old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS;
549 data_ptr = kmalloc(data_size, GFP_ATOMIC);
550 if (!data_ptr)
551 return -ENOMEM;
552
553 memcpy(data_ptr, orig_node->bat_iv.bcast_own, old_size);
554 kfree(orig_node->bat_iv.bcast_own);
555 orig_node->bat_iv.bcast_own = data_ptr;
556
557 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
558 if (!data_ptr)
559 return -ENOMEM;
560
561 memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
562 (max_if_num - 1) * sizeof(uint8_t));
563 kfree(orig_node->bat_iv.bcast_own_sum);
564 orig_node->bat_iv.bcast_own_sum = data_ptr;
565
566 return 0;
567}
568
569int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, 542int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
570 int max_if_num) 543 int max_if_num)
571{ 544{
572 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 545 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
546 struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
573 struct batadv_hashtable *hash = bat_priv->orig_hash; 547 struct batadv_hashtable *hash = bat_priv->orig_hash;
574 struct hlist_head *head; 548 struct hlist_head *head;
575 struct batadv_orig_node *orig_node; 549 struct batadv_orig_node *orig_node;
@@ -584,10 +558,10 @@ int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
584 558
585 rcu_read_lock(); 559 rcu_read_lock();
586 hlist_for_each_entry_rcu(orig_node, head, hash_entry) { 560 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
587 spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); 561 ret = 0;
588 ret = batadv_orig_node_add_if(orig_node, max_if_num); 562 if (bao->bat_orig_add_if)
589 spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); 563 ret = bao->bat_orig_add_if(orig_node,
590 564 max_if_num);
591 if (ret == -ENOMEM) 565 if (ret == -ENOMEM)
592 goto err; 566 goto err;
593 } 567 }
@@ -601,55 +575,6 @@ err:
601 return -ENOMEM; 575 return -ENOMEM;
602} 576}
603 577
604static int batadv_orig_node_del_if(struct batadv_orig_node *orig_node,
605 int max_if_num, int del_if_num)
606{
607 int chunk_size, if_offset;
608 void *data_ptr = NULL;
609
610 /* last interface was removed */
611 if (max_if_num == 0)
612 goto free_bcast_own;
613
614 chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS;
615 data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
616 if (!data_ptr)
617 return -ENOMEM;
618
619 /* copy first part */
620 memcpy(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size);
621
622 /* copy second part */
623 memcpy((char *)data_ptr + del_if_num * chunk_size,
624 orig_node->bat_iv.bcast_own + ((del_if_num + 1) * chunk_size),
625 (max_if_num - del_if_num) * chunk_size);
626
627free_bcast_own:
628 kfree(orig_node->bat_iv.bcast_own);
629 orig_node->bat_iv.bcast_own = data_ptr;
630
631 if (max_if_num == 0)
632 goto free_own_sum;
633
634 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
635 if (!data_ptr)
636 return -ENOMEM;
637
638 memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
639 del_if_num * sizeof(uint8_t));
640
641 if_offset = (del_if_num + 1) * sizeof(uint8_t);
642 memcpy((char *)data_ptr + del_if_num * sizeof(uint8_t),
643 orig_node->bat_iv.bcast_own_sum + if_offset,
644 (max_if_num - del_if_num) * sizeof(uint8_t));
645
646free_own_sum:
647 kfree(orig_node->bat_iv.bcast_own_sum);
648 orig_node->bat_iv.bcast_own_sum = data_ptr;
649
650 return 0;
651}
652
653int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, 578int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
654 int max_if_num) 579 int max_if_num)
655{ 580{
@@ -658,6 +583,7 @@ int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
658 struct hlist_head *head; 583 struct hlist_head *head;
659 struct batadv_hard_iface *hard_iface_tmp; 584 struct batadv_hard_iface *hard_iface_tmp;
660 struct batadv_orig_node *orig_node; 585 struct batadv_orig_node *orig_node;
586 struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
661 uint32_t i; 587 uint32_t i;
662 int ret; 588 int ret;
663 589
@@ -669,11 +595,11 @@ int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
669 595
670 rcu_read_lock(); 596 rcu_read_lock();
671 hlist_for_each_entry_rcu(orig_node, head, hash_entry) { 597 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
672 spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); 598 ret = 0;
673 ret = batadv_orig_node_del_if(orig_node, max_if_num, 599 if (bao->bat_orig_del_if)
674 hard_iface->if_num); 600 ret = bao->bat_orig_del_if(orig_node,
675 spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); 601 max_if_num,
676 602 hard_iface->if_num);
677 if (ret == -ENOMEM) 603 if (ret == -ENOMEM)
678 goto err; 604 goto err;
679 } 605 }
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index d0e64d269da4..672a8134d3ba 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -996,6 +996,12 @@ struct batadv_forw_packet {
996 * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or 996 * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or
997 * better than neigh2 from the metric prospective 997 * better than neigh2 from the metric prospective
998 * @bat_orig_print: print the originator table (optional) 998 * @bat_orig_print: print the originator table (optional)
999 * @bat_orig_free: free the resources allocated by the routing algorithm for an
1000 * orig_node object
1001 * @bat_orig_add_if: ask the routing algorithm to apply the needed changes to
1002 * the orig_node due to a new hard-interface being added into the mesh
1003 * @bat_orig_del_if: ask the routing algorithm to apply the needed changes to
1004 * the orig_node due to an hard-interface being removed from the mesh
999 */ 1005 */
1000struct batadv_algo_ops { 1006struct batadv_algo_ops {
1001 struct hlist_node list; 1007 struct hlist_node list;
@@ -1012,6 +1018,11 @@ struct batadv_algo_ops {
1012 struct batadv_neigh_node *neigh2); 1018 struct batadv_neigh_node *neigh2);
1013 /* orig_node handling API */ 1019 /* orig_node handling API */
1014 void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq); 1020 void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq);
1021 void (*bat_orig_free)(struct batadv_orig_node *orig_node);
1022 int (*bat_orig_add_if)(struct batadv_orig_node *orig_node,
1023 int max_if_num);
1024 int (*bat_orig_del_if)(struct batadv_orig_node *orig_node,
1025 int max_if_num, int del_if_num);
1015}; 1026};
1016 1027
1017/** 1028/**