diff options
Diffstat (limited to 'net/ipv4/ip_vti.c')
-rw-r--r-- | net/ipv4/ip_vti.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index a917903d5e97..cc701fa70b12 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -557,6 +557,33 @@ static struct rtnl_link_ops vti_link_ops __read_mostly = { | |||
557 | .get_link_net = ip_tunnel_get_link_net, | 557 | .get_link_net = ip_tunnel_get_link_net, |
558 | }; | 558 | }; |
559 | 559 | ||
560 | static bool is_vti_tunnel(const struct net_device *dev) | ||
561 | { | ||
562 | return dev->netdev_ops == &vti_netdev_ops; | ||
563 | } | ||
564 | |||
565 | static int vti_device_event(struct notifier_block *unused, | ||
566 | unsigned long event, void *ptr) | ||
567 | { | ||
568 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | ||
569 | struct ip_tunnel *tunnel = netdev_priv(dev); | ||
570 | |||
571 | if (!is_vti_tunnel(dev)) | ||
572 | return NOTIFY_DONE; | ||
573 | |||
574 | switch (event) { | ||
575 | case NETDEV_DOWN: | ||
576 | if (!net_eq(tunnel->net, dev_net(dev))) | ||
577 | xfrm_garbage_collect(tunnel->net); | ||
578 | break; | ||
579 | } | ||
580 | return NOTIFY_DONE; | ||
581 | } | ||
582 | |||
583 | static struct notifier_block vti_notifier_block __read_mostly = { | ||
584 | .notifier_call = vti_device_event, | ||
585 | }; | ||
586 | |||
560 | static int __init vti_init(void) | 587 | static int __init vti_init(void) |
561 | { | 588 | { |
562 | const char *msg; | 589 | const char *msg; |
@@ -564,6 +591,8 @@ static int __init vti_init(void) | |||
564 | 591 | ||
565 | pr_info("IPv4 over IPsec tunneling driver\n"); | 592 | pr_info("IPv4 over IPsec tunneling driver\n"); |
566 | 593 | ||
594 | register_netdevice_notifier(&vti_notifier_block); | ||
595 | |||
567 | msg = "tunnel device"; | 596 | msg = "tunnel device"; |
568 | err = register_pernet_device(&vti_net_ops); | 597 | err = register_pernet_device(&vti_net_ops); |
569 | if (err < 0) | 598 | if (err < 0) |
@@ -596,6 +625,7 @@ xfrm_proto_ah_failed: | |||
596 | xfrm_proto_esp_failed: | 625 | xfrm_proto_esp_failed: |
597 | unregister_pernet_device(&vti_net_ops); | 626 | unregister_pernet_device(&vti_net_ops); |
598 | pernet_dev_failed: | 627 | pernet_dev_failed: |
628 | unregister_netdevice_notifier(&vti_notifier_block); | ||
599 | pr_err("vti init: failed to register %s\n", msg); | 629 | pr_err("vti init: failed to register %s\n", msg); |
600 | return err; | 630 | return err; |
601 | } | 631 | } |
@@ -607,6 +637,7 @@ static void __exit vti_fini(void) | |||
607 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); | 637 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); |
608 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); | 638 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); |
609 | unregister_pernet_device(&vti_net_ops); | 639 | unregister_pernet_device(&vti_net_ops); |
640 | unregister_netdevice_notifier(&vti_notifier_block); | ||
610 | } | 641 | } |
611 | 642 | ||
612 | module_init(vti_init); | 643 | module_init(vti_init); |