11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Generic parts 31da177e4SLinus Torvalds * Linux ethernet bridge 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Authors: 61da177e4SLinus Torvalds * Lennert Buytenhek <buytenh@gnu.org> 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 91da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 101da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 111da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include <linux/module.h> 151da177e4SLinus Torvalds #include <linux/kernel.h> 161da177e4SLinus Torvalds #include <linux/netdevice.h> 171da177e4SLinus Torvalds #include <linux/etherdevice.h> 181da177e4SLinus Torvalds #include <linux/init.h> 19cf0f02d0SStephen Hemminger #include <linux/llc.h> 20cf0f02d0SStephen Hemminger #include <net/llc.h> 217c85fbf0SPatrick McHardy #include <net/stp.h> 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds #include "br_private.h" 241da177e4SLinus Torvalds 253db05feaSHerbert Xu int (*br_should_route_hook)(struct sk_buff *skb); 261da177e4SLinus Torvalds 277c85fbf0SPatrick McHardy static const struct stp_proto br_stp_proto = { 287c85fbf0SPatrick McHardy .rcv = br_stp_rcv, 297c85fbf0SPatrick McHardy }; 30cf0f02d0SStephen Hemminger 31712d6954SAlexey Dobriyan static struct pernet_operations br_net_ops = { 32712d6954SAlexey Dobriyan .exit = br_net_exit, 33712d6954SAlexey Dobriyan }; 34712d6954SAlexey Dobriyan 351da177e4SLinus Torvalds static int __init br_init(void) 361da177e4SLinus Torvalds { 37c0909713SStephen Hemminger int err; 38c0909713SStephen Hemminger 397c85fbf0SPatrick McHardy err = stp_proto_register(&br_stp_proto); 407c85fbf0SPatrick McHardy if (err < 0) { 41cf0f02d0SStephen Hemminger printk(KERN_ERR "bridge: can't register sap for STP\n"); 427c85fbf0SPatrick McHardy return err; 43cf0f02d0SStephen Hemminger } 44cf0f02d0SStephen Hemminger 4587a596e0SAkinobu Mita err = br_fdb_init(); 4687a596e0SAkinobu Mita if (err) 4717efdd45SPavel Emelyanov goto err_out; 481da177e4SLinus Torvalds 49712d6954SAlexey Dobriyan err = register_pernet_subsys(&br_net_ops); 50c0909713SStephen Hemminger if (err) 51c0909713SStephen Hemminger goto err_out1; 52c0909713SStephen Hemminger 53712d6954SAlexey Dobriyan err = br_netfilter_init(); 54c0909713SStephen Hemminger if (err) 55c0909713SStephen Hemminger goto err_out2; 56c0909713SStephen Hemminger 57712d6954SAlexey Dobriyan err = register_netdevice_notifier(&br_device_notifier); 5832fe21c0SThomas Graf if (err) 5932fe21c0SThomas Graf goto err_out3; 6032fe21c0SThomas Graf 61712d6954SAlexey Dobriyan err = br_netlink_init(); 62712d6954SAlexey Dobriyan if (err) 63712d6954SAlexey Dobriyan goto err_out4; 64712d6954SAlexey Dobriyan 651da177e4SLinus Torvalds brioctl_set(br_ioctl_deviceless_stub); 661da177e4SLinus Torvalds br_handle_frame_hook = br_handle_frame; 671da177e4SLinus Torvalds 68da678292SMichał Mirosław #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) 69da678292SMichał Mirosław br_fdb_test_addr_hook = br_fdb_test_addr; 70da678292SMichał Mirosław #endif 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds return 0; 73712d6954SAlexey Dobriyan err_out4: 7432fe21c0SThomas Graf unregister_netdevice_notifier(&br_device_notifier); 75712d6954SAlexey Dobriyan err_out3: 76c0909713SStephen Hemminger br_netfilter_fini(); 77712d6954SAlexey Dobriyan err_out2: 78712d6954SAlexey Dobriyan unregister_pernet_subsys(&br_net_ops); 79c0909713SStephen Hemminger err_out1: 8017efdd45SPavel Emelyanov br_fdb_fini(); 8117efdd45SPavel Emelyanov err_out: 827c85fbf0SPatrick McHardy stp_proto_unregister(&br_stp_proto); 83c0909713SStephen Hemminger return err; 841da177e4SLinus Torvalds } 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds static void __exit br_deinit(void) 871da177e4SLinus Torvalds { 887c85fbf0SPatrick McHardy stp_proto_unregister(&br_stp_proto); 89cf0f02d0SStephen Hemminger 9011dc1f36SStephen Hemminger br_netlink_fini(); 911da177e4SLinus Torvalds unregister_netdevice_notifier(&br_device_notifier); 921da177e4SLinus Torvalds brioctl_set(NULL); 931da177e4SLinus Torvalds 94712d6954SAlexey Dobriyan unregister_pernet_subsys(&br_net_ops); 951da177e4SLinus Torvalds 96473c22d7SJesper Dangaard Brouer rcu_barrier(); /* Wait for completion of call_rcu()'s */ 971da177e4SLinus Torvalds 98d69efb16SBodo Stroesser br_netfilter_fini(); 99da678292SMichał Mirosław #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) 100da678292SMichał Mirosław br_fdb_test_addr_hook = NULL; 101da678292SMichał Mirosław #endif 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds br_handle_frame_hook = NULL; 1041da177e4SLinus Torvalds br_fdb_fini(); 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds EXPORT_SYMBOL(br_should_route_hook); 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds module_init(br_init) 1101da177e4SLinus Torvalds module_exit(br_deinit) 1111da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 1128cbb512eSStephen Hemminger MODULE_VERSION(BR_VERSION); 113