diff options
author | Rémi Denis-Courmont <remi.denis-courmont@nokia.com> | 2009-10-13 20:48:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-14 18:04:17 -0400 |
commit | f062f41d06575744b9eaf725eef8a5d3b5f5b7ca (patch) | |
tree | 1ee1c966a2810c1f2a7274a51dba0387861efc68 /net/phonet/pn_dev.c | |
parent | 55748ac0468134a89bc55aed6a9691e320caa8a9 (diff) |
Phonet: routing table Netlink interface
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/phonet/pn_dev.c')
-rw-r--r-- | net/phonet/pn_dev.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 71fffa587783..6d64fda1afc9 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c | |||
@@ -240,6 +240,27 @@ static int phonet_device_autoconf(struct net_device *dev) | |||
240 | return 0; | 240 | return 0; |
241 | } | 241 | } |
242 | 242 | ||
243 | static void phonet_route_autodel(struct net_device *dev) | ||
244 | { | ||
245 | struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); | ||
246 | unsigned i; | ||
247 | DECLARE_BITMAP(deleted, 64); | ||
248 | |||
249 | /* Remove left-over Phonet routes */ | ||
250 | bitmap_zero(deleted, 64); | ||
251 | spin_lock_bh(&pnn->routes.lock); | ||
252 | for (i = 0; i < 64; i++) | ||
253 | if (dev == pnn->routes.table[i]) { | ||
254 | set_bit(i, deleted); | ||
255 | pnn->routes.table[i] = NULL; | ||
256 | dev_put(dev); | ||
257 | } | ||
258 | spin_unlock_bh(&pnn->routes.lock); | ||
259 | for (i = find_first_bit(deleted, 64); i < 64; | ||
260 | i = find_next_bit(deleted, 64, i + 1)) | ||
261 | rtm_phonet_notify(RTM_DELROUTE, dev, i); | ||
262 | } | ||
263 | |||
243 | /* notify Phonet of device events */ | 264 | /* notify Phonet of device events */ |
244 | static int phonet_device_notify(struct notifier_block *me, unsigned long what, | 265 | static int phonet_device_notify(struct notifier_block *me, unsigned long what, |
245 | void *arg) | 266 | void *arg) |
@@ -253,6 +274,7 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what, | |||
253 | break; | 274 | break; |
254 | case NETDEV_UNREGISTER: | 275 | case NETDEV_UNREGISTER: |
255 | phonet_device_destroy(dev); | 276 | phonet_device_destroy(dev); |
277 | phonet_route_autodel(dev); | ||
256 | break; | 278 | break; |
257 | } | 279 | } |
258 | return 0; | 280 | return 0; |
@@ -287,10 +309,19 @@ static void phonet_exit_net(struct net *net) | |||
287 | { | 309 | { |
288 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 310 | struct phonet_net *pnn = net_generic(net, phonet_net_id); |
289 | struct net_device *dev; | 311 | struct net_device *dev; |
312 | unsigned i; | ||
290 | 313 | ||
291 | rtnl_lock(); | 314 | rtnl_lock(); |
292 | for_each_netdev(net, dev) | 315 | for_each_netdev(net, dev) |
293 | phonet_device_destroy(dev); | 316 | phonet_device_destroy(dev); |
317 | |||
318 | for (i = 0; i < 64; i++) { | ||
319 | dev = pnn->routes.table[i]; | ||
320 | if (dev) { | ||
321 | rtm_phonet_notify(RTM_DELROUTE, dev, i); | ||
322 | dev_put(dev); | ||
323 | } | ||
324 | } | ||
294 | rtnl_unlock(); | 325 | rtnl_unlock(); |
295 | 326 | ||
296 | proc_net_remove(net, "phonet"); | 327 | proc_net_remove(net, "phonet"); |