diff options
| author | Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de> | 2012-01-22 14:00:18 -0500 |
|---|---|---|
| committer | Antonio Quartulli <ordex@autistici.org> | 2012-04-11 08:28:58 -0400 |
| commit | a7f6ee9493677ba40625d810258de5bd521cc1b0 (patch) | |
| tree | 6635b87289ae083a466f14d2c9aed4bb20adae34 /net/batman-adv | |
| parent | 8681a1c4dd258c573e80b4a7af7e7127770b67a8 (diff) | |
batman-adv: remove old bridge loop avoidance code
The functionality is to be replaced by an improved implementation,
so first clean up.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Diffstat (limited to 'net/batman-adv')
| -rw-r--r-- | net/batman-adv/bat_debugfs.c | 8 | ||||
| -rw-r--r-- | net/batman-adv/main.c | 5 | ||||
| -rw-r--r-- | net/batman-adv/main.h | 2 | ||||
| -rw-r--r-- | net/batman-adv/originator.c | 2 | ||||
| -rw-r--r-- | net/batman-adv/routing.c | 5 | ||||
| -rw-r--r-- | net/batman-adv/routing.h | 1 | ||||
| -rw-r--r-- | net/batman-adv/soft-interface.c | 476 | ||||
| -rw-r--r-- | net/batman-adv/soft-interface.h | 2 | ||||
| -rw-r--r-- | net/batman-adv/types.h | 21 |
9 files changed, 5 insertions, 517 deletions
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c index c3b0548b175d..165ff62a2bed 100644 --- a/net/batman-adv/bat_debugfs.c +++ b/net/batman-adv/bat_debugfs.c | |||
| @@ -238,12 +238,6 @@ static int gateways_open(struct inode *inode, struct file *file) | |||
| 238 | return single_open(file, gw_client_seq_print_text, net_dev); | 238 | return single_open(file, gw_client_seq_print_text, net_dev); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | static int softif_neigh_open(struct inode *inode, struct file *file) | ||
| 242 | { | ||
| 243 | struct net_device *net_dev = (struct net_device *)inode->i_private; | ||
| 244 | return single_open(file, softif_neigh_seq_print_text, net_dev); | ||
| 245 | } | ||
| 246 | |||
| 247 | static int transtable_global_open(struct inode *inode, struct file *file) | 241 | static int transtable_global_open(struct inode *inode, struct file *file) |
| 248 | { | 242 | { |
| 249 | struct net_device *net_dev = (struct net_device *)inode->i_private; | 243 | struct net_device *net_dev = (struct net_device *)inode->i_private; |
| @@ -282,7 +276,6 @@ struct bat_debuginfo bat_debuginfo_##_name = { \ | |||
| 282 | static BAT_DEBUGINFO(routing_algos, S_IRUGO, bat_algorithms_open); | 276 | static BAT_DEBUGINFO(routing_algos, S_IRUGO, bat_algorithms_open); |
| 283 | static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); | 277 | static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); |
| 284 | static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); | 278 | static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); |
| 285 | static BAT_DEBUGINFO(softif_neigh, S_IRUGO, softif_neigh_open); | ||
| 286 | static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); | 279 | static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); |
| 287 | static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); | 280 | static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); |
| 288 | static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); | 281 | static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); |
| @@ -290,7 +283,6 @@ static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); | |||
| 290 | static struct bat_debuginfo *mesh_debuginfos[] = { | 283 | static struct bat_debuginfo *mesh_debuginfos[] = { |
| 291 | &bat_debuginfo_originators, | 284 | &bat_debuginfo_originators, |
| 292 | &bat_debuginfo_gateways, | 285 | &bat_debuginfo_gateways, |
| 293 | &bat_debuginfo_softif_neigh, | ||
| 294 | &bat_debuginfo_transtable_global, | 286 | &bat_debuginfo_transtable_global, |
| 295 | &bat_debuginfo_transtable_local, | 287 | &bat_debuginfo_transtable_local, |
| 296 | &bat_debuginfo_vis_data, | 288 | &bat_debuginfo_vis_data, |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 6d51caaf8cec..94d4968a953a 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
| @@ -96,13 +96,10 @@ int mesh_init(struct net_device *soft_iface) | |||
| 96 | spin_lock_init(&bat_priv->gw_list_lock); | 96 | spin_lock_init(&bat_priv->gw_list_lock); |
| 97 | spin_lock_init(&bat_priv->vis_hash_lock); | 97 | spin_lock_init(&bat_priv->vis_hash_lock); |
| 98 | spin_lock_init(&bat_priv->vis_list_lock); | 98 | spin_lock_init(&bat_priv->vis_list_lock); |
| 99 | spin_lock_init(&bat_priv->softif_neigh_lock); | ||
| 100 | spin_lock_init(&bat_priv->softif_neigh_vid_lock); | ||
| 101 | 99 | ||
| 102 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); | 100 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); |
| 103 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); | 101 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); |
| 104 | INIT_HLIST_HEAD(&bat_priv->gw_list); | 102 | INIT_HLIST_HEAD(&bat_priv->gw_list); |
| 105 | INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids); | ||
| 106 | INIT_LIST_HEAD(&bat_priv->tt_changes_list); | 103 | INIT_LIST_HEAD(&bat_priv->tt_changes_list); |
| 107 | INIT_LIST_HEAD(&bat_priv->tt_req_list); | 104 | INIT_LIST_HEAD(&bat_priv->tt_req_list); |
| 108 | INIT_LIST_HEAD(&bat_priv->tt_roam_list); | 105 | INIT_LIST_HEAD(&bat_priv->tt_roam_list); |
| @@ -145,8 +142,6 @@ void mesh_free(struct net_device *soft_iface) | |||
| 145 | 142 | ||
| 146 | tt_free(bat_priv); | 143 | tt_free(bat_priv); |
| 147 | 144 | ||
| 148 | softif_neigh_purge(bat_priv); | ||
| 149 | |||
| 150 | atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); | 145 | atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); |
| 151 | } | 146 | } |
| 152 | 147 | ||
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 0a20a19197aa..7a6a25f22fc2 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
| @@ -80,8 +80,6 @@ | |||
| 80 | #define MAX_AGGREGATION_BYTES 512 | 80 | #define MAX_AGGREGATION_BYTES 512 |
| 81 | #define MAX_AGGREGATION_MS 100 | 81 | #define MAX_AGGREGATION_MS 100 |
| 82 | 82 | ||
| 83 | #define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */ | ||
| 84 | |||
| 85 | /* don't reset again within 30 seconds */ | 83 | /* don't reset again within 30 seconds */ |
| 86 | #define RESET_PROTECTION_MS 30000 | 84 | #define RESET_PROTECTION_MS 30000 |
| 87 | #define EXPECTED_SEQNO_RANGE 65536 | 85 | #define EXPECTED_SEQNO_RANGE 65536 |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 43c0a4f1399e..82390818874b 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
| @@ -375,8 +375,6 @@ static void _purge_orig(struct bat_priv *bat_priv) | |||
| 375 | 375 | ||
| 376 | gw_node_purge(bat_priv); | 376 | gw_node_purge(bat_priv); |
| 377 | gw_election(bat_priv); | 377 | gw_election(bat_priv); |
| 378 | |||
| 379 | softif_neigh_purge(bat_priv); | ||
| 380 | } | 378 | } |
| 381 | 379 | ||
| 382 | static void purge_orig(struct work_struct *work) | 380 | static void purge_orig(struct work_struct *work) |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index b0370e3c59e8..71d4211beb23 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
| @@ -30,6 +30,9 @@ | |||
| 30 | #include "vis.h" | 30 | #include "vis.h" |
| 31 | #include "unicast.h" | 31 | #include "unicast.h" |
| 32 | 32 | ||
| 33 | static int route_unicast_packet(struct sk_buff *skb, | ||
| 34 | struct hard_iface *recv_if); | ||
| 35 | |||
| 33 | void slide_own_bcast_window(struct hard_iface *hard_iface) | 36 | void slide_own_bcast_window(struct hard_iface *hard_iface) |
| 34 | { | 37 | { |
| 35 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 38 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
| @@ -798,7 +801,7 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) | |||
| 798 | return 0; | 801 | return 0; |
| 799 | } | 802 | } |
| 800 | 803 | ||
| 801 | int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | 804 | static int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
| 802 | { | 805 | { |
| 803 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 806 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
| 804 | struct orig_node *orig_node = NULL; | 807 | struct orig_node *orig_node = NULL; |
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index 92ac100d83da..3d729cb17113 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | void slide_own_bcast_window(struct hard_iface *hard_iface); | 25 | void slide_own_bcast_window(struct hard_iface *hard_iface); |
| 26 | void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, | 26 | void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, |
| 27 | struct neigh_node *neigh_node); | 27 | struct neigh_node *neigh_node); |
| 28 | int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); | ||
| 29 | int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 28 | int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
| 30 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 29 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
| 31 | int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 30 | int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 82c097d6ec93..e56cb88ef2ba 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
| @@ -73,439 +73,6 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len) | |||
| 73 | return 0; | 73 | return 0; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) | ||
| 77 | { | ||
| 78 | if (atomic_dec_and_test(&softif_neigh->refcount)) | ||
| 79 | kfree_rcu(softif_neigh, rcu); | ||
| 80 | } | ||
| 81 | |||
| 82 | static void softif_neigh_vid_free_rcu(struct rcu_head *rcu) | ||
| 83 | { | ||
| 84 | struct softif_neigh_vid *softif_neigh_vid; | ||
| 85 | struct softif_neigh *softif_neigh; | ||
| 86 | struct hlist_node *node, *node_tmp; | ||
| 87 | struct bat_priv *bat_priv; | ||
| 88 | |||
| 89 | softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu); | ||
| 90 | bat_priv = softif_neigh_vid->bat_priv; | ||
| 91 | |||
| 92 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
| 93 | hlist_for_each_entry_safe(softif_neigh, node, node_tmp, | ||
| 94 | &softif_neigh_vid->softif_neigh_list, list) { | ||
| 95 | hlist_del_rcu(&softif_neigh->list); | ||
| 96 | softif_neigh_free_ref(softif_neigh); | ||
| 97 | } | ||
| 98 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
| 99 | |||
| 100 | kfree(softif_neigh_vid); | ||
| 101 | } | ||
| 102 | |||
| 103 | static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid) | ||
| 104 | { | ||
| 105 | if (atomic_dec_and_test(&softif_neigh_vid->refcount)) | ||
| 106 | call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu); | ||
| 107 | } | ||
| 108 | |||
| 109 | static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv, | ||
| 110 | short vid) | ||
| 111 | { | ||
| 112 | struct softif_neigh_vid *softif_neigh_vid; | ||
| 113 | struct hlist_node *node; | ||
| 114 | |||
| 115 | rcu_read_lock(); | ||
| 116 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
| 117 | &bat_priv->softif_neigh_vids, list) { | ||
| 118 | if (softif_neigh_vid->vid != vid) | ||
| 119 | continue; | ||
| 120 | |||
| 121 | if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) | ||
| 122 | continue; | ||
| 123 | |||
| 124 | goto out; | ||
| 125 | } | ||
| 126 | |||
| 127 | softif_neigh_vid = kzalloc(sizeof(*softif_neigh_vid), GFP_ATOMIC); | ||
| 128 | if (!softif_neigh_vid) | ||
| 129 | goto out; | ||
| 130 | |||
| 131 | softif_neigh_vid->vid = vid; | ||
| 132 | softif_neigh_vid->bat_priv = bat_priv; | ||
| 133 | |||
| 134 | /* initialize with 2 - caller decrements counter by one */ | ||
| 135 | atomic_set(&softif_neigh_vid->refcount, 2); | ||
| 136 | INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list); | ||
| 137 | INIT_HLIST_NODE(&softif_neigh_vid->list); | ||
| 138 | spin_lock_bh(&bat_priv->softif_neigh_vid_lock); | ||
| 139 | hlist_add_head_rcu(&softif_neigh_vid->list, | ||
| 140 | &bat_priv->softif_neigh_vids); | ||
| 141 | spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); | ||
| 142 | |||
| 143 | out: | ||
| 144 | rcu_read_unlock(); | ||
| 145 | return softif_neigh_vid; | ||
| 146 | } | ||
| 147 | |||
| 148 | static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, | ||
| 149 | const uint8_t *addr, short vid) | ||
| 150 | { | ||
| 151 | struct softif_neigh_vid *softif_neigh_vid; | ||
| 152 | struct softif_neigh *softif_neigh = NULL; | ||
| 153 | struct hlist_node *node; | ||
| 154 | |||
| 155 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
| 156 | if (!softif_neigh_vid) | ||
| 157 | goto out; | ||
| 158 | |||
| 159 | rcu_read_lock(); | ||
| 160 | hlist_for_each_entry_rcu(softif_neigh, node, | ||
| 161 | &softif_neigh_vid->softif_neigh_list, | ||
| 162 | list) { | ||
| 163 | if (!compare_eth(softif_neigh->addr, addr)) | ||
| 164 | continue; | ||
| 165 | |||
| 166 | if (!atomic_inc_not_zero(&softif_neigh->refcount)) | ||
| 167 | continue; | ||
| 168 | |||
| 169 | softif_neigh->last_seen = jiffies; | ||
| 170 | goto unlock; | ||
| 171 | } | ||
| 172 | |||
| 173 | softif_neigh = kzalloc(sizeof(*softif_neigh), GFP_ATOMIC); | ||
| 174 | if (!softif_neigh) | ||
| 175 | goto unlock; | ||
| 176 | |||
| 177 | memcpy(softif_neigh->addr, addr, ETH_ALEN); | ||
| 178 | softif_neigh->last_seen = jiffies; | ||
| 179 | /* initialize with 2 - caller decrements counter by one */ | ||
| 180 | atomic_set(&softif_neigh->refcount, 2); | ||
| 181 | |||
| 182 | INIT_HLIST_NODE(&softif_neigh->list); | ||
| 183 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
| 184 | hlist_add_head_rcu(&softif_neigh->list, | ||
| 185 | &softif_neigh_vid->softif_neigh_list); | ||
| 186 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
| 187 | |||
| 188 | unlock: | ||
| 189 | rcu_read_unlock(); | ||
| 190 | out: | ||
| 191 | if (softif_neigh_vid) | ||
| 192 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
| 193 | return softif_neigh; | ||
| 194 | } | ||
| 195 | |||
| 196 | static struct softif_neigh *softif_neigh_get_selected( | ||
| 197 | struct softif_neigh_vid *softif_neigh_vid) | ||
| 198 | { | ||
| 199 | struct softif_neigh *softif_neigh; | ||
| 200 | |||
| 201 | rcu_read_lock(); | ||
| 202 | softif_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); | ||
| 203 | |||
| 204 | if (softif_neigh && !atomic_inc_not_zero(&softif_neigh->refcount)) | ||
| 205 | softif_neigh = NULL; | ||
| 206 | |||
| 207 | rcu_read_unlock(); | ||
| 208 | return softif_neigh; | ||
| 209 | } | ||
| 210 | |||
| 211 | static struct softif_neigh *softif_neigh_vid_get_selected( | ||
| 212 | struct bat_priv *bat_priv, | ||
| 213 | short vid) | ||
| 214 | { | ||
| 215 | struct softif_neigh_vid *softif_neigh_vid; | ||
| 216 | struct softif_neigh *softif_neigh = NULL; | ||
| 217 | |||
| 218 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
| 219 | if (!softif_neigh_vid) | ||
| 220 | goto out; | ||
| 221 | |||
| 222 | softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
| 223 | out: | ||
| 224 | if (softif_neigh_vid) | ||
| 225 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
| 226 | return softif_neigh; | ||
| 227 | } | ||
| 228 | |||
| 229 | static void softif_neigh_vid_select(struct bat_priv *bat_priv, | ||
| 230 | struct softif_neigh *new_neigh, | ||
| 231 | short vid) | ||
| 232 | { | ||
| 233 | struct softif_neigh_vid *softif_neigh_vid; | ||
| 234 | struct softif_neigh *curr_neigh; | ||
| 235 | |||
| 236 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
| 237 | if (!softif_neigh_vid) | ||
| 238 | goto out; | ||
| 239 | |||
| 240 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
| 241 | |||
| 242 | if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) | ||
| 243 | new_neigh = NULL; | ||
| 244 | |||
| 245 | curr_neigh = rcu_dereference_protected(softif_neigh_vid->softif_neigh, | ||
| 246 | 1); | ||
| 247 | rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh); | ||
| 248 | |||
| 249 | if ((curr_neigh) && (!new_neigh)) | ||
| 250 | bat_dbg(DBG_ROUTES, bat_priv, | ||
| 251 | "Removing mesh exit point on vid: %d (prev: %pM).\n", | ||
| 252 | vid, curr_neigh->addr); | ||
| 253 | else if ((curr_neigh) && (new_neigh)) | ||
| 254 | bat_dbg(DBG_ROUTES, bat_priv, | ||
| 255 | "Changing mesh exit point on vid: %d from %pM to %pM.\n", | ||
| 256 | vid, curr_neigh->addr, new_neigh->addr); | ||
| 257 | else if ((!curr_neigh) && (new_neigh)) | ||
| 258 | bat_dbg(DBG_ROUTES, bat_priv, | ||
| 259 | "Setting mesh exit point on vid: %d to %pM.\n", | ||
| 260 | vid, new_neigh->addr); | ||
| 261 | |||
| 262 | if (curr_neigh) | ||
| 263 | softif_neigh_free_ref(curr_neigh); | ||
| 264 | |||
| 265 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
| 266 | |||
| 267 | out: | ||
| 268 | if (softif_neigh_vid) | ||
| 269 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
| 270 | } | ||
| 271 | |||
| 272 | static void softif_neigh_vid_deselect(struct bat_priv *bat_priv, | ||
| 273 | struct softif_neigh_vid *softif_neigh_vid) | ||
| 274 | { | ||
| 275 | struct softif_neigh *curr_neigh; | ||
| 276 | struct softif_neigh *softif_neigh = NULL, *softif_neigh_tmp; | ||
| 277 | struct hard_iface *primary_if = NULL; | ||
| 278 | struct hlist_node *node; | ||
| 279 | |||
| 280 | primary_if = primary_if_get_selected(bat_priv); | ||
| 281 | if (!primary_if) | ||
| 282 | goto out; | ||
| 283 | |||
| 284 | /* find new softif_neigh immediately to avoid temporary loops */ | ||
| 285 | rcu_read_lock(); | ||
| 286 | curr_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); | ||
| 287 | |||
| 288 | hlist_for_each_entry_rcu(softif_neigh_tmp, node, | ||
| 289 | &softif_neigh_vid->softif_neigh_list, | ||
| 290 | list) { | ||
| 291 | if (softif_neigh_tmp == curr_neigh) | ||
| 292 | continue; | ||
| 293 | |||
| 294 | /* we got a neighbor but its mac is 'bigger' than ours */ | ||
| 295 | if (memcmp(primary_if->net_dev->dev_addr, | ||
| 296 | softif_neigh_tmp->addr, ETH_ALEN) < 0) | ||
| 297 | continue; | ||
| 298 | |||
| 299 | if (!atomic_inc_not_zero(&softif_neigh_tmp->refcount)) | ||
| 300 | continue; | ||
| 301 | |||
| 302 | softif_neigh = softif_neigh_tmp; | ||
| 303 | goto unlock; | ||
| 304 | } | ||
| 305 | |||
| 306 | unlock: | ||
| 307 | rcu_read_unlock(); | ||
| 308 | out: | ||
| 309 | softif_neigh_vid_select(bat_priv, softif_neigh, softif_neigh_vid->vid); | ||
| 310 | |||
| 311 | if (primary_if) | ||
| 312 | hardif_free_ref(primary_if); | ||
| 313 | if (softif_neigh) | ||
| 314 | softif_neigh_free_ref(softif_neigh); | ||
| 315 | } | ||
| 316 | |||
| 317 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) | ||
| 318 | { | ||
| 319 | struct net_device *net_dev = (struct net_device *)seq->private; | ||
| 320 | struct bat_priv *bat_priv = netdev_priv(net_dev); | ||
| 321 | struct softif_neigh_vid *softif_neigh_vid; | ||
| 322 | struct softif_neigh *softif_neigh; | ||
| 323 | struct hard_iface *primary_if; | ||
| 324 | struct hlist_node *node, *node_tmp; | ||
| 325 | struct softif_neigh *curr_softif_neigh; | ||
| 326 | int ret = 0, last_seen_secs, last_seen_msecs; | ||
| 327 | |||
| 328 | primary_if = primary_if_get_selected(bat_priv); | ||
| 329 | if (!primary_if) { | ||
| 330 | ret = seq_printf(seq, | ||
| 331 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
| 332 | net_dev->name); | ||
| 333 | goto out; | ||
| 334 | } | ||
| 335 | |||
| 336 | if (primary_if->if_status != IF_ACTIVE) { | ||
| 337 | ret = seq_printf(seq, | ||
| 338 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
| 339 | net_dev->name); | ||
| 340 | goto out; | ||
| 341 | } | ||
| 342 | |||
| 343 | seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); | ||
| 344 | |||
| 345 | rcu_read_lock(); | ||
| 346 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
| 347 | &bat_priv->softif_neigh_vids, list) { | ||
| 348 | seq_printf(seq, " %-15s %s on vid: %d\n", | ||
| 349 | "Originator", "last-seen", softif_neigh_vid->vid); | ||
| 350 | |||
| 351 | curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
| 352 | |||
| 353 | hlist_for_each_entry_rcu(softif_neigh, node_tmp, | ||
| 354 | &softif_neigh_vid->softif_neigh_list, | ||
| 355 | list) { | ||
| 356 | last_seen_secs = jiffies_to_msecs(jiffies - | ||
| 357 | softif_neigh->last_seen) / 1000; | ||
| 358 | last_seen_msecs = jiffies_to_msecs(jiffies - | ||
| 359 | softif_neigh->last_seen) % 1000; | ||
| 360 | seq_printf(seq, "%s %pM %3i.%03is\n", | ||
| 361 | curr_softif_neigh == softif_neigh | ||
| 362 | ? "=>" : " ", softif_neigh->addr, | ||
| 363 | last_seen_secs, last_seen_msecs); | ||
| 364 | } | ||
| 365 | |||
| 366 | if (curr_softif_neigh) | ||
| 367 | softif_neigh_free_ref(curr_softif_neigh); | ||
| 368 | |||
| 369 | seq_printf(seq, "\n"); | ||
| 370 | } | ||
| 371 | rcu_read_unlock(); | ||
| 372 | |||
| 373 | out: | ||
| 374 | if (primary_if) | ||
| 375 | hardif_free_ref(primary_if); | ||
| 376 | return ret; | ||
| 377 | } | ||
| 378 | |||
| 379 | void softif_neigh_purge(struct bat_priv *bat_priv) | ||
| 380 | { | ||
| 381 | struct softif_neigh *softif_neigh, *curr_softif_neigh; | ||
| 382 | struct softif_neigh_vid *softif_neigh_vid; | ||
| 383 | struct hlist_node *node, *node_tmp, *node_tmp2; | ||
| 384 | int do_deselect; | ||
| 385 | |||
| 386 | rcu_read_lock(); | ||
| 387 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
| 388 | &bat_priv->softif_neigh_vids, list) { | ||
| 389 | if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) | ||
| 390 | continue; | ||
| 391 | |||
| 392 | curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
| 393 | do_deselect = 0; | ||
| 394 | |||
| 395 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
| 396 | hlist_for_each_entry_safe(softif_neigh, node_tmp, node_tmp2, | ||
| 397 | &softif_neigh_vid->softif_neigh_list, | ||
| 398 | list) { | ||
| 399 | if ((!has_timed_out(softif_neigh->last_seen, | ||
| 400 | SOFTIF_NEIGH_TIMEOUT)) && | ||
| 401 | (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) | ||
| 402 | continue; | ||
| 403 | |||
| 404 | if (curr_softif_neigh == softif_neigh) { | ||
| 405 | bat_dbg(DBG_ROUTES, bat_priv, | ||
| 406 | "Current mesh exit point on vid: %d '%pM' vanished.\n", | ||
| 407 | softif_neigh_vid->vid, | ||
| 408 | softif_neigh->addr); | ||
| 409 | do_deselect = 1; | ||
| 410 | } | ||
| 411 | |||
| 412 | hlist_del_rcu(&softif_neigh->list); | ||
| 413 | softif_neigh_free_ref(softif_neigh); | ||
| 414 | } | ||
| 415 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
| 416 | |||
| 417 | /* soft_neigh_vid_deselect() needs to acquire the | ||
| 418 | * softif_neigh_lock */ | ||
| 419 | if (do_deselect) | ||
| 420 | softif_neigh_vid_deselect(bat_priv, softif_neigh_vid); | ||
| 421 | |||
| 422 | if (curr_softif_neigh) | ||
| 423 | softif_neigh_free_ref(curr_softif_neigh); | ||
| 424 | |||
| 425 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
| 426 | } | ||
| 427 | rcu_read_unlock(); | ||
| 428 | |||
| 429 | spin_lock_bh(&bat_priv->softif_neigh_vid_lock); | ||
| 430 | hlist_for_each_entry_safe(softif_neigh_vid, node, node_tmp, | ||
| 431 | &bat_priv->softif_neigh_vids, list) { | ||
| 432 | if (!hlist_empty(&softif_neigh_vid->softif_neigh_list)) | ||
| 433 | continue; | ||
| 434 | |||
| 435 | hlist_del_rcu(&softif_neigh_vid->list); | ||
| 436 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
| 437 | } | ||
| 438 | spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); | ||
| 439 | |||
| 440 | } | ||
| 441 | |||
| 442 | static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | ||
| 443 | short vid) | ||
| 444 | { | ||
| 445 | struct bat_priv *bat_priv = netdev_priv(dev); | ||
| 446 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | ||
| 447 | struct batman_ogm_packet *batman_ogm_packet; | ||
| 448 | struct softif_neigh *softif_neigh = NULL; | ||
| 449 | struct hard_iface *primary_if = NULL; | ||
| 450 | struct softif_neigh *curr_softif_neigh = NULL; | ||
| 451 | |||
| 452 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) | ||
| 453 | batman_ogm_packet = (struct batman_ogm_packet *) | ||
| 454 | (skb->data + ETH_HLEN + VLAN_HLEN); | ||
| 455 | else | ||
| 456 | batman_ogm_packet = (struct batman_ogm_packet *) | ||
| 457 | (skb->data + ETH_HLEN); | ||
| 458 | |||
| 459 | if (batman_ogm_packet->header.version != COMPAT_VERSION) | ||
| 460 | goto out; | ||
| 461 | |||
| 462 | if (batman_ogm_packet->header.packet_type != BAT_OGM) | ||
| 463 | goto out; | ||
| 464 | |||
| 465 | if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) | ||
| 466 | goto out; | ||
| 467 | |||
| 468 | if (is_my_mac(batman_ogm_packet->orig)) | ||
| 469 | goto out; | ||
| 470 | |||
| 471 | softif_neigh = softif_neigh_get(bat_priv, batman_ogm_packet->orig, vid); | ||
| 472 | if (!softif_neigh) | ||
| 473 | goto out; | ||
| 474 | |||
| 475 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); | ||
| 476 | if (curr_softif_neigh == softif_neigh) | ||
| 477 | goto out; | ||
| 478 | |||
| 479 | primary_if = primary_if_get_selected(bat_priv); | ||
| 480 | if (!primary_if) | ||
| 481 | goto out; | ||
| 482 | |||
| 483 | /* we got a neighbor but its mac is 'bigger' than ours */ | ||
| 484 | if (memcmp(primary_if->net_dev->dev_addr, | ||
| 485 | softif_neigh->addr, ETH_ALEN) < 0) | ||
| 486 | goto out; | ||
| 487 | |||
| 488 | /* close own batX device and use softif_neigh as exit node */ | ||
| 489 | if (!curr_softif_neigh) { | ||
| 490 | softif_neigh_vid_select(bat_priv, softif_neigh, vid); | ||
| 491 | goto out; | ||
| 492 | } | ||
| 493 | |||
| 494 | /* switch to new 'smallest neighbor' */ | ||
| 495 | if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0) | ||
| 496 | softif_neigh_vid_select(bat_priv, softif_neigh, vid); | ||
| 497 | |||
| 498 | out: | ||
| 499 | kfree_skb(skb); | ||
| 500 | if (softif_neigh) | ||
| 501 | softif_neigh_free_ref(softif_neigh); | ||
| 502 | if (curr_softif_neigh) | ||
| 503 | softif_neigh_free_ref(curr_softif_neigh); | ||
| 504 | if (primary_if) | ||
| 505 | hardif_free_ref(primary_if); | ||
| 506 | return; | ||
| 507 | } | ||
| 508 | |||
| 509 | static int interface_open(struct net_device *dev) | 76 | static int interface_open(struct net_device *dev) |
| 510 | { | 77 | { |
| 511 | netif_start_queue(dev); | 78 | netif_start_queue(dev); |
| @@ -562,7 +129,6 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
| 562 | struct hard_iface *primary_if = NULL; | 129 | struct hard_iface *primary_if = NULL; |
| 563 | struct bcast_packet *bcast_packet; | 130 | struct bcast_packet *bcast_packet; |
| 564 | struct vlan_ethhdr *vhdr; | 131 | struct vlan_ethhdr *vhdr; |
| 565 | struct softif_neigh *curr_softif_neigh = NULL; | ||
| 566 | unsigned int header_len = 0; | 132 | unsigned int header_len = 0; |
| 567 | int data_len = skb->len, ret; | 133 | int data_len = skb->len, ret; |
| 568 | short vid = -1; | 134 | short vid = -1; |
| @@ -583,17 +149,8 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
| 583 | 149 | ||
| 584 | /* fall through */ | 150 | /* fall through */ |
| 585 | case ETH_P_BATMAN: | 151 | case ETH_P_BATMAN: |
| 586 | softif_batman_recv(skb, soft_iface, vid); | ||
| 587 | goto end; | ||
| 588 | } | ||
| 589 | |||
| 590 | /** | ||
| 591 | * if we have a another chosen mesh exit node in range | ||
| 592 | * it will transport the packets to the mesh | ||
| 593 | */ | ||
| 594 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); | ||
| 595 | if (curr_softif_neigh) | ||
| 596 | goto dropped; | 152 | goto dropped; |
| 153 | } | ||
| 597 | 154 | ||
| 598 | /* Register the client MAC in the transtable */ | 155 | /* Register the client MAC in the transtable */ |
| 599 | tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); | 156 | tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); |
| @@ -675,8 +232,6 @@ dropped: | |||
| 675 | dropped_freed: | 232 | dropped_freed: |
| 676 | bat_priv->stats.tx_dropped++; | 233 | bat_priv->stats.tx_dropped++; |
| 677 | end: | 234 | end: |
| 678 | if (curr_softif_neigh) | ||
| 679 | softif_neigh_free_ref(curr_softif_neigh); | ||
| 680 | if (primary_if) | 235 | if (primary_if) |
| 681 | hardif_free_ref(primary_if); | 236 | hardif_free_ref(primary_if); |
| 682 | return NETDEV_TX_OK; | 237 | return NETDEV_TX_OK; |
| @@ -687,12 +242,9 @@ void interface_rx(struct net_device *soft_iface, | |||
| 687 | int hdr_size) | 242 | int hdr_size) |
| 688 | { | 243 | { |
| 689 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 244 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
| 690 | struct unicast_packet *unicast_packet; | ||
| 691 | struct ethhdr *ethhdr; | 245 | struct ethhdr *ethhdr; |
| 692 | struct vlan_ethhdr *vhdr; | 246 | struct vlan_ethhdr *vhdr; |
| 693 | struct softif_neigh *curr_softif_neigh = NULL; | ||
| 694 | short vid = -1; | 247 | short vid = -1; |
| 695 | int ret; | ||
| 696 | 248 | ||
| 697 | /* check if enough space is available for pulling, and pull */ | 249 | /* check if enough space is available for pulling, and pull */ |
| 698 | if (!pskb_may_pull(skb, hdr_size)) | 250 | if (!pskb_may_pull(skb, hdr_size)) |
| @@ -716,30 +268,6 @@ void interface_rx(struct net_device *soft_iface, | |||
| 716 | goto dropped; | 268 | goto dropped; |
| 717 | } | 269 | } |
| 718 | 270 | ||
| 719 | /** | ||
| 720 | * if we have a another chosen mesh exit node in range | ||
| 721 | * it will transport the packets to the non-mesh network | ||
| 722 | */ | ||
| 723 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); | ||
| 724 | if (curr_softif_neigh) { | ||
| 725 | skb_push(skb, hdr_size); | ||
| 726 | unicast_packet = (struct unicast_packet *)skb->data; | ||
| 727 | |||
| 728 | if ((unicast_packet->header.packet_type != BAT_UNICAST) && | ||
| 729 | (unicast_packet->header.packet_type != BAT_UNICAST_FRAG)) | ||
| 730 | goto dropped; | ||
| 731 | |||
| 732 | skb_reset_mac_header(skb); | ||
| 733 | |||
| 734 | memcpy(unicast_packet->dest, | ||
| 735 | curr_softif_neigh->addr, ETH_ALEN); | ||
| 736 | ret = route_unicast_packet(skb, recv_if); | ||
| 737 | if (ret == NET_RX_DROP) | ||
| 738 | goto dropped; | ||
| 739 | |||
| 740 | goto out; | ||
| 741 | } | ||
| 742 | |||
| 743 | /* skb->dev & skb->pkt_type are set here */ | 271 | /* skb->dev & skb->pkt_type are set here */ |
| 744 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) | 272 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) |
| 745 | goto dropped; | 273 | goto dropped; |
| @@ -765,8 +293,6 @@ void interface_rx(struct net_device *soft_iface, | |||
| 765 | dropped: | 293 | dropped: |
| 766 | kfree_skb(skb); | 294 | kfree_skb(skb); |
| 767 | out: | 295 | out: |
| 768 | if (curr_softif_neigh) | ||
| 769 | softif_neigh_free_ref(curr_softif_neigh); | ||
| 770 | return; | 296 | return; |
| 771 | } | 297 | } |
| 772 | 298 | ||
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h index 756eab5b8dd4..020300673884 100644 --- a/net/batman-adv/soft-interface.h +++ b/net/batman-adv/soft-interface.h | |||
| @@ -23,8 +23,6 @@ | |||
| 23 | #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_ | 23 | #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_ |
| 24 | 24 | ||
| 25 | int my_skb_head_push(struct sk_buff *skb, unsigned int len); | 25 | int my_skb_head_push(struct sk_buff *skb, unsigned int len); |
| 26 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset); | ||
| 27 | void softif_neigh_purge(struct bat_priv *bat_priv); | ||
| 28 | void interface_rx(struct net_device *soft_iface, | 26 | void interface_rx(struct net_device *soft_iface, |
| 29 | struct sk_buff *skb, struct hard_iface *recv_if, | 27 | struct sk_buff *skb, struct hard_iface *recv_if, |
| 30 | int hdr_size); | 28 | int hdr_size); |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 24c8a31a3d91..feac2f4030c8 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
| @@ -174,7 +174,6 @@ struct bat_priv { | |||
| 174 | struct hlist_head forw_bat_list; | 174 | struct hlist_head forw_bat_list; |
| 175 | struct hlist_head forw_bcast_list; | 175 | struct hlist_head forw_bcast_list; |
| 176 | struct hlist_head gw_list; | 176 | struct hlist_head gw_list; |
| 177 | struct hlist_head softif_neigh_vids; | ||
| 178 | struct list_head tt_changes_list; /* tracks changes in a OGM int */ | 177 | struct list_head tt_changes_list; /* tracks changes in a OGM int */ |
| 179 | struct list_head vis_send_list; | 178 | struct list_head vis_send_list; |
| 180 | struct hashtable_t *orig_hash; | 179 | struct hashtable_t *orig_hash; |
| @@ -191,8 +190,6 @@ struct bat_priv { | |||
| 191 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ | 190 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ |
| 192 | spinlock_t vis_hash_lock; /* protects vis_hash */ | 191 | spinlock_t vis_hash_lock; /* protects vis_hash */ |
| 193 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ | 192 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ |
| 194 | spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ | ||
| 195 | spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */ | ||
| 196 | atomic_t num_local_tt; | 193 | atomic_t num_local_tt; |
| 197 | /* Checksum of the local table, recomputed before sending a new OGM */ | 194 | /* Checksum of the local table, recomputed before sending a new OGM */ |
| 198 | atomic_t tt_crc; | 195 | atomic_t tt_crc; |
| @@ -327,24 +324,6 @@ struct recvlist_node { | |||
| 327 | uint8_t mac[ETH_ALEN]; | 324 | uint8_t mac[ETH_ALEN]; |
| 328 | }; | 325 | }; |
| 329 | 326 | ||
| 330 | struct softif_neigh_vid { | ||
| 331 | struct hlist_node list; | ||
| 332 | struct bat_priv *bat_priv; | ||
| 333 | short vid; | ||
| 334 | atomic_t refcount; | ||
| 335 | struct softif_neigh __rcu *softif_neigh; | ||
| 336 | struct rcu_head rcu; | ||
| 337 | struct hlist_head softif_neigh_list; | ||
| 338 | }; | ||
| 339 | |||
| 340 | struct softif_neigh { | ||
| 341 | struct hlist_node list; | ||
| 342 | uint8_t addr[ETH_ALEN]; | ||
| 343 | unsigned long last_seen; | ||
| 344 | atomic_t refcount; | ||
| 345 | struct rcu_head rcu; | ||
| 346 | }; | ||
| 347 | |||
| 348 | struct bat_algo_ops { | 327 | struct bat_algo_ops { |
| 349 | struct hlist_node list; | 328 | struct hlist_node list; |
| 350 | char *name; | 329 | char *name; |
