1from ryu.services.protocols.bgp.rtconf.base import ConfWithStats 2from ryu.services.protocols.bgp.rtconf.common import CommonConfListener 3from ryu.services.protocols.bgp.rtconf.neighbors import NeighborsConfListener 4from ryu.services.protocols.bgp.rtconf import vrfs 5from ryu.services.protocols.bgp.rtconf.vrfs import VrfConf 6from ryu.services.protocols.bgp.rtconf.vrfs import VrfsConfListener 7 8import logging 9 10LOG = logging.getLogger('bgpspeaker.core_managers.table_mixin') 11 12 13class ConfigurationManager(CommonConfListener, VrfsConfListener, 14 NeighborsConfListener): 15 def __init__(self, core_service, common_conf, vrfs_conf, neighbors_conf): 16 self._signal_bus = core_service.signal_bus 17 self._common_config = common_conf 18 self._peer_manager = core_service.peer_manager 19 self._table_manager = core_service.table_manager 20 self._rt_manager = core_service.rt_manager 21 CommonConfListener.__init__(self, common_conf) 22 VrfsConfListener.__init__(self, vrfs_conf) 23 NeighborsConfListener.__init__(self, neighbors_conf) 24 25 def on_update_common_conf(self, evt): 26 raise NotImplementedError() 27 28 def on_add_neighbor_conf(self, evt): 29 neigh_conf = evt.value 30 self._peer_manager.add_peer(neigh_conf, self._common_config) 31 32 def on_remove_neighbor_conf(self, evt): 33 neigh_conf = evt.value 34 self._peer_manager.remove_peer(neigh_conf) 35 36 def on_chg_vrf_conf(self, evt): 37 evt_value = evt.value 38 vrf_conf = evt.src 39 new_imp_rts, removed_imp_rts, import_maps, re_export, re_import = \ 40 evt_value 41 route_family = vrf_conf.route_family 42 vrf_table = self._table_manager.get_vrf_table( 43 vrf_conf.route_dist, route_family 44 ) 45 assert vrf_table 46 47 # If we have new import RTs we have to update RTC table and make route 48 # refresh request to peers not participating in RT address-family 49 self._table_manager.update_vrf_table_links( 50 vrf_table, new_imp_rts, removed_imp_rts 51 ) 52 53 # If other properties of VRF changed we re-install local paths. 54 if re_export: 55 self._table_manager.re_install_net_ctrl_paths(vrf_table) 56 57 # We have to withdraw paths that do not have any RT that are or 58 # interest 59 vrf_table.clean_uninteresting_paths() 60 if import_maps is not None: 61 vrf_table.init_import_maps(import_maps) 62 changed_dests = vrf_table.apply_import_maps() 63 for dest in changed_dests: 64 self._signal_bus.dest_changed(dest) 65 66 # import new rts 67 if re_import: 68 LOG.debug( 69 "RE-importing prefixes from VPN table to VRF %r", vrf_table 70 ) 71 self._table_manager.import_all_vpn_paths_to_vrf(vrf_table) 72 else: 73 self._table_manager.import_all_vpn_paths_to_vrf( 74 vrf_table, new_imp_rts 75 ) 76 77 # Update local/global RT NLRIs 78 self._rt_manager.update_local_rt_nlris() 79 80 def on_remove_vrf_conf(self, evt): 81 """Removes VRF table associated with given `vrf_conf`. 82 83 Cleans up other links to this table as well. 84 """ 85 vrf_conf = evt.value 86 # Detach VrfConf change listener. 87 vrf_conf.remove_listener(VrfConf.VRF_CHG_EVT, self.on_chg_vrf_conf) 88 89 self._table_manager.remove_vrf_by_vrf_conf(vrf_conf) 90 91 # Update local RT NLRIs 92 self._rt_manager.update_local_rt_nlris() 93 94 self._signal_bus.vrf_removed(vrf_conf.route_dist) 95 96 # Remove AttributeMaps under the removed vrf 97 rd = vrf_conf.route_dist 98 rf = vrf_conf.route_family 99 peers = self._peer_manager.iterpeers 100 for peer in peers: 101 key = ':'.join([rd, rf]) 102 peer.attribute_maps.pop(key, None) 103 104 def on_add_vrf_conf(self, evt): 105 """Event handler for new VrfConf. 106 107 Creates a VrfTable to store routing information related to new Vrf. 108 Also arranges for related paths to be imported to this VrfTable. 109 """ 110 vrf_conf = evt.value 111 route_family = vrf_conf.route_family 112 assert route_family in vrfs.SUPPORTED_VRF_RF 113 # Create VRF table with given configuration. 114 vrf_table = self._table_manager.create_and_link_vrf_table(vrf_conf) 115 116 # Attach VrfConf change listeners. 117 vrf_conf.add_listener(ConfWithStats.UPDATE_STATS_LOG_ENABLED_EVT, 118 self.on_stats_config_change) 119 vrf_conf.add_listener(ConfWithStats.UPDATE_STATS_TIME_EVT, 120 self.on_stats_config_change) 121 vrf_conf.add_listener(VrfConf.VRF_CHG_EVT, self.on_chg_vrf_conf) 122 123 # Import paths from VPN table that match this VRF/VPN. 124 self._table_manager.import_all_vpn_paths_to_vrf(vrf_table) 125 126 # Update local RT NLRIs 127 self._rt_manager.update_local_rt_nlris() 128 self._signal_bus.vrf_added(vrf_conf) 129 130 def on_stats_config_change(self, evt): 131 vrf_conf = evt.src 132 self._signal_bus.stats_config_changed(vrf_conf) 133