diff options
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 126 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 102 | ||||
-rw-r--r-- | net/batman-adv/types.h | 11 |
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 | */ | ||
95 | static 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 | */ | ||
109 | static 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 | |||
141 | unlock: | ||
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 | */ | ||
156 | static 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 | |||
181 | free_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 | |||
202 | free_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; | ||
207 | unlock: | ||
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 | ||
1527 | int __init batadv_iv_init(void) | 1653 | int __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 | ||
541 | static 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 | |||
569 | int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, | 542 | int 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 | ||
604 | static 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 | |||
627 | free_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 | |||
646 | free_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 | |||
653 | int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, | 578 | int 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 | */ |
1000 | struct batadv_algo_ops { | 1006 | struct 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 | /** |