Example #1
0
def ryu(routerid, asn, peerip, peerport, peeras):
    import eventlet
    from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker
    eventlet.monkey_patch()  # BGPSpeaker needs sockets patched

    def dump_remote_best_path_change(event):
        print('the best path changed:', event.remote_as, event.prefix,
              event.nexthop, event.is_withdraw)

    def detect_peer_down(remote_ip, remote_as):
        print('Peer down:', remote_ip, remote_as)

    speaker = BGPSpeaker(
        as_number=int(args.asn),
        router_id=args.router_id,
        best_path_change_handler=dump_remote_best_path_change,
        peer_down_handler=detect_peer_down)

    # XXX need to fix port arg
    speaker.neighbor_add(peerip, peeras, peerport)
    # uncomment the below line if the speaker needs to talk with a bmp server.
    # speaker.bmp_server_add('192.168.177.2', 11019)

    # count = 1
    while True:
        eventlet.sleep(30)
Example #2
0
    def __init__(self, *args, **kwargs):
        super(SDNIP, self).__init__(*args, **kwargs)
        self.fwd = kwargs['fwd']
        self.hop_db = kwargs['hop_db']
        self.cfg_mgr = SDNIPConfigManager()
        self.waiters = {}
        self.bgp_speaker =\
            BGPSpeaker(self.cfg_mgr.as_number,
                       str(self.cfg_mgr.router_id),
                       bgp_server_port=self.cfg_mgr.listen_port,
                       best_path_change_handler=self.best_path_change_handler,
                       peer_down_handler=self.peer_down_handler,
                       peer_up_handler=self.peer_up_handler)

        speaker_ids = self.cfg_mgr.get_all_speaker_id()

        for speaker_id in speaker_ids:
            self.bgp_speaker.neighbor_add(speaker_id,
                                          self.cfg_mgr.as_number,
                                          is_next_hop_self=True)

        hub.spawn(self.prefix_check_loop)

        if with_dk:
            dk_plugin.DynamicLoader.register_custom_cmd(
                'sdn-ip:info', self.cmd_self_info)
            dk_plugin.DynamicLoader.register_custom_cmd(
                'sdn-ip:routes', self.cmd_list_routes)
            dk_plugin.DynamicLoader.register_custom_cmd(
                'sdn-ip:flows', self.cmd_get_flows)
 def start_bgpspeaker(self, asNum, routerId, label_start, label_end):
     self.myRouterId = routerId
     self.labelRange = tuple([label_start, label_end])
     self.speaker = BGPSpeaker(as_number=asNum, router_id=routerId,
                  best_path_change_handler=self.dump_remote_best_path_change,
                  peer_down_handler=self.detect_peer_down,
                  peer_up_handler=self.detect_peer_up,
                  label_range=self.labelRange)
Example #4
0
def main():
    reset_flows()
    sw=discover_switches()
    resolve_nhops()
    print "start BGP peering"
    speaker = BGPSpeaker(**self)
    speaker.neighbor_add(**neighbor)
    while True:
        eventlet.sleep(10)
Example #5
0
    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Settings for starting BGPSpeaker
        bgp_settings = {}

        # Get required settings.
        try:
            bgp_settings['as_number'] = settings.get(LOCAL_AS)
            bgp_settings['router_id'] = settings.get(ROUTER_ID)
        except KeyError as e:
            raise ApplicationException(
                desc='Required BGP configuration missing: %s' % e)

        # Set event notify handlers if no corresponding handler specified.
        bgp_settings['best_path_change_handler'] = settings.get(
            'best_path_change_handler', self._notify_best_path_changed_event)
        bgp_settings['peer_down_handler'] = settings.get(
            'peer_down_handler', self._notify_peer_down_event)
        bgp_settings['peer_up_handler'] = settings.get(
            'peer_up_handler', self._notify_peer_up_event)

        # Get optional settings.
        bgp_settings[BGP_SERVER_PORT] = settings.get(
            BGP_SERVER_PORT, DEFAULT_BGP_SERVER_PORT)
        bgp_settings[REFRESH_STALEPATH_TIME] = settings.get(
            REFRESH_STALEPATH_TIME, DEFAULT_REFRESH_STALEPATH_TIME)
        bgp_settings[REFRESH_MAX_EOR_TIME] = settings.get(
            REFRESH_MAX_EOR_TIME, DEFAULT_REFRESH_MAX_EOR_TIME)
        bgp_settings[LABEL_RANGE] = settings.get(
            LABEL_RANGE, DEFAULT_LABEL_RANGE)
        bgp_settings['allow_local_as_in_count'] = settings.get(
            'allow_local_as_in_count', 0)
        bgp_settings[LOCAL_PREF] = settings.get(
            LOCAL_PREF, DEFAULT_LOCAL_PREF)

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        self.speaker = BGPSpeaker(**bgp_settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(settings.get('neighbors', []))

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(settings.get('vrfs', []))

        # Add Networks
        LOG.debug('Adding routes...')
        self._add_routes(settings.get('routes', []))
Example #6
0
 def reset_bgp(self):
     # TODO: port status changes should cause us to withdraw a route.
     # TODO: configurable behavior - withdraw routes if peer goes down.
     for dp_id, valve in self.valves.iteritems():
         if dp_id not in self.dp_bgp_speakers:
             self.dp_bgp_speakers[dp_id] = {}
         bgp_speakers = self.dp_bgp_speakers[dp_id]
         for bgp_speaker in bgp_speakers.itervalues():
             bgp_speaker.shutdown()
         for vlan in valve.dp.vlans.itervalues():
             if vlan.bgp_as:
                 handler = lambda x: self.bgp_route_handler(x, vlan)
                 bgp_speaker = BGPSpeaker(
                     as_number=vlan.bgp_as,
                     router_id=vlan.bgp_routerid,
                     bgp_server_port=vlan.bgp_port,
                     best_path_change_handler=handler)
                 for controller_ip in vlan.controller_ips:
                     prefix = ipaddr.IPNetwork(
                         '/'.join(
                             (str(controller_ip.ip),
                              str(controller_ip.prefixlen))))
                     bgp_speaker.prefix_add(
                         prefix=str(prefix),
                         next_hop=controller_ip.ip)
                 for route_table in (vlan.ipv4_routes, vlan.ipv6_routes):
                     for ip_dst, ip_gw in route_table.iteritems():
                         bgp_speaker.prefix_add(
                             prefix=str(ip_dst),
                             next_hop=str(ip_gw))
                 bgp_speaker.neighbor_add(
                     address=vlan.bgp_neighbor_address,
                     remote_as=vlan.bgp_neighbor_as)
                 bgp_speakers[vlan] = bgp_speaker
    def _create_bgp_speaker_for_vlan(self, vlan):
        """Set up BGP speaker for an individual VLAN if required.

        Args:
            vlan (vlan): VLAN associated with this speaker.
        Returns:
            ryu.services.protocols.bgp.bgpspeaker.BGPSpeaker: BGP speaker.
        """
        handler = lambda x: self._bgp_route_handler(x, vlan)
        bgp_speaker = BGPSpeaker(as_number=vlan.bgp_as,
                                 router_id=vlan.bgp_routerid,
                                 bgp_server_port=vlan.bgp_port,
                                 best_path_change_handler=handler)
        for faucet_vip in vlan.faucet_vips:
            prefix = ipaddr.IPNetwork(faucet_vip.exploded)
            bgp_speaker.prefix_add(prefix=str(prefix),
                                   next_hop=str(faucet_vip.ip))
        for route_table in (vlan.ipv4_routes, vlan.ipv6_routes):
            for ip_dst, ip_gw in route_table.iteritems():
                bgp_speaker.prefix_add(prefix=str(ip_dst), next_hop=str(ip_gw))
        for bgp_neighbor_address in vlan.bgp_neighbor_addresses:
            bgp_speaker.neighbor_add(address=bgp_neighbor_address,
                                     remote_as=vlan.bgp_neighbor_as,
                                     local_address=vlan.bgp_local_address,
                                     enable_ipv4=True,
                                     enable_ipv6=True)
        return bgp_speaker
Example #8
0
    def __init__(self, *args, **kwargs):
        super(SDNIP, self).__init__(*args, **kwargs)
        self.fwd = kwargs['fwd']
        self.hop_db = kwargs['hop_db']
        self.cfg_mgr = SDNIPConfigManager()
        self.waiters = {}
        self.bgp_speaker =\
            BGPSpeaker(self.cfg_mgr.as_number,
                       str(self.cfg_mgr.router_id),
                       bgp_server_port=self.cfg_mgr.listen_port,
                       best_path_change_handler=self.best_path_change_handler,
                       peer_down_handler=self.peer_down_handler,
                       peer_up_handler=self.peer_up_handler)

        speaker_ids = self.cfg_mgr.get_all_speaker_id()

        for speaker_id in speaker_ids:
            self.bgp_speaker.neighbor_add(speaker_id,
                                          self.cfg_mgr.as_number,
                                          is_next_hop_self=True)

        hub.spawn(self.prefix_check_loop)

        if with_dk:
            dk_plugin.DynamicLoader.register_custom_cmd('sdn-ip:info', self.cmd_self_info)
            dk_plugin.DynamicLoader.register_custom_cmd('sdn-ip:routes', self.cmd_list_routes)
            dk_plugin.DynamicLoader.register_custom_cmd('sdn-ip:flows', self.cmd_get_flows)
Example #9
0
    def _create_bgp_speaker_for_vlan(self, vlan):
        """Set up BGP speaker for an individual VLAN if required.

        Args:
            vlan (vlan): VLAN associated with this speaker.
        Returns:
            ryu.services.protocols.bgp.bgpspeaker.BGPSpeaker: BGP speaker.
        """
        handler = lambda x: self._bgp_route_handler(x, vlan)
        bgp_speaker = BGPSpeaker(
            as_number=vlan.bgp_as,
            router_id=vlan.bgp_routerid,
            bgp_server_port=vlan.bgp_port,
            best_path_change_handler=handler)
        for controller_ip in vlan.controller_ips:
            prefix = ipaddr.IPNetwork(
                '/'.join((str(controller_ip.ip), str(controller_ip.prefixlen))))
            bgp_speaker.prefix_add(
                prefix=str(prefix), next_hop=controller_ip.ip)
        for route_table in (vlan.ipv4_routes, vlan.ipv6_routes):
            for ip_dst, ip_gw in route_table.iteritems():
                bgp_speaker.prefix_add(
                    prefix=str(ip_dst), next_hop=str(ip_gw))
        for bgp_neighbor_address in vlan.bgp_neighbor_addresses:
            bgp_speaker.neighbor_add(
                address=bgp_neighbor_address,
                remote_as=vlan.bgp_neighbor_as)
        return bgp_speaker
Example #10
0
 def reset_bgp(self):
     # TODO: port status changes should cause us to withdraw a route.
     # TODO: configurable behavior - withdraw routes if peer goes down.
     for bgp_speaker in self.bgp_speakers.itervalues():
         bgp_speaker.shutdown()
     for vlan in self.valve.dp.vlans.itervalues():
         if vlan.bgp_as:
             handler = lambda x: self.bgp_route_handler(x, vlan)
             bgp_speaker = BGPSpeaker(
                 as_number=vlan.bgp_as,
                 router_id=vlan.bgp_routerid,
                 bgp_server_port=vlan.bgp_port,
                 best_path_change_handler=handler)
             for controller_ip in vlan.controller_ips:
                 prefix = ipaddr.IPNetwork(
                     '/'.join(
                         (str(controller_ip.ip),
                          str(controller_ip.prefixlen))))
                 bgp_speaker.prefix_add(
                     prefix=str(prefix),
                     next_hop=controller_ip.ip)
             for route_table in (vlan.ipv4_routes, vlan.ipv6_routes):
                 for ip_dst, ip_gw in route_table.iteritems():
                     bgp_speaker.prefix_add(
                         prefix=str(ip_dst),
                         next_hop=str(ip_gw))
             bgp_speaker.neighbor_add(
                 address=vlan.bgp_neighbor_address,
                 remote_as=vlan.bgp_neighbor_as)
             self.bgp_speakers[vlan] = bgp_speaker
Example #11
0
    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Check required settings.
        _required_settings = (
            LOCAL_AS,
            ROUTER_ID,
        )
        for required in _required_settings:
            if required not in settings:
                raise ApplicationException(
                    desc='Required BGP configuration missing: %s' % required)

        # Set event notify handlers if no corresponding handler specified.
        settings.setdefault(
            'best_path_change_handler', self._notify_best_path_changed_event)
        settings.setdefault(
            'adj_rib_in_change_handler', self._notify_adj_rib_in_changed_event)
        settings.setdefault(
            'peer_down_handler', self._notify_peer_down_event)
        settings.setdefault(
            'peer_up_handler', self._notify_peer_up_event)

        # Pop settings other than creating BGPSpeaker instance.
        neighbors_settings = settings.pop('neighbors', [])
        vrfs_settings = settings.pop('vrfs', [])
        routes_settings = settings.pop('routes', [])

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        settings.setdefault('as_number', settings.pop(LOCAL_AS))
        self.speaker = BGPSpeaker(**settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(neighbors_settings)

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(vrfs_settings)

        # Add routes
        LOG.debug('Adding routes...')
        self._add_routes(routes_settings)
Example #12
0
    def bgp_sender(self):
        def dump_remote_best_path_change(event):
            print 'the best path changed:', event.remote_as, event.prefix, \
                event.nexthop, event.is_withdraw

        def detect_peer_down(remote_ip, remote_as):
            print 'Peer down:', remote_ip, remote_as

        def detect_peer_up(remote_ip, remote_as, uri_enabled, peer):
            print 'Peer up', remote_ip, remote_as
            if uri_enabled:
                self.uri_enabled_capability = True
                self.peer[remote_ip] = (
                    peer, self.uri_enabled_capability
                )  #Create peer dictionary with key ip and value a tuple of peer and uri_enabled capability
                self.uri_enabled_capability = False
            else:
                self.peer[remote_ip] = (peer, False)

        self.speaker = BGPSpeaker(
            as_number=1000,
            router_id='147.102.13.198',
            best_path_change_handler=dump_remote_best_path_change,
            peer_down_handler=detect_peer_down,
            peer_up_handler=detect_peer_up)
        #self.speaker = BGPSpeaker(as_number=1000, router_id='2.1.1.1',
        #                        best_path_change_handler=dump_remote_best_path_change,
        #                         peer_down_handler=detect_peer_down,peer_up_handler=detect_peer_up)

        self.speaker.neighbor_add('147.102.13.156', 1000, next_hop='192.0.2.1')

        #self.speaker.neighbor_add('192.168.1.2', 1001,enable_uri=True)
        #self.speaker.neighbor_add('2.1.1.2', 1000, next_hop='192.0.2.1')
        #alla = PrefixFilter('0.0.0.0/0',policy=PrefixFilter.POLICY_DENY)
        #self.speaker.out_filter_set('192.168.1.2',[alla])
        #self.speaker.out_filter_set('2.1.1.2',[alla])
        #self.drop_to_router(AC(1000).create())
        #self.speaker.
        #eventlet.sleep(20)
        #self.drop_to_router(['147.102.13.199/32'])
        ofs = Switch()
        eventlet.sleep(40)
        ofs.add_flow("147.102.13.199")
        """
Example #13
0
    def __init__(self, *args, **kwargs):
        super(SDNIP, self).__init__(*args, **kwargs)
        self.fwd_util = kwargs['fwd']
        self.hop_db = kwargs['hop_db']
        self.cfg_mgr = SDNIPConfigManager()  #获取SDN-IP配置信息
        # 在Ryu上运行一个iBGPSpeaker
        self.bgp_speaker =\
            BGPSpeaker(self.cfg_mgr.as_number,      #AS号
                       str(self.cfg_mgr.router_id),     #iBGP的router id
                       bgp_server_port=self.cfg_mgr.listen_port,        #监听BGP协议的端口号
                       best_path_change_handler=self.best_path_change_handler,      #当路由信息变化时调用此方法
                       peer_down_handler=self.peer_down_handler,        #BGP对等体下线
                       peer_up_handler=self.peer_up_handler)        #BGP对等体上线

        speaker_ids = self.cfg_mgr.get_all_speaker_id()
        # 建立iBGPSpeaker与SDN域内的BGPSpeaker的连接
        for speaker_id in speaker_ids:
            self.bgp_speaker.neighbor_add(speaker_id,
                                          self.cfg_mgr.as_number,
                                          is_next_hop_self=True)
Example #14
0
    def bgp_create(self, as_number, router_id):
        # MUDAR AQUI - INICIO
        try:
            self.bgp_speaker = BGPSpeaker(
                as_number=as_number,
                router_id=router_id,
                best_path_change_handler=self.best_path_change_handler,
                adj_rib_in_change_handler=self.adj_rib_in_change_handler,
                peer_down_handler=self.peer_down_handler,
                peer_up_handler=self.peer_up_handler)
        except Exception as e:
            print "Error creating bgp speaker: %s" % (e)
            return (False, 'Failed to create BGP speaker')
        # MUDAR AQUI - FIM

        self.bgp_config['as_number'] = as_number
        self.bgp_config['router_id'] = router_id
        self.bgp_config['neighbors'] = []
        self.bgp_config['adv_prefixes'] = []
        self.persist_config()
        return (True, 'Success')
Example #15
0
    def __init__(self, *args, **kwargs):
        super(SDNIP, self).__init__(*args, **kwargs)
        self.fwd = kwargs['fwd']
        self.hop_db = kwargs['hop_db']
        self.cfg_mgr = SDNIPConfigManager('config.json')
        self.bgp_speaker =\
        BGPSpeaker(self.cfg_mgr.as_number,
                   self.cfg_mgr.router_id,
                   bgp_server_port=self.cfg_mgr.listen_port,
                   best_path_change_handler=self.best_path_change_handler,
                   peer_down_handler=self.peer_down_handler,
                   peer_up_handler=self.peer_up_handler)

        speaker_ids = self.cfg_mgr.get_all_speaker_id()

        for speaker_id in speaker_ids:
            self.bgp_speaker.neighbor_add(speaker_id,
                                          self.cfg_mgr.as_number,
                                          is_next_hop_self=True)

        hub.spawn(self.prefix_check_loop)
Example #16
0
    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Settings for starting BGPSpeaker
        bgp_settings = {}

        # Get required settings.
        try:
            bgp_settings['as_number'] = settings.get(LOCAL_AS)
            bgp_settings['router_id'] = settings.get(ROUTER_ID)
        except KeyError as e:
            raise ApplicationException(
                desc='Required BGP configuration missing: %s' % e)

        # Get optional settings.
        bgp_settings[BGP_SERVER_PORT] = settings.get(BGP_SERVER_PORT,
                                                     DEFAULT_BGP_SERVER_PORT)
        bgp_settings[REFRESH_STALEPATH_TIME] = settings.get(
            REFRESH_STALEPATH_TIME, DEFAULT_REFRESH_STALEPATH_TIME)
        bgp_settings[REFRESH_MAX_EOR_TIME] = settings.get(
            REFRESH_MAX_EOR_TIME, DEFAULT_REFRESH_MAX_EOR_TIME)
        bgp_settings[LABEL_RANGE] = settings.get(LABEL_RANGE,
                                                 DEFAULT_LABEL_RANGE)

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        self.speaker = BGPSpeaker(**bgp_settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(settings.get('neighbors', []))

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(settings.get('vrfs', []))

        # Add Networks
        LOG.debug('Adding routes...')
        self._add_routes(settings.get('routes', []))
Example #17
0
    def _create_bgp_speaker_for_vlan(self, vlan, dp_id, vlan_vid):
        """Set up BGP speaker for an individual VLAN if required.

        Args:
            vlan (valve VLAN): VLAN for BGP speaker.
            dp_id (int): Datapath ID for BGP speaker.
            vlan_vid (vlan_vid): VLAN VID for BGP speaker.
        Returns:
            ryu.services.protocols.bgp.bgpspeaker.BGPSpeaker: BGP speaker.
        """
        handler = lambda x: self._bgp_route_handler(x, dp_id, vlan_vid)
        bgp_speaker = BGPSpeaker(
            as_number=vlan.bgp_as,
            router_id=vlan.bgp_routerid,
            bgp_server_port=vlan.bgp_port,
            bgp_server_hosts=vlan.bgp_server_addresses,
            best_path_change_handler=handler,
            peer_up_handler=self._bgp_up_handler,
            peer_down_handler=self._bgp_down_handler)
        for ip_dst, ip_gw in self._vlan_prefixes(vlan):
            bgp_speaker.prefix_add(prefix=ip_dst, next_hop=ip_gw)
        for bgp_neighbor_address in vlan.bgp_neighbor_addresses:
            bgp_speaker.neighbor_add(
                connect_mode=vlan.bgp_connect_mode,
                address=bgp_neighbor_address,
                remote_as=vlan.bgp_neighbor_as,
                local_address=vlan.bgp_local_address,
                enable_ipv4=True,
                enable_ipv6=True)
        return bgp_speaker
Example #18
0
    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Settings for starting BGPSpeaker
        bgp_settings = {}

        # Get required settings.
        try:
            bgp_settings['as_number'] = settings.get(LOCAL_AS)
            bgp_settings['router_id'] = settings.get(ROUTER_ID)
        except KeyError as e:
            raise ApplicationException(
                desc='Required BGP configuration missing: %s' % e)

        # Set event notify handlers if no corresponding handler specified.
        bgp_settings['best_path_change_handler'] = settings.get(
            'best_path_change_handler', self._notify_best_path_changed_event)
        bgp_settings['peer_down_handler'] = settings.get(
            'peer_down_handler', self._notify_peer_down_event)
        bgp_settings['peer_up_handler'] = settings.get(
            'peer_up_handler', self._notify_peer_up_event)

        # Get optional settings.
        bgp_settings[BGP_SERVER_PORT] = settings.get(
            BGP_SERVER_PORT, DEFAULT_BGP_SERVER_PORT)
        bgp_settings[REFRESH_STALEPATH_TIME] = settings.get(
            REFRESH_STALEPATH_TIME, DEFAULT_REFRESH_STALEPATH_TIME)
        bgp_settings[REFRESH_MAX_EOR_TIME] = settings.get(
            REFRESH_MAX_EOR_TIME, DEFAULT_REFRESH_MAX_EOR_TIME)
        bgp_settings[LABEL_RANGE] = settings.get(
            LABEL_RANGE, DEFAULT_LABEL_RANGE)
        bgp_settings['allow_local_as_in_count'] = settings.get(
            'allow_local_as_in_count', 0)

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        self.speaker = BGPSpeaker(**bgp_settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(settings.get('neighbors', []))

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(settings.get('vrfs', []))

        # Add Networks
        LOG.debug('Adding routes...')
        self._add_routes(settings.get('routes', []))
Example #19
0
    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Check required settings.
        _required_settings = (
            LOCAL_AS,
            ROUTER_ID,
        )
        for required in _required_settings:
            if required not in settings:
                raise ApplicationException(
                    desc='Required BGP configuration missing: %s' % required)

        # Set event notify handlers if no corresponding handler specified.
        settings.setdefault(
            'best_path_change_handler', self._notify_best_path_changed_event)
        settings.setdefault(
            'peer_down_handler', self._notify_peer_down_event)
        settings.setdefault(
            'peer_up_handler', self._notify_peer_up_event)

        # Pop settings other than creating BGPSpeaker instance.
        neighbors_settings = settings.pop('neighbors', [])
        vrfs_settings = settings.pop('vrfs', [])
        routes_settings = settings.pop('routes', [])

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        settings.setdefault('as_number', settings.pop(LOCAL_AS))
        self.speaker = BGPSpeaker(**settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(neighbors_settings)

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(vrfs_settings)

        # Add routes
        LOG.debug('Adding routes...')
        self._add_routes(routes_settings)
Example #20
0
    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Settings for starting BGPSpeaker
        bgp_settings = {}

        # Get required settings.
        try:
            bgp_settings['as_number'] = settings.get(LOCAL_AS)
            bgp_settings['router_id'] = settings.get(ROUTER_ID)
        except KeyError as e:
            raise ApplicationException(
                desc='Required BGP configuration missing: %s' % e)

        # Get optional settings.
        bgp_settings[BGP_SERVER_PORT] = settings.get(
            BGP_SERVER_PORT, DEFAULT_BGP_SERVER_PORT)
        bgp_settings[REFRESH_STALEPATH_TIME] = settings.get(
            REFRESH_STALEPATH_TIME, DEFAULT_REFRESH_STALEPATH_TIME)
        bgp_settings[REFRESH_MAX_EOR_TIME] = settings.get(
            REFRESH_MAX_EOR_TIME, DEFAULT_REFRESH_MAX_EOR_TIME)
        bgp_settings[LABEL_RANGE] = settings.get(
            LABEL_RANGE, DEFAULT_LABEL_RANGE)

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        self.speaker = BGPSpeaker(**bgp_settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(settings.get('neighbors', []))

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(settings.get('vrfs', []))

        # Add Networks
        LOG.debug('Adding routes...')
        self._add_routes(settings.get('routes', []))
Example #21
0
    def _create_bgp_speaker_for_vlan(self, vlan):
        """Set up BGP speaker for an individual VLAN if required.

        Args:
            vlan (vlan): VLAN associated with this speaker.
        Returns:
            ryu.services.protocols.bgp.bgpspeaker.BGPSpeaker: BGP speaker.
        """
        handler = lambda x: self._bgp_route_handler(x, vlan)
        bgp_speaker = BGPSpeaker(as_number=vlan.bgp_as,
                                 router_id=vlan.bgp_routerid,
                                 bgp_server_port=vlan.bgp_port,
                                 best_path_change_handler=handler)
        for controller_ip in vlan.controller_ips:
            prefix = ipaddr.IPNetwork('/'.join(
                (str(controller_ip.ip), str(controller_ip.prefixlen))))
            bgp_speaker.prefix_add(prefix=str(prefix),
                                   next_hop=controller_ip.ip)
        for route_table in (vlan.ipv4_routes, vlan.ipv6_routes):
            for ip_dst, ip_gw in route_table.iteritems():
                bgp_speaker.prefix_add(prefix=str(ip_dst), next_hop=str(ip_gw))
        bgp_speaker.neighbor_add(address=vlan.bgp_neighbor_address,
                                 remote_as=vlan.bgp_neighbor_as)
        return bgp_speaker
Example #22
0
class SDNIP(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
    _CONTEXTS = {'fwd': FwdUtil, 'hop_db': HopDB}
    """
        初始化方法
    """
    def __init__(self, *args, **kwargs):
        super(SDNIP, self).__init__(*args, **kwargs)
        self.fwd_util = kwargs['fwd']
        self.hop_db = kwargs['hop_db']
        self.cfg_mgr = SDNIPConfigManager()  #获取SDN-IP配置信息
        # 在Ryu上运行一个iBGPSpeaker
        self.bgp_speaker =\
            BGPSpeaker(self.cfg_mgr.as_number,      #AS号
                       str(self.cfg_mgr.router_id),     #iBGP的router id
                       bgp_server_port=self.cfg_mgr.listen_port,        #监听BGP协议的端口号
                       best_path_change_handler=self.best_path_change_handler,      #当路由信息变化时调用此方法
                       peer_down_handler=self.peer_down_handler,        #BGP对等体下线
                       peer_up_handler=self.peer_up_handler)        #BGP对等体上线

        speaker_ids = self.cfg_mgr.get_all_speaker_id()
        # 建立iBGPSpeaker与SDN域内的BGPSpeaker的连接
        for speaker_id in speaker_ids:
            self.bgp_speaker.neighbor_add(speaker_id,
                                          self.cfg_mgr.as_number,
                                          is_next_hop_self=True)
        # 启动一个线程,用于修复访问外部主机的数据路径
        #hub.spawn(self.prefix_check_loop)

    """
        当路由信息变化时,调用此方法,建立访问外部主机的数据路径。
        参数:
            ev: 路由更新时间,含有访问目的网络的下一跳地址信息。
        建立的路径有:
        1.穿过本地的流量到外部主机的路径(Transit Traffic ---> Internet)
        2.本地主机访问外部主机的路径(Local Host ---> Internet)
    """

    def best_path_change_handler(self, ev):
        self.logger.info('best path changed:')
        self.logger.info('remote_as: %d', ev.remote_as)
        self.logger.info('route_dist: %s', ev.route_dist)
        self.logger.info('prefix: %s', ev.prefix)
        self.logger.info('nexthop: %s', ev.nexthop)
        self.logger.info('label: %s', ev.label)
        self.logger.info('is_withdraw: %s', ev.is_withdraw)
        self.logger.info('')

        # 取网络前缀
        prefix_nw = IPNetwork(ev.prefix)
        # 不处理本地网络更新
        for internal_network in self.cfg_mgr.get_internal_networks():
            int_nw = IPNetwork(internal_network)

            if int_nw == prefix_nw:
                self.logger.info('Internal network, ignored.')
                return
        if ev.is_withdraw:
            self.hop_db.remove_hop(ev.prefix)
        else:
            # 记录访问目的网络的下一跳地址信息
            self.hop_db.add_hop(ev.prefix, ev.nexthop)

    """
        建立BGPSpeaker间的连接。
    """

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def bgp_packet_in_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        dpid = dp.id
        ofproto = dp.ofproto

        pkt = packet.Packet(msg.data)
        tcp_header = pkt.get_protocol(tcp.tcp)

        #只处理BGP数据包,tcp端口为179
        if tcp_header is None or (tcp_header.src_port is not 179
                                  and tcp_header.dst_port is not 179):
            return

        ipv4_header = pkt.get_protocol(ipv4.ipv4)
        src_ip = ipv4_header.src
        dst_ip = ipv4_header.dst
        self.logger.info("BGP from %s to %s", src_ip, dst_ip)

        # 获取源、目的主机信息
        hosts = topo_api.get_all_host(self)
        src_host = None
        dst_host = None

        for host in hosts:
            if src_ip in host.ipv4:
                src_host = host

            elif dst_ip in host.ipv4:
                dst_host = host
        if src_host is None or dst_host is None:
            return

        # 建立BGPSpeaker间的数据路径
        src_port = src_host.port
        dst_port = dst_host.port
        dst_mac = dst_host.mac
        to_dst_match = dp.ofproto_parser.OFPMatch(eth_dst=dst_mac,
                                                  ipv4_dst=dst_ip,
                                                  eth_type=2048)
        pre_actions = [dp.ofproto_parser.OFPActionSetField(eth_dst=dst_mac)]
        port_no = self.fwd_util.setup_shortest_path(src_port.dpid,
                                                    dst_port.dpid,
                                                    dst_port.port_no,
                                                    to_dst_match, pre_actions)
        # 将首个数据包直接递交给目的主机,防止首包丢失
        if port_no is None:
            return
        self.fwd_util.packet_out(dp, msg, port_no)

    """
        处理packet-in请求,建立到外部主机的单向数据路径。
    """

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    @packet_in_filter(RequiredTypeFilter, {'types': [ipv4.ipv4]})
    def internal_host_route_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        dpid = dp.id
        ofproto = dp.ofproto

        pkt = packet.Packet(msg.data)
        ipv4_header = pkt.get_protocol(ipv4.ipv4)

        src_ip = ipv4_header.src
        dst_ip = ipv4_header.dst
        #只处理目的不是本地的访问
        if self.cfg_mgr.is_internal_host(dst_ip):
            return
        # 获取下一跳信息,若下一条信息不存在,不处理
        nexthop_info = self.hop_db.get_nexthop_by_ip(dst_ip)
        if not nexthop_info:
            return
        nexthop_prefix = nexthop_info[0]
        nexthop = nexthop_info[1]
        nexthop_host = self.fwd_util.get_host(nexthop)
        if nexthop_host is None:
            return
        # 建立主机间的数据路径
        host_match = \
            dp.ofproto_parser.OFPMatch(ipv4_dst=(str(nexthop_prefix.ip), str(nexthop_prefix.netmask)), eth_type=2048)
        pre_actions = [
            dp.ofproto_parser.OFPActionSetField(eth_dst=nexthop_host.mac)
        ]
        self.logger.info("daowaiwaiwai")
        self.fwd_util.setup_shortest_path(dpid, nexthop_host.port.dpid,
                                          nexthop_host.port.port_no,
                                          host_match, pre_actions)
        # 将首个数据包直接递交给目的主机,防止首包丢失
        switch = topo_api.get_switch(self, nexthop_host.port.dpid)[0]
        self.fwd_util.packet_out(switch.dp, msg, nexthop_host.port.port_no)

    """
        处理packet-in请求,建立目的主机为本地主机的单向数据路径。
    """

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    @packet_in_filter(RequiredTypeFilter, {'types': [ipv4.ipv4]})
    def internet_to_host_route_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        dpid = dp.id
        ofproto = dp.ofproto

        pkt = packet.Packet(msg.data)
        ipv4_header = pkt.get_protocol(ipv4.ipv4)

        src_ip = ipv4_header.src
        dst_ip = ipv4_header.dst
        # 若目的主机不是本地主机,不处理
        if not self.cfg_mgr.is_internal_host(dst_ip):
            return

        #获取目的主机信息,若目的主机不存在,不处理
        dst_host = self.fwd_util.get_host(dst_ip)
        if dst_host is None:
            return
        #到本地主机的数据路径
        host_match = \
            dp.ofproto_parser.OFPMatch(ipv4_dst=dst_ip, eth_type=2048)
        pre_actions = [
            dp.ofproto_parser.OFPActionSetField(eth_dst=dst_host.mac)
        ]
        self.logger.info("daoneineinei")
        self.fwd_util.setup_shortest_path(dpid, dst_host.port.dpid,
                                          dst_host.port.port_no, host_match,
                                          pre_actions)
        #  将首个数据包直接递交给目的主机,防止首包丢失
        switch = topo_api.get_switch(self, dst_host.port.dpid)[0]
        self.fwd_util.packet_out(switch.dp, msg, dst_host.port.port_no)

    def peer_down_handler(self, remote_ip, remote_as):
        self.logger.info('peer down:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    def peer_up_handler(self, remote_ip, remote_as):
        self.logger.info('peer up:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    """
        修复访问外部主机的数据路径
    """

    def prefix_check_loop(self):
        while True:
            prefixs_to_install = self.hop_db.get_uninstalled_prefix_list()
            self.logger.debug("prefix to install: %s", str(prefixs_to_install))

            for prefix in prefixs_to_install:
                prefix_nw = IPNetwork(prefix)

                for internal_network in self.cfg_mgr.get_internal_networks():
                    int_nw = IPNetwork(internal_network)

                    if int_nw == prefix_nw:
                        self.logger.info('Internal network, ignored.')
                        continue
                nexthop = self.hop_db.get_nexthop(prefix)
                self.install_best_path(prefix, nexthop)

            hub.sleep(3)

    """
        根据下一跳地址建立到目的网络的路径[Traffic(dst_ip in prefix) ---> nexthot host]
    """

    def install_best_path(self, prefix, nexthop):
        # 获取下一跳路由器信息
        nexthop_host = self.fwd_util.get_host(nexthop)
        self.logger.debug("nexthop host: %s", str(nexthop_host))
        if nexthop_host is None:
            return

        nexthop_port = nexthop_host.port
        nexthop_mac = nexthop_host.mac
        nexthop_dpid = nexthop_port.dpid
        nexthop_port_no = nexthop_port.port_no
        prefix_ip = str(IPNetwork(prefix).ip)
        prefix_mask = str(IPNetwork(prefix).netmask)
        '''
            在通往下一跳主机路径上的每个switch上下发流表:
            匹配:
                数据包类型为IPV4
                目的ipv4网络为prefix
            处理:
                修改目的Mac为下一跳路由器Mac
                将数据包转发往下一跳方向
        '''
        for dp in self.fwd_util.get_all_datapaths():
            from_dpid = dp.id
            nexthop_match = \
                dp.ofproto_parser.OFPMatch(ipv4_dst=(prefix_ip, prefix_mask),
                                           eth_type=2048)
            pre_actions = [
                dp.ofproto_parser.OFPActionSetField(eth_dst=nexthop_mac)
            ]

            self.fwd_util.setup_shortest_path(from_dpid, nexthop_dpid,
                                              nexthop_port_no, nexthop_match,
                                              pre_actions)

        self.hop_db.install_prefix(prefix)


#app_manager.require_app('ryu.app.gui_topology.gui_topology')
class SimpleBGPSpeaker(app_manager.RyuApp):

    def __init__(self, *args, **kwargs):
        super(SimpleBGPSpeaker, self).__init__(*args, **kwargs)
        self.bgp_q = hub.Queue()
        self.name = 'bgps'
        self.bgpPeerStatus = {}
        self.target_route_dist = None
        self.bgp_thread = hub.spawn(self.monitor_target_remotePrefix)

    def monitor_target_remotePrefix(self):
        previous_route_dist = None
        while True:
            if self.target_route_dist == None:
                pass
            elif self.target_route_dist == previous_route_dist:
                self.target_route_dist = None
            else:
                previous_route_dist = self.target_route_dist
            time.sleep(60)


    def dump_remote_best_path_change(self, event):
        remote_prefix = {}
        prefixInfo = IPNetwork(event.prefix)

        remote_prefix['remote_as'] = event.remote_as
        remote_prefix['route_dist'] = event.route_dist
        remote_prefix['prefix'] = str(prefixInfo.ip)
        remote_prefix['netmask'] = str(prefixInfo.netmask)
        remote_prefix['nexthop'] = event.nexthop
        remote_prefix['label'] = event.label
        remote_prefix['withdraw'] = event.is_withdraw
        LOG.debug("remote_prefix=%s"%remote_prefix)

        if self.filter_regist_remotePrefix(event.route_dist):
            self.bgp_q.put(remote_prefix)

    def filter_regist_remotePrefix(self, route_dist):
        if self.target_route_dist == None:
            result = True
        elif self.target_route_dist == route_dist:
            result = True
        else:
            result = False

        return result


    def detect_peer_down(self, remote_ip, remote_as):
        nowtime = datetime.datetime.now()
        LOG.info("%s: Peer down!![remote_ip: %s, remote_as: %s]"%(nowtime, remote_ip, remote_as))
        self.bgpPeerStatus[nowtime] = BgpPeerStatus(nowtime,
                                                    "Peer Down",
                                                    self.myRouterId,
                                                    remote_ip,
                                                    remote_as)


    def detect_peer_up(self, remote_ip, remote_as):
        nowtime = datetime.datetime.now()
        LOG.info("%s: Peer up!![remote_ip: %s, remote_as: %s]"%(nowtime, remote_ip, remote_as))
        self.bgpPeerStatus[nowtime] = BgpPeerStatus(nowtime,
                                                    "Peer Up",
                                                    self.myRouterId,
                                                    remote_ip,
                                                    remote_as)


    def start_bgpspeaker(self, asNum, routerId, label_start, label_end):
        self.myRouterId = routerId
        self.labelRange = tuple([label_start, label_end])
        self.speaker = BGPSpeaker(as_number=asNum, router_id=routerId,
                     best_path_change_handler=self.dump_remote_best_path_change,
                     peer_down_handler=self.detect_peer_down,
                     peer_up_handler=self.detect_peer_up,
                     label_range=self.labelRange)


    def start_bmpclient(self, address, port):
        return self.speaker.bmp_server_add(address, port)


    def stop_bmpclient(self, address, port):
        return self.speaker.bmp_server_del(address, port)


    def add_neighbor(self, peerIp, asNumber, med, localPref, filterAsNum):
        self.speaker.neighbor_add(peerIp, asNumber, is_next_hop_self=True,
                               enable_vpnv4=True, enable_enhanced_refresh=True,
                               multi_exit_disc=med)
        if filterAsNum:
            as_path_filter = ASPathFilter(filterAsNum,
                                          policy=ASPathFilter.POLICY_TOP)
            if localPref:
                attribute_map = AttributeMap([as_path_filter],
                                             AttributeMap.ATTR_LOCAL_PREF,
                                             localPref)
                self.speaker.attribute_map_set(peerIp, [attribute_map],
                                               route_family='ipv4')


    def add_vrf(self, routeDist, importList, exportList):
        self.speaker.vrf_add(routeDist, importList, exportList)
        self.target_route_dist = routeDist


    def del_vrf(self, routeDist):
        self.speaker.vrf_del(routeDist)


    def add_prefix(self, ipaddress, netmask, nexthop=None, routeDist=None):
        prefix = IPNetwork(ipaddress + '/' + netmask)
        local_prefix = str(prefix.cidr)

        if routeDist:
            if nexthop:
                LOG.info("Send BGP UPDATE Message [%s, %s]"%(local_prefix,
                          nexthop))
            else:
                LOG.info("Send BGP UPDATE Message [%s]"%local_prefix)
                nexthop = "0.0.0.0"
            result_list = self.speaker.prefix_add(local_prefix, nexthop,
                                                  routeDist)
            result = result_list[0]
            label = result['label']
            return label
        else:
            if nexthop:
                LOG.info("Send BGP UPDATE Message [%s, %s]"%(local_prefix,
                          nexthop))
                self.speaker.prefix_add(local_prefix, nexthop)
            else:
                LOG.info("Send BGP UPDATE Message [%s]"%local_prefix)
                self.speaker.prefix_add(local_prefix)


    def remove_prefix(self, ipaddress, netmask, routeDist=None):
        prefix = IPNetwork(ipaddress + '/' + netmask)
        local_prefix = str(prefix.cidr)

        LOG.info("Send BGP UPDATE(withdraw) Message [%s]"%local_prefix)
        self.speaker.prefix_del(local_prefix, routeDist)


    def show_rib(self):
        family ="vpnv4"
        format = "cli"
        return self.speaker.rib_get(family, format)


    def show_vrfs(self):
        format = "cli"
        return self.speaker.vrfs_get(format)


    def show_neighbor(self, routetype, address):
        format = "cli"
        return self.speaker.neighbor_get(routetype, address, format)


    def update_neighbor_med(self, peerIp, med_value):
        conf_type = 'multi_exit_disc'
        conf_value = med_value
        LOG.info("Send BGP UPDATE Message for changing MED[%s]"%med_value)
        return self.speaker.neighbor_update(peerIp, conf_type, conf_value)
Example #24
0
class SDNIP(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
    _CONTEXTS = {
        'fwd': Fwd,
        'hop_db': HopDB
    }

    def __init__(self, *args, **kwargs):
        super(SDNIP, self).__init__(*args, **kwargs)
        self.fwd = kwargs['fwd']
        self.hop_db = kwargs['hop_db']
        self.cfg_mgr = SDNIPConfigManager()
        self.waiters = {}
        self.bgp_speaker =\
            BGPSpeaker(self.cfg_mgr.as_number,
                       str(self.cfg_mgr.router_id),
                       bgp_server_port=self.cfg_mgr.listen_port,
                       best_path_change_handler=self.best_path_change_handler,
                       peer_down_handler=self.peer_down_handler,
                       peer_up_handler=self.peer_up_handler)

        speaker_ids = self.cfg_mgr.get_all_speaker_id()

        for speaker_id in speaker_ids:
            self.bgp_speaker.neighbor_add(speaker_id,
                                          self.cfg_mgr.as_number,
                                          is_next_hop_self=True)

        hub.spawn(self.prefix_check_loop)

        if with_dk:
            dk_plugin.DynamicLoader.register_custom_cmd('sdn-ip:info', self.cmd_self_info)
            dk_plugin.DynamicLoader.register_custom_cmd('sdn-ip:routes', self.cmd_list_routes)
            dk_plugin.DynamicLoader.register_custom_cmd('sdn-ip:flows', self.cmd_get_flows)

    def best_path_change_handler(self, ev):
        self.logger.info('best path changed:')
        self.logger.info('remote_as: %d', ev.remote_as)
        self.logger.info('route_dist: %s', ev.route_dist)
        self.logger.info('prefix: %s', ev.prefix)
        self.logger.info('nexthop: %s', ev.nexthop)
        self.logger.info('label: %s', ev.label)
        self.logger.info('is_withdraw: %s', ev.is_withdraw)
        self.logger.info('')

        # Ignore internal network
        prefix_nw = IPNetwork(ev.prefix)

        for internal_network in self.cfg_mgr.get_internal_networks():
            int_nw = IPNetwork(internal_network)

            if int_nw == prefix_nw:
                self.logger.info('Internal network, ignored.')
                return

        if ev.is_withdraw:
            self.hop_db.withdraw(ev.prefix)
            self.uninstall_best_path(ev.prefix, ev.nexthop)

        else:
            self.hop_db.add_hop(ev.prefix, ev.nexthop)
            self.install_best_path(ev.prefix, ev.nexthop)

    def peer_down_handler(self, remote_ip, remote_as):
        self.logger.info('peer down:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    def peer_up_handler(self, remote_ip, remote_as):
        self.logger.info('peer up:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    def get_host(self, ip):
        hosts = topo_api.get_all_host(self)

        for host in hosts:
            if ip in host.ipv4:
                return host

        return None

    def prefix_check_loop(self):

        while True:
            prefixs_to_install = self.hop_db.get_uninstalled_prefix_list()
            self.logger.debug("prefix to install: %s", str(prefixs_to_install))

            for prefix in prefixs_to_install:
                nexthop = self.hop_db.get_nexthop(prefix)
                self.install_best_path(prefix, nexthop)

            hub.sleep(3)

    def install_best_path(self, prefix, nexthop):

        nexthop_host = self.get_host(nexthop)
        self.logger.debug("nexthop host: %s", str(nexthop_host))
        if nexthop_host is None:
            self.logger.debug("Can't find nexthop host: %s", str(nexthop_host))
            return

        nexthop_port = nexthop_host.port
        nexthop_mac = nexthop_host.mac
        nexthop_dpid = nexthop_port.dpid
        nexthop_port_no = nexthop_port.port_no
        prefix_ip = str(IPNetwork(prefix).ip)
        prefix_mask = str(IPNetwork(prefix).netmask)

        for dp in self.fwd.get_all_datapaths():
            from_dpid = dp.id
            nexthop_match =\
                dp.ofproto_parser.OFPMatch(ipv4_dst=(prefix_ip, prefix_mask),
                                           eth_type=2048)
            pre_actions = [
                dp.ofproto_parser.OFPActionSetField(eth_dst=nexthop_mac)
                ]

            self.fwd.setup_shortest_path(from_dpid,
                                         nexthop_dpid,
                                         nexthop_port_no,
                                         nexthop_match,
                                         pre_actions)

        self.hop_db.install_prefix(prefix)

    def uninstall_best_path(self, prefix, nexthop):

        prefix_ip = str(IPNetwork(prefix).ip)
        prefix_mask = str(IPNetwork(prefix).netmask)

        # remove all flow rule for this prefix
        for dp in self.fwd.get_all_datapaths():
            match =\
                dp.ofproto_parser.OFPMatch(ipv4_dst=(prefix_ip, prefix_mask),
                                       eth_type=2048)
            flow_del = dp.ofproto_parser.OFPFlowMod(datapath=dp,
                                    command=OFPFC_DELETE,
                                    match=match)
            dp.send_msg(flow_del)

    def install_internal_host_path(self, ip):
        host = self.get_host(ip)

        if host is None:
            return

        for dp in self.fwd.get_all_datapaths():
            from_dpid = dp.id
            host_match =\
                dp.ofproto_parser.OFPMatch(ipv4_dst=ip, eth_type=2048)
            pre_actions = [
                dp.ofproto_parser.OFPActionSetField(eth_dst=host.mac)
                ]

            self.fwd.setup_shortest_path(from_dpid,
                                         host.port.dpid,
                                         host.port.port_no,
                                         host_match,
                                         pre_actions)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    @packet_in_filter(RequiredTypeFilter, {'types': [ipv4.ipv4]})
    def internal_host_route_handler(self, ev):
        '''
        Handle internal network host routing
        '''
        msg = ev.msg
        dp = msg.datapath
        dpid = dp.id
        ofproto = dp.ofproto

        pkt = packet.Packet(msg.data)
        ipv4_header = pkt.get_protocol(ipv4.ipv4)

        src_ip = ipv4_header.src
        dst_ip = ipv4_header.dst

        if not self.cfg_mgr.is_internal_host(dst_ip):
            return

        self.install_internal_host_path(dst_ip)

    @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
    def flow_status_reply_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath

        if dp.id not in self.waiters:
            return
        if msg.xid not in self.waiters[dp.id]:
            return
        lock, msgs = self.waiters[dp.id][msg.xid]
        msgs.append(msg)

        flags = 0
        flags = dp.ofproto.OFPMPF_REPLY_MORE

        if msg.flags & flags:
            return
        del self.waiters[dp.id][msg.xid]
        lock.set()

    # commands
    def cmd_self_info(self):
        information = "AS number : {}\n" + \
                      "Router ID: {}\n" + \
                      "BGP port: {}\n"

        information = information.format(self.cfg_mgr.as_number,
                                         str(self.cfg_mgr.router_id),
                                         self.cfg_mgr.listen_port)

        return information

    def cmd_list_routes(self):
        prefix_list = self.hop_db.get_all_prefixes()
        result = "{:<20}{:<17}{}\n".format("Prefix", "Next Hop", "Path installed")

        result = result + "=" * 40 + "\n"

        for prefix in prefix_list:
            result = result + "{:<20}".format(prefix)
            _next_hop = self.hop_db.hops.get(prefix)

            if _next_hop is None:
                _next_hop = "None"

            result = result + "{:<17}".format(_next_hop)
            result = result + str(self.hop_db.is_prefix_installed(prefix))
            result = result + "\n"

        return result

    def cmd_get_flows(self):
        result = ""
        for dp in self.fwd.get_all_datapaths():
            flows = ofctl_v1_3.get_flow_stats(dp, self.waiters, {})

            result = result + "{:0>16}:\n".format(dp.id)
            result = result + "=" * 17 + "\n"

            for flow in flows:
                result = result + json.dumps(flow) + "\n"

        return result
Example #25
0
class SDNIP(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
    _CONTEXTS = {'fwd': Fwd, 'hop_db': HopDB}

    def __init__(self, *args, **kwargs):
        super(SDNIP, self).__init__(*args, **kwargs)
        self.fwd = kwargs['fwd']
        self.hop_db = kwargs['hop_db']
        self.cfg_mgr = SDNIPConfigManager()
        self.waiters = {}
        self.bgp_speaker =\
            BGPSpeaker(self.cfg_mgr.as_number,
                       str(self.cfg_mgr.router_id),
                       bgp_server_port=self.cfg_mgr.listen_port,
                       best_path_change_handler=self.best_path_change_handler,
                       peer_down_handler=self.peer_down_handler,
                       peer_up_handler=self.peer_up_handler)

        speaker_ids = self.cfg_mgr.get_all_speaker_id()

        for speaker_id in speaker_ids:
            self.bgp_speaker.neighbor_add(speaker_id,
                                          self.cfg_mgr.as_number,
                                          is_next_hop_self=True)

        hub.spawn(self.prefix_check_loop)

        if with_dk:
            dk_plugin.DynamicLoader.register_custom_cmd(
                'sdn-ip:info', self.cmd_self_info)
            dk_plugin.DynamicLoader.register_custom_cmd(
                'sdn-ip:routes', self.cmd_list_routes)
            dk_plugin.DynamicLoader.register_custom_cmd(
                'sdn-ip:flows', self.cmd_get_flows)

    def best_path_change_handler(self, ev):
        self.logger.info('best path changed:')
        self.logger.info('remote_as: %d', ev.remote_as)
        self.logger.info('route_dist: %s', ev.route_dist)
        self.logger.info('prefix: %s', ev.prefix)
        self.logger.info('nexthop: %s', ev.nexthop)
        self.logger.info('label: %s', ev.label)
        self.logger.info('is_withdraw: %s', ev.is_withdraw)
        self.logger.info('')

        # Ignore internal network
        prefix_nw = IPNetwork(ev.prefix)

        for internal_network in self.cfg_mgr.get_internal_networks():
            int_nw = IPNetwork(internal_network)

            if int_nw == prefix_nw:
                self.logger.info('Internal network, ignored.')
                return

        if ev.is_withdraw:
            self.hop_db.withdraw(ev.prefix)
            self.uninstall_best_path(ev.prefix, ev.nexthop)

        else:
            self.hop_db.add_hop(ev.prefix, ev.nexthop)
            self.install_best_path(ev.prefix, ev.nexthop)

    def peer_down_handler(self, remote_ip, remote_as):
        self.logger.info('peer down:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    def peer_up_handler(self, remote_ip, remote_as):
        self.logger.info('peer up:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    def get_host(self, ip):
        hosts = topo_api.get_all_host(self)

        for host in hosts:
            if ip in host.ipv4:
                return host

        return None

    def prefix_check_loop(self):

        while True:
            prefixs_to_install = self.hop_db.get_uninstalled_prefix_list()
            self.logger.debug("prefix to install: %s", str(prefixs_to_install))

            for prefix in prefixs_to_install:
                nexthop = self.hop_db.get_nexthop(prefix)
                self.install_best_path(prefix, nexthop)

            hub.sleep(3)

    def install_best_path(self, prefix, nexthop):

        nexthop_host = self.get_host(nexthop)
        self.logger.debug("nexthop host: %s", str(nexthop_host))
        if nexthop_host is None:
            self.logger.debug("Can't find nexthop host: %s", str(nexthop_host))
            return

        nexthop_port = nexthop_host.port
        nexthop_mac = nexthop_host.mac
        nexthop_dpid = nexthop_port.dpid
        nexthop_port_no = nexthop_port.port_no
        prefix_ip = str(IPNetwork(prefix).ip)
        prefix_mask = str(IPNetwork(prefix).netmask)

        for dp in self.fwd.get_all_datapaths():
            from_dpid = dp.id
            nexthop_match =\
                dp.ofproto_parser.OFPMatch(ipv4_dst=(prefix_ip, prefix_mask),
                                           eth_type=2048)
            pre_actions = [
                dp.ofproto_parser.OFPActionSetField(eth_dst=nexthop_mac)
            ]

            self.fwd.setup_shortest_path(from_dpid, nexthop_dpid,
                                         nexthop_port_no, nexthop_match,
                                         pre_actions)

        self.hop_db.install_prefix(prefix)

    def uninstall_best_path(self, prefix, nexthop):

        prefix_ip = str(IPNetwork(prefix).ip)
        prefix_mask = str(IPNetwork(prefix).netmask)

        # remove all flow rule for this prefix
        for dp in self.fwd.get_all_datapaths():
            match =\
                dp.ofproto_parser.OFPMatch(ipv4_dst=(prefix_ip, prefix_mask),
                                       eth_type=2048)
            flow_del = dp.ofproto_parser.OFPFlowMod(datapath=dp,
                                                    command=OFPFC_DELETE,
                                                    match=match)
            dp.send_msg(flow_del)

    def install_internal_host_path(self, ip):
        host = self.get_host(ip)

        if host is None:
            return

        for dp in self.fwd.get_all_datapaths():
            from_dpid = dp.id
            host_match =\
                dp.ofproto_parser.OFPMatch(ipv4_dst=ip, eth_type=2048)
            pre_actions = [
                dp.ofproto_parser.OFPActionSetField(eth_dst=host.mac)
            ]

            self.fwd.setup_shortest_path(from_dpid, host.port.dpid,
                                         host.port.port_no, host_match,
                                         pre_actions)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    @packet_in_filter(RequiredTypeFilter, {'types': [ipv4.ipv4]})
    def internal_host_route_handler(self, ev):
        '''
        Handle internal network host routing
        '''
        msg = ev.msg
        dp = msg.datapath
        dpid = dp.id
        ofproto = dp.ofproto

        pkt = packet.Packet(msg.data)
        ipv4_header = pkt.get_protocol(ipv4.ipv4)

        src_ip = ipv4_header.src
        dst_ip = ipv4_header.dst

        if not self.cfg_mgr.is_internal_host(dst_ip):
            return

        self.install_internal_host_path(dst_ip)

    @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
    def flow_status_reply_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath

        if dp.id not in self.waiters:
            return
        if msg.xid not in self.waiters[dp.id]:
            return
        lock, msgs = self.waiters[dp.id][msg.xid]
        msgs.append(msg)

        flags = 0
        flags = dp.ofproto.OFPMPF_REPLY_MORE

        if msg.flags & flags:
            return
        del self.waiters[dp.id][msg.xid]
        lock.set()

    # commands
    def cmd_self_info(self):
        information = "AS number : {}\n" + \
                      "Router ID: {}\n" + \
                      "BGP port: {}\n"

        information = information.format(self.cfg_mgr.as_number,
                                         str(self.cfg_mgr.router_id),
                                         self.cfg_mgr.listen_port)

        return information

    def cmd_list_routes(self):
        prefix_list = self.hop_db.get_all_prefixes()
        result = "{:<20}{:<17}{}\n".format("Prefix", "Next Hop",
                                           "Path installed")

        result = result + "=" * 40 + "\n"

        for prefix in prefix_list:
            result = result + "{:<20}".format(prefix)
            _next_hop = self.hop_db.hops.get(prefix)

            if _next_hop is None:
                _next_hop = "None"

            result = result + "{:<17}".format(_next_hop)
            result = result + str(self.hop_db.is_prefix_installed(prefix))
            result = result + "\n"

        return result

    def cmd_get_flows(self):
        result = ""
        for dp in self.fwd.get_all_datapaths():
            flows = ofctl_v1_3.get_flow_stats(dp, self.waiters, {})

            result = result + "{:0>16}:\n".format(dp.id)
            result = result + "=" * 17 + "\n"

            for flow in flows:
                result = result + json.dumps(flow) + "\n"

        return result
Example #26
0
class RyuBGPSpeaker(RyuApp):
    """
    Base application for implementing BGP applications.

    This application will notifies
     - ``EventBestPathChanged``
     - ``EventPeerDown``
     - ``EventPeerUp``
    to other BGP applications.
    To catch these events, specify ``@set_ev_cls()`` decorator to the event
    handlers in the Ryu applications.

    Example::

        ...
        from ryu.base import app_manager
        from ryu.controller.handler import set_ev_cls
        from ryu.services.protocols.bgp import application as bgp_application
        ...

        class MyBGPApp(app_manager.RyuApp):
            _CONTEXTS = {
                'ryubgpspeaker': bgp_application.RyuBGPSpeaker,
            }

            ...
            @set_ev_cls(bgp_application.EventBestPathChanged)
            def _best_patch_changed_handler(self, ev):
                self.logger.info(
                    'Best path changed: is_withdraw=%s, path=%s',
                    ev.is_withdraw, ev.path)
    """
    _EVENTS = [
        EventBestPathChanged,
        EventPeerDown,
        EventPeerUp,
    ]

    def __init__(self, *args, **kwargs):
        super(RyuBGPSpeaker, self).__init__(*args, **kwargs)
        self.config_file = CONF.config_file

        # BGPSpeaker instance (not instantiated yet)
        self.speaker = None

    def start(self):
        super(RyuBGPSpeaker, self).start()

        # If configuration file was provided and loaded successfully, we start
        # BGPSpeaker using the given settings.
        # If no configuration file is provided or if any minimum required
        # setting is missing, BGPSpeaker will not be started.
        if self.config_file:
            LOG.debug('Loading config file %s...', self.config_file)
            settings = load_config(self.config_file)

            # Configure logging settings, if available.
            if hasattr(settings, 'LOGGING'):
                # Not implemented yet.
                LOG.debug('Loading LOGGING settings... (NOT implemented yet)')
                # from logging.config import dictConfig
                # logging_settings = dictConfig(settings.LOGGING)

            # Configure BGP settings, if available.
            if hasattr(settings, 'BGP'):
                LOG.debug('Loading BGP settings...')
                self._start_speaker(settings.BGP)

            # Configure SSH settings, if available.
            if hasattr(settings, 'SSH'):
                LOG.debug('Loading SSH settings...')
                # Note: paramiko used in bgp.operator.ssh is the optional
                # requirements, imports bgp.operator.ssh here.
                from ryu.services.protocols.bgp.operator import ssh
                hub.spawn(ssh.SSH_CLI_CONTROLLER.start, **settings.SSH)

        # Start RPC server with the given RPC settings.
        rpc_settings = {
            NC_RPC_BIND_PORT: CONF.rpc_port,
            NC_RPC_BIND_IP: validate_rpc_host(CONF.rpc_host),
        }
        return hub.spawn(NET_CONTROLLER.start, **rpc_settings)

    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Settings for starting BGPSpeaker
        bgp_settings = {}

        # Get required settings.
        try:
            bgp_settings['as_number'] = settings.get(LOCAL_AS)
            bgp_settings['router_id'] = settings.get(ROUTER_ID)
        except KeyError as e:
            raise ApplicationException(
                desc='Required BGP configuration missing: %s' % e)

        # Set event notify handlers if no corresponding handler specified.
        bgp_settings['best_path_change_handler'] = settings.get(
            'best_path_change_handler', self._notify_best_path_changed_event)
        bgp_settings['peer_down_handler'] = settings.get(
            'peer_down_handler', self._notify_peer_down_event)
        bgp_settings['peer_up_handler'] = settings.get(
            'peer_up_handler', self._notify_peer_up_event)

        # Get optional settings.
        bgp_settings[BGP_SERVER_PORT] = settings.get(BGP_SERVER_PORT,
                                                     DEFAULT_BGP_SERVER_PORT)
        bgp_settings[REFRESH_STALEPATH_TIME] = settings.get(
            REFRESH_STALEPATH_TIME, DEFAULT_REFRESH_STALEPATH_TIME)
        bgp_settings[REFRESH_MAX_EOR_TIME] = settings.get(
            REFRESH_MAX_EOR_TIME, DEFAULT_REFRESH_MAX_EOR_TIME)
        bgp_settings[LABEL_RANGE] = settings.get(LABEL_RANGE,
                                                 DEFAULT_LABEL_RANGE)
        bgp_settings['allow_local_as_in_count'] = settings.get(
            'allow_local_as_in_count', 0)

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        self.speaker = BGPSpeaker(**bgp_settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(settings.get('neighbors', []))

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(settings.get('vrfs', []))

        # Add Networks
        LOG.debug('Adding routes...')
        self._add_routes(settings.get('routes', []))

    def _notify_best_path_changed_event(self, ev):
        ev = EventBestPathChanged(ev.path, ev.is_withdraw)
        self.send_event_to_observers(ev)

    def _notify_peer_down_event(self, remote_ip, remote_as):
        ev = EventPeerDown(remote_ip, remote_as)
        self.send_event_to_observers(ev)

    def _notify_peer_up_event(self, remote_ip, remote_as):
        ev = EventPeerUp(remote_ip, remote_as)
        self.send_event_to_observers(ev)

    def _add_neighbors(self, settings):
        """
        Add BGP neighbors from the given settings.

        All valid neighbors are loaded.
        Miss-configured neighbors are ignored and errors are logged.
        """
        for neighbor_settings in settings:
            LOG.debug('Adding neighbor settings: %s', neighbor_settings)
            try:
                self.speaker.neighbor_add(**neighbor_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_vrfs(self, settings):
        """
        Add BGP VRFs from the given settings.

        All valid VRFs are loaded.
        Miss-configured VRFs are ignored and errors are logged.
        """
        for vrf_settings in settings:
            LOG.debug('Adding VRF settings: %s', vrf_settings)
            try:
                self.speaker.vrf_add(**vrf_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_routes(self, settings):
        """
        Add BGP routes from given settings.

        All valid routes are loaded.
        Miss-configured routes are ignored and errors are logged.
        """
        for route_settings in settings:
            if 'prefix' in route_settings:
                prefix_add = self.speaker.prefix_add
            elif 'route_type' in route_settings:
                prefix_add = self.speaker.evpn_prefix_add
            else:
                LOG.debug('Skip invalid route settings: %s', route_settings)
                continue

            LOG.debug('Adding route settings: %s', route_settings)
            try:
                prefix_add(**route_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)
Example #27
0
log.addHandler(logging.StreamHandler(sys.stderr))

from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker


def dump_remote_best_path_change(event):
    print 'the best path changed:', event.remote_as, event.prefix, event.nexthop, event.is_withdraw


def detect_peer_down(remote_ip, remote_as):
    print 'Peer down:', remote_ip, remote_as


if __name__ == "__main__":
    speaker = BGPSpeaker(as_number=20,
                         router_id='1.1.1.1',
                         best_path_change_handler=dump_remote_best_path_change,
                         peer_down_handler=detect_peer_down)
    speaker.neighbor_add("10.108.90.1", 10)
    speaker.neighbor_add("10.108.91.1", 30)
    #speaker.neighbor_add("10.108.92.1",40)

    #print speaker.rib_get()
    #speaker.neighbor_add("10.108.91.1",30)

    #uncomment the below line if the speaker needs to talk with a bmp server
    #speaker.bmp_server_add('192.168.177.2',11019)

    count = 1
    while True:
        eventlet.sleep(10)
        prefix = '10.108.' + str(count) + '.0/24'
Example #28
0
class SDNIP(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
    _CONTEXTS = {
        'fwd': Fwd,
        'hop_db': HopDB
    }

    def __init__(self, *args, **kwargs):
        super(SDNIP, self).__init__(*args, **kwargs)
        self.fwd = kwargs['fwd']
        self.hop_db = kwargs['hop_db']
        self.cfg_mgr = SDNIPConfigManager('config.json')
        self.bgp_speaker =\
        BGPSpeaker(self.cfg_mgr.as_number,
                   self.cfg_mgr.router_id,
                   bgp_server_port=self.cfg_mgr.listen_port,
                   best_path_change_handler=self.best_path_change_handler,
                   peer_down_handler=self.peer_down_handler,
                   peer_up_handler=self.peer_up_handler)

        speaker_ids = self.cfg_mgr.get_all_speaker_id()

        for speaker_id in speaker_ids:
            self.bgp_speaker.neighbor_add(speaker_id,
                                          self.cfg_mgr.as_number,
                                          is_next_hop_self=True)

        hub.spawn(self.prefix_check_loop)

    def best_path_change_handler(self, ev):
        self.logger.info('best path changed:')
        self.logger.info('remote_as: %d', ev.remote_as)
        self.logger.info('route_dist: %s', ev.route_dist)
        self.logger.info('prefix: %s', ev.prefix)
        self.logger.info('nexthop: %s', ev.nexthop)
        self.logger.info('label: %s', ev.label)
        self.logger.info('is_withdraw: %s', ev.is_withdraw)
        self.logger.info('')
        self.hop_db.add_hop(ev.prefix, ev.nexthop)
        self.install_best_path(ev.prefix, ev.nexthop)

    def peer_down_handler(self, remote_ip, remote_as):
        self.logger.info('peer down:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    def peer_up_handler(self, remote_ip, remote_as):
        self.logger.info('peer up:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    def get_nexthop_host(self, ip):
        hosts = topo_api.get_all_host(self)

        for host in hosts:
            if ip in host.ipv4:
                return host

        return None

    def prefix_check_loop(self):

        while True:
            prefixs_to_install = self.hop_db.get_uninstalled_prefix_list()
            self.logger.debug("prefix to install: %s", str(prefixs_to_install))

            for prefix in prefixs_to_install:
                nexthop = self.hop_db.get_nexthop(prefix)
                self.install_best_path(prefix, nexthop)

            hub.sleep(3)

    def install_best_path(self, prefix, nexthop):

        nexthop_host = self.get_nexthop_host(nexthop)
        self.logger.debug("nexthop host: %s", str(nexthop_host))
        if nexthop_host is None:
            return

        nexthop_port = nexthop_host.port
        nexthop_mac = nexthop_host.mac
        nexthop_dpid = nexthop_port.dpid
        nexthop_port_no = nexthop_port.port_no
        prefix_ip = str(IPNetwork(prefix).ip)
        prefix_mask = str(IPNetwork(prefix).netmask)

        for dp in self.fwd.get_all_datapaths():
            from_dpid = dp.id
            nexthop_match =\
            dp.ofproto_parser.OFPMatch(ipv4_dst=(prefix_ip, prefix_mask),
                                       eth_type=2048)
            pre_actions = [
                dp.ofproto_parser.OFPActionSetField(eth_dst=nexthop_mac)
                ]

            self.fwd.setup_shortest_path(from_dpid,
                                         nexthop_dpid,
                                         nexthop_port_no,
                                         nexthop_match,
                                         pre_actions)

        self.hop_db.install_prefix(prefix)
Example #29
0
class RyuBGPSpeaker(RyuApp):

    def __init__(self, *args, **kwargs):
        super(RyuBGPSpeaker, self).__init__(*args, **kwargs)
        self.config_file = CONF.config_file

        # BGPSpeaker instance (not instantiated yet)
        self.speaker = None

    def start(self):
        super(RyuBGPSpeaker, self).start()

        # If configuration file was provided and loaded successfully, we start
        # BGPSpeaker using the given settings.
        # If no configuration file is provided or if any minimum required
        # setting is missing, BGPSpeaker will not be started.
        if self.config_file:
            LOG.debug('Loading config file %s...', self.config_file)
            settings = load_config(self.config_file)

            # Configure logging settings, if available.
            if hasattr(settings, 'LOGGING'):
                # Not implemented yet.
                LOG.debug('Loading LOGGING settings... (NOT implemented yet)')
                # from logging.config import dictConfig
                # logging_settings = dictConfig(settings.LOGGING)

            # Configure BGP settings, if available.
            if hasattr(settings, 'BGP'):
                LOG.debug('Loading BGP settings...')
                self._start_speaker(settings.BGP)

            # Configure SSH settings, if available.
            if hasattr(settings, 'SSH'):
                LOG.debug('Loading SSH settings...')
                hub.spawn(SSH_CLI_CONTROLLER.start, **settings.SSH)

        # Start RPC server with the given RPC settings.
        rpc_settings = {
            NC_RPC_BIND_PORT: CONF.rpc_port,
            NC_RPC_BIND_IP: validate_rpc_host(CONF.rpc_host),
        }
        return hub.spawn(NET_CONTROLLER.start, **rpc_settings)

    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Settings for starting BGPSpeaker
        bgp_settings = {}

        # Get required settings.
        try:
            bgp_settings['as_number'] = settings.get(LOCAL_AS)
            bgp_settings['router_id'] = settings.get(ROUTER_ID)
        except KeyError as e:
            raise ApplicationException(
                desc='Required BGP configuration missing: %s' % e)

        # Get optional settings.
        bgp_settings[BGP_SERVER_PORT] = settings.get(
            BGP_SERVER_PORT, DEFAULT_BGP_SERVER_PORT)
        bgp_settings[REFRESH_STALEPATH_TIME] = settings.get(
            REFRESH_STALEPATH_TIME, DEFAULT_REFRESH_STALEPATH_TIME)
        bgp_settings[REFRESH_MAX_EOR_TIME] = settings.get(
            REFRESH_MAX_EOR_TIME, DEFAULT_REFRESH_MAX_EOR_TIME)
        bgp_settings[LABEL_RANGE] = settings.get(
            LABEL_RANGE, DEFAULT_LABEL_RANGE)

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        self.speaker = BGPSpeaker(**bgp_settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(settings.get('neighbors', []))

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(settings.get('vrfs', []))

        # Add Networks
        LOG.debug('Adding routes...')
        self._add_routes(settings.get('routes', []))

    def _add_neighbors(self, settings):
        """
        Add BGP neighbors from the given settings.

        All valid neighbors are loaded.
        Miss-configured neighbors are ignored and errors are logged.
        """
        for neighbor_settings in settings:
            LOG.debug('Adding neighbor settings: %s', neighbor_settings)
            try:
                self.speaker.neighbor_add(**neighbor_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_vrfs(self, settings):
        """
        Add BGP VRFs from the given settings.

        All valid VRFs are loaded.
        Miss-configured VRFs are ignored and errors are logged.
        """
        for vrf_settings in settings:
            LOG.debug('Adding VRF settings: %s', vrf_settings)
            try:
                self.speaker.vrf_add(**vrf_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_routes(self, settings):
        """
        Add BGP routes from given settings.

        All valid routes are loaded.
        Miss-configured routes are ignored and errors are logged.
        """
        for route_settings in settings:
            if 'prefix' in route_settings:
                prefix_add = self.speaker.prefix_add
            elif 'route_type' in route_settings:
                prefix_add = self.speaker.evpn_prefix_add
            else:
                LOG.debug('Skip invalid route settings: %s', route_settings)
                continue

            LOG.debug('Adding route settings: %s', route_settings)
            try:
                prefix_add(**route_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)
Example #30
0
        event.nexthop, event.is_withdraw

def detect_peer_down(remote_ip, remote_as):
    print 'Peer down:', remote_ip, remote_as


SSH = {
    'ssh_port': 4990,
    'ssh_host': 'localhost',
    'ssh_host_key': '/etc/ssh_host_rsa_key',
    'ssh_username': '******',
    'ssh_password': '******',
}

if __name__ == "__main__":
    speaker = BGPSpeaker(as_number=65005, router_id='172.16.1.174',
                         best_path_change_handler=dump_remote_best_path_change,
                         peer_down_handler=detect_peer_down)

    speaker.neighbor_add('172.16.1.175', 65003)
    count = 0
    while True:
        eventlet.sleep(5)
        prefix = '192.168.' + str(count) + '.0/24'
        print "add a new prefix", prefix
        speaker.prefix_add(prefix)
        count += 1
        print("Neighbors: ", speaker.neighbors_get())
        print("Routes: ", speaker.rib_get())

Example #31
0
from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker

'''
sudo /usr/bin/python2.7 "/home/walber/Dropbox/SDN - Controllers/ryu/ryu/app/COOL/topology_management/bgp_tester.py"
'''

def dump_remote_best_path_change(event):
    print 'the best path changed:', event.remote_as, event.prefix,\
        event.nexthop, event.is_withdraw

def detect_peer_down(remote_ip, remote_as):
    print 'Peer down:', remote_ip, remote_as

if __name__ == "__main__":
    speaker = BGPSpeaker(as_number=65001, router_id='192.168.25.7',
                         best_path_change_handler=dump_remote_best_path_change,
                         peer_down_handler=detect_peer_down)

    speaker.neighbor_add('192.168.25.2', 65002)
    # uncomment the below line if the speaker needs to talk with a bmp server.
    # speaker.bmp_server_add('192.168.177.2', 11019)
    count = 1
    while True:
        print "Oi"
        eventlet.sleep(30)
        prefix = '10.20.' + str(count) + '.0/24'
        print "add a new prefix", prefix
        speaker.prefix_add(prefix)
        count += 1
        if count == 4:
            speaker.shutdown()
Example #32
0
class RyuBGPSpeaker(RyuApp):
    """
    Base application for implementing BGP applications.
    """
    _EVENTS = [
        EventBestPathChanged,
        EventAdjRibInChanged,
        EventPeerDown,
        EventPeerUp,
    ]

    def __init__(self, *args, **kwargs):
        super(RyuBGPSpeaker, self).__init__(*args, **kwargs)
        self.config_file = CONF.config_file

        # BGPSpeaker instance (not instantiated yet)
        self.speaker = None

    def start(self):
        super(RyuBGPSpeaker, self).start()

        # If configuration file was provided and loaded successfully, we start
        # BGPSpeaker using the given settings.
        # If no configuration file is provided or if any minimum required
        # setting is missing, BGPSpeaker will not be started.
        if self.config_file:
            LOG.debug('Loading config file %s...', self.config_file)
            settings = load_config(self.config_file)

            # Configure logging settings, if available.
            if hasattr(settings, 'LOGGING'):
                # Not implemented yet.
                LOG.debug('Loading LOGGING settings... (NOT implemented yet)')
                # from logging.config import dictConfig
                # logging_settings = dictConfig(settings.LOGGING)

            # Configure BGP settings, if available.
            if hasattr(settings, 'BGP'):
                LOG.debug('Loading BGP settings...')
                self._start_speaker(settings.BGP)

            # Configure SSH settings, if available.
            if hasattr(settings, 'SSH'):
                LOG.debug('Loading SSH settings...')
                # Note: paramiko used in bgp.operator.ssh is the optional
                # requirements, imports bgp.operator.ssh here.
                from ryu.services.protocols.bgp.operator import ssh
                hub.spawn(ssh.SSH_CLI_CONTROLLER.start, **settings.SSH)

        # Start RPC server with the given RPC settings.
        rpc_settings = {
            NC_RPC_BIND_PORT: CONF.rpc_port,
            NC_RPC_BIND_IP: validate_rpc_host(CONF.rpc_host),
        }
        return hub.spawn(NET_CONTROLLER.start, **rpc_settings)

    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Check required settings.
        _required_settings = (
            LOCAL_AS,
            ROUTER_ID,
        )
        for required in _required_settings:
            if required not in settings:
                raise ApplicationException(
                    desc='Required BGP configuration missing: %s' % required)

        # Set event notify handlers if no corresponding handler specified.
        settings.setdefault('best_path_change_handler',
                            self._notify_best_path_changed_event)
        settings.setdefault('adj_rib_in_change_handler',
                            self._notify_adj_rib_in_changed_event)
        settings.setdefault('peer_down_handler', self._notify_peer_down_event)
        settings.setdefault('peer_up_handler', self._notify_peer_up_event)

        # Pop settings other than creating BGPSpeaker instance.
        neighbors_settings = settings.pop('neighbors', [])
        vrfs_settings = settings.pop('vrfs', [])
        routes_settings = settings.pop('routes', [])

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        settings.setdefault('as_number', settings.pop(LOCAL_AS))
        self.speaker = BGPSpeaker(**settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(neighbors_settings)

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(vrfs_settings)

        # Add routes
        LOG.debug('Adding routes...')
        self._add_routes(routes_settings)

    def _notify_best_path_changed_event(self, ev):
        ev = EventBestPathChanged(ev.path, ev.is_withdraw)
        self.send_event_to_observers(ev)

    def _notify_adj_rib_in_changed_event(self, ev, peer_ip, peer_as):
        ev = EventAdjRibInChanged(ev.path, ev.is_withdraw, peer_ip, peer_as)
        self.send_event_to_observers(ev)

    def _notify_peer_down_event(self, remote_ip, remote_as):
        ev = EventPeerDown(remote_ip, remote_as)
        self.send_event_to_observers(ev)

    def _notify_peer_up_event(self, remote_ip, remote_as):
        ev = EventPeerUp(remote_ip, remote_as)
        self.send_event_to_observers(ev)

    def _add_neighbors(self, settings):
        """
        Add BGP neighbors from the given settings.

        All valid neighbors are loaded.
        Miss-configured neighbors are ignored and errors are logged.
        """
        for neighbor_settings in settings:
            LOG.debug('Adding neighbor settings: %s', neighbor_settings)
            try:
                self.speaker.neighbor_add(**neighbor_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_vrfs(self, settings):
        """
        Add BGP VRFs from the given settings.

        All valid VRFs are loaded.
        Miss-configured VRFs are ignored and errors are logged.
        """
        for vrf_settings in settings:
            LOG.debug('Adding VRF settings: %s', vrf_settings)
            try:
                self.speaker.vrf_add(**vrf_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_routes(self, settings):
        """
        Add BGP routes from given settings.

        All valid routes are loaded.
        Miss-configured routes are ignored and errors are logged.
        """
        for route_settings in settings:
            if 'prefix' in route_settings:
                prefix_add = self.speaker.prefix_add
            elif 'route_type' in route_settings:
                prefix_add = self.speaker.evpn_prefix_add
            elif 'flowspec_family' in route_settings:
                prefix_add = self.speaker.flowspec_prefix_add
            else:
                LOG.debug('Skip invalid route settings: %s', route_settings)
                continue

            LOG.debug('Adding route settings: %s', route_settings)
            try:
                prefix_add(**route_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)
Example #33
0
import sys
log = logging.getLogger()
log.addHandler(logging.StreamHandler(sys.stderr))

from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker


def dump_remote_best_path_change(event):
    print 'the best path changed:',event.remote_as,event.prefix,event.nexthop,event.is_withdraw

def detect_peer_down(remote_ip,remote_as):
    print 'Peer down:',remote_ip,remote_as

if __name__=="__main__":
    speaker = BGPSpeaker(as_number=20,router_id='1.1.1.1',
                         best_path_change_handler=dump_remote_best_path_change,
                         peer_down_handler=detect_peer_down
                         )
    speaker.neighbor_add("10.108.90.1",10)
    speaker.neighbor_add("10.108.91.1",30)
    #speaker.neighbor_add("10.108.92.1",40)



    #print speaker.rib_get()
    #speaker.neighbor_add("10.108.91.1",30)




    #uncomment the below line if the speaker needs to talk with a bmp server
    #speaker.bmp_server_add('192.168.177.2',11019)
Example #34
0
import eventlet
import json
eventlet.monkey_patch()

import logging
import sys
log = logging.getLogger()
log.addHandler(logging.StreamHandler(sys.stderr))
log.setLevel(logging.DEBUG)

from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker

if __name__ == "__main__":
    speaker = BGPSpeaker(as_number=10, router_id='10.0.0.1',
                         ssh_console=True)


    speaker.neighbor_add('10.9.10.1', 9)
    speaker.neighbor_add('10.5.10.1', 5)
    prefix = '10.0.0.0/8'
    print "add a new prefix", prefix
    speaker.prefix_add(prefix)


    while True:
        eventlet.sleep(5)




Example #35
0
class BGP_Speaker(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self, hosts=None, networks=None, *args, **kwargs):
        super(BGP_Speaker, self).__init__(*args, **kwargs)
        self.networks = networks
        self.hosts = hosts
        # Configuring AS 65501:
        self.as_number = 65001
        #self.remote_as = 65501
        self.router_id = '192.168.25.7'
        self.router_next_hop = "10.0.254.254"  # The source IP of the BGP
        self.listen_port = 179
        self.bgp_speaker = \
            BGPSpeaker(self.as_number,
                       self.router_id,
                       bgp_server_port=self.listen_port,
                       best_path_change_handler=self.best_path_change_handler,
                       peer_down_handler=self.peer_down_handler,
                       peer_up_handler=self.peer_up_handler)
        # print "<<<<<<<<<",self.bgp_speaker

        # speaker = BGPSpeaker(as_number=65001, router_id='192.168.25.7',
        #                      best_path_change_handler=dump_remote_best_path_change,
        #                      peer_down_handler=detect_peer_down)
        self.neighbor1 = Neighbor(ip="192.168.25.2",
                                  asn=65002,
                                  next_hop="10.0.1.254",
                                  border_switch=2,
                                  sw_port=1,
                                  controller_ip="10.0.1.254")
        #self.neighbor2 = Neighbor(ip="10.0.2.2", asn=65002,next_hop="10.0.1.254", border_switch=2, sw_port=2, controller_ip="10.0.1.254")
        # self.neighbor = {"10.0.1.1": {'asn': 65001,'switch':2, 'port': 1,'controller_ip':"10.0.1.254"},
        #                  "10.0.2.2": {'asn': 65002,'switch':2, 'port': 2,'controller_ip':"10.0.2.254"},
        #                  }
        self.neighbors = [self.neighbor1]  #,self.neighbor2]
        #self.local_networks = {"192.168.2.0/24":{'controller_ip':"192.168.2.254"}}
        self.prefix_add(prefix="192.168.2.0/24", next_hop="192.168.2.254")
        # Adding neighbors:
        #TODO: Verify the option of next_hop
        for neighbor in self.neighbors:
            # self.bgp_speaker.neighbor_add(address=neighbor, remote_as=self.neighbor[neighbor]['asn'],
            #                               next_hop=self.router_next_hop,
            #                               is_next_hop_self=True)
            self.neighbors_add(neighbor)
            # for network in self.local_networks:
            #     # Adding prefixes:
            #     self.bgp_speaker.prefix_add(network, self.neighbor[neighbor]['controller_ip'])  # next_hop (how to reach the network)
            #     #self.bgp_speaker.prefix_add("192.168.2.0/24", "10.0.2.254")  # next_hop (how to reach the network)
            #     # self.bgp_speaker.prefix_add("10.0.0.0/24", "10.0.1.1")

        # "10.0.3.1": 'fe:00:00:00:00:03'}
        # self.arp_controller = '00:00:00:00:00:fe'
        # self.monitor_thread = hub.spawn(self._monitor)
        # self.best_paths ={}

        self.prefix_learned = {}  # "198.51.100.0/24",'10.0.1.0/24'}

        self.is_load_balancer_active = False
        self.load_balancer = {}

        #self.monitor_thread = hub.spawn(self.stand_alone)
        print "BGP Speaker started! ;)"
        self.stand_alone()

    def stand_alone(self):
        #print "Oi"
        while True:
            eventlet.sleep(3)
            """ This method returns the BGP adj-RIB-in/adj-RIB-out information
                    in a json format."""
            #print "Sent routes:",self.bgp_speaker.neighbor_get(route_type='sent-routes', address=self.neighbor1.get_IP(),
            #                                    format='json')
            #print '\nReceived-routes:',self.bgp_speaker.neighbor_get(route_type='received-routes',address=self.neighbor1.get_IP(),format='json')
            self.prefix_add("10.0.0.0/24", "10.0.0.1")
            #print self.get_cool_rib(),"\n\n\n"

    def prefix_add(self, prefix, next_hop):
        '''``prefix`` must be the string representation of an IP network
        (e.g., 10.1.1.0/24).

        ``next_hop`` specifies the next hop address for this
        prefix. This parameter is necessary for only VPNv4 and VPNv6
        address families.'''
        self.bgp_speaker.prefix_add(prefix, next_hop)

    def neighbors_add(self, neighbor):
        if isinstance(neighbor, Neighbor):
            self.bgp_speaker.neighbor_add(
                address=neighbor.get_IP(),  #neighbor,
                remote_as=neighbor.get_ASN(),  #self.neighbor[neighbor]['asn'],
                next_hop=neighbor.get_next_hop(),  #self.router_next_hop,
                is_next_hop_self=True)
        else:
            print "Object is not the type Neighbor! type:", type(
                neighbor), type(Neighbor), neighbor

    def get_cool_rib(self):
        # from ryu.services.protocols.bgp.api.base import call
        # show = {
        #     'params': ['rib', 'ipv4'],
        #     'format': format
        # }
        #
        # call('operator.show', **show)
        from ryu.services.protocols.bgp.operator.internal_api import InternalApi
        INTERNAL_API = InternalApi()  #_init_log_handler())

        # table_manager = self.get_core_service().table_manager
        # gtable = table_manager.get_global_table_by_route_family(rf)
        return INTERNAL_API.get_single_rib_routes('ipv4')

    def update_networks_from_rib(self):
        from ryu.services.protocols.bgp.operator.internal_api import InternalApi
        INTERNAL_API = InternalApi()
        rib_bgp = INTERNAL_API.get_single_rib_routes('ipv4')
        print rib_bgp
        to_delete = {}
        for route in rib_bgp:
            prefix = route['prefix']
            paths = route['paths']
            best_hop = None
            list_of_next_hops = []
            for index, path in enumerate(paths):
                aspath = path['aspath']
                if aspath == []:
                    continue
                nexthop = path['nexthop']
                list_of_next_hops.append(nexthop)
                is_best_route = path['best']
                if is_best_route:
                    best_hop = nexthop
                ip = IPNetwork(prefix)  # ("172.16.0.0/24")
                ip_network = str(ip.network)
                # mask_value = ip.prefixlen
                # netmask = ip.netmask
                #print prefix,'\n\n\n'
                if ip_network not in self.networks:
                    switch = self.neighbor[nexthop]['switch']
                    port = self.neighbor[nexthop]['port']
                    controller_ip = None
                    if aspath == []:  # aspath = [] means that this prefix is local
                        controller_ip = self.local_networks[prefix][
                            'controller_ip']
                    else:
                        controller_ip = self.hosts['neighbors'][nexthop][
                            'controller_ip']
                    self.networks[ip_network] = {
                        'mask': str(ip.netmask),
                        'controller_ip': controller_ip,
                        'next_hop': {
                            nexthop: {
                                'switch': switch,
                                'port': port,
                                'bandwidth': 0,
                                'congested': 0
                            }
                        },
                        'as_path': aspath,
                        'best_hop': nexthop
                    }
                else:
                    best_next_hop = self.networks[ip_network]['best_hop']
                    if best_hop != best_next_hop:
                        self.networks[ip_network]['next_hop'][
                            'best_hop'] = best_hop
                    if nexthop not in self.networks[ip_network]['next_hop']:
                        switch = self.neighbor[nexthop]['switch']
                        port = self.neighbor[nexthop]['port']
                        controller_ip = None
                        if aspath == []:  # aspath = [] means that this prefix is local
                            controller_ip = self.local_networks[prefix][
                                'controller_ip']
                        else:
                            controller_ip = self.hosts['neighbors'][nexthop][
                                'controller_ip']
                        self.networks[ip_network]['next_hop'][nexthop] = {
                            'switch': switch,
                            'port': port,
                            'bandwidth': 0,
                            'congested': 0
                        }
                    else:
                        #I  dont know if it is necessary to change
                        pass
                    self.networks[ip_network]['as_path'] = aspath

            ip = IPNetwork(prefix)  # ("172.16.0.0/24")
            ip_network = str(ip.network)
            if ip_network in self.networks:
                for nexthop in self.networks[ip_network]['next_hop']:
                    if nexthop not in list_of_next_hops:
                        del self.networks[ip_network]['next_hop'][nexthop]

                        # How it should be:
        # networks = {'10.0.2.0': {'controller_ip':"10.0.2.254",'mask': '255.255.255.0',
        #                         'next_hop': {"10.0.2.2": {'switch': 2, 'port': 2,'bandwidth': 0,'congested':0}},'best_hop':"10.0.2.2"},
        #         '10.0.1.0': {'controller_ip':"10.0.1.254",'mask': '255.255.255.0',
        #                         'next_hop': {"10.0.1.1": {'switch': 2, 'port': 1,'bandwidth': 0,'congested':0}},'best_hop':"10.0.1.1"},
        #         '172.16.0.0': {'controller_ip':"10.0.1.254",'mask': '255.255.255.0',
        #                         'next_hop': {"10.0.1.1": {'switch': 2, 'port': 1,'bandwidth': 0,'congested':0},
        #                                      "10.0.2.2": {'switch': 2, 'port': 2,'bandwidth': 0,'congested':0}},
        #                                      'best_hop': "10.0.1.1"},
        #         '10.0.254.0': {'controller_ip':"10.0.254.254",'mask': '255.255.255.0',
        #                         'next_hop': {"10.0.254.1": {'switch': 2, 'port': 6,'bandwidth': 0,'congested':0}},'best_hop':"10.0.254.1"}
        #         }

    def peer_down_handler(self, remote_ip, remote_as):
        print "peer_down_handler"
        self.logger.info('peer down:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')
        for network in self.networks.keys():
            for next_hop in self.networks[network]['next_hop'].keys():
                if str(remote_ip) == next_hop:
                    del self.networks[network]['next_hop'][next_hop]

    def peer_up_handler(self, remote_ip, remote_as):
        print "peer_up_handler"
        self.logger.info('peer up:')
        self.logger.info('remote_as: %d', remote_as)
        self.logger.info('remote ip: %s', remote_ip)
        self.logger.info('')

    def best_path_change_handler(self, ev):
        print "Best paht changed! ", ev
        #self.update_networks_from_rib()
        #self.prefix_learned["OI"] = "Path changed!"
        self.logger.info('best path changed:')
        self.logger.info('remote_as: %d', ev.remote_as)
        self.logger.info('route_dist: %s', ev.route_dist)
        self.logger.info('prefix: %s', ev.prefix)
        self.logger.info('nexthop: %s', ev.nexthop)
        self.logger.info('label: %s', ev.label)
        self.logger.info('path: %s', ev.path)
        self.logger.info('peer: %s %s' %
                         (ev.path._source, type(ev.path._source)))
        self.logger.info('peer ip: %s' % ev.path._source.ip_address)
        if True:
            return
        self.logger.info('Port: %s' %
                         self.neighbor[ev.path._source.ip_address]['port'])
        self.logger.info('is_withdraw: %s', ev.is_withdraw)
        self.logger.info('')
        """
        ev.path:
        data: {'path': Path(Peer(ip: 192.168.25.51, asn: 65501)
        peer: Peer(ip: 192.168.25.51, asn: 65501)
        NLRI: network layer reachability information. For IPv4 is all about send prefix information. 
        With other addresses families it can carry other types of information
        Received msg from ('10.0.1.51', '46426') << BGPUpdate(len=52,nlri=[BGPNLRI(addr='198.51.100.0',length=24)],path_attributes=[BGPPathAttributeOrigin(flags=64,length=1,type=1,value=0), BGPPathAttributeAsPath(flags=80,length=10,type=2,value=[[65501, 65500]]), BGPPathAttributeNextHop(flags=64,length=4,type=3,value='10.0.1.51')],total_path_attribute_len=25,type=2,withdrawn_routes=[],withdrawn_routes_len=0)
NLRI: BGPNLRI(addr='198.51.100.0',length=24)
Extracted paths from Update msg.: 
Path(source: Peer(ip: 10.0.1.51, asn: 65501), nlri: BGPNLRI(addr='198.51.100.0',length=24), source ver#: 1, 
path attrs.: {1: BGPPathAttributeOrigin(flags=64,length=1,type=1,value=0), 
2: BGPPathAttributeAsPath(flags=80,length=10,type=2,value=[[65501, 65500]]), 
3: BGPPathAttributeNextHop(flags=64,length=4,type=3,value='10.0.1.51')}, nexthop: 10.0.1.51, is_withdraw: False)

        return ('Path(%s, %s, %s, %s, %s, %s)' % (
            self._source, self._nlri, self._source_version_num,
            self._path_attr_map, self._nexthop, self._is_withdraw))

            Used to pass an update on any best remote path to
            best_path_change_handler.

            ================ ======================================================
            Attribute        Description
            ================ ======================================================
            remote_as        The AS number of a peer that caused this change
            route_dist       None in the case of IPv4 or IPv6 family
            prefix           A prefix was changed
            nexthop          The nexthop of the changed prefix
            label            MPLS label for VPNv4, VPNv6 or EVPN prefix
            path             An instance of ``info_base.base.Path`` subclass
            is_withdraw      True if this prefix has gone otherwise False
            ================ ======================================================
            """

        print "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nCreate a rule for %s with next hop %s and port %s" % (
            ev.prefix, ev.nexthop,
            self.neighbor[ev.path._source.ip_address]['port'])

        print "AS path:", ev.path
        print "AS path attributes:", ev.path._path_attr_map
        print "AS path attributes, AS_Path:", ev.path.get_pattr(
            bgp.BGP_ATTR_TYPE_AS_PATH)
        print "AS path attributes, AS_Path value:", ev.path.get_pattr(
            bgp.BGP_ATTR_TYPE_AS_PATH).value
        # Check if the prefix already has been learned
        if ev.prefix not in self.prefix_learned:
            ip = IPNetwork(ev.prefix)  #("172.16.0.0/24")
            #print ip.network, ip.prefixlen???
            switch = self.neighbor[ev.path._source.ip_address]['switch']
            port = self.neighbor[ev.path._source.ip_address]['port']
            as_path = ev.path.get_pattr(bgp.BGP_ATTR_TYPE_AS_PATH).value
            self.prefix_learned[ev.prefix] = {
                'next_hop': {
                    ev.nexthop: {
                        'switch': switch,
                        'port': port,
                        'as_path': as_path,
                        'neighbor': ev.path._source.ip_address
                    }
                }
            }
        else:
            switch = self.neighbor[ev.path._source.ip_address]['switch']
            port = self.neighbor[ev.path._source.ip_address]['port']
            as_path = ev.path.get_pattr(bgp.BGP_ATTR_TYPE_AS_PATH).value
            if ev.nexthop not in self.prefix_learned[ev.prefix]['next_hop']:
                self.prefix_learned[ev.prefix]['next_hop'] = {
                    ev.nexthop: {
                        'switch': switch,
                        'port': port,
                        'as_path': as_path,
                        'neighbor': ev.path._source.ip_address
                    }
                }
            else:
                self.prefix_learned[ev.prefix]['next_hop'][ev.nexthop] = {
                    'switch': switch,
                    'port': port,
                    'as_path': as_path,
                    'neighbor': ev.path._source.ip_address
                }

            #{'172.16.0.0/24': {'paths': [[65001, 65501]], 'next_hop': '10.0.1.1', 'port': 1, 'neighbor': '10.0.1.1'}}"
            #How it should be:
            # networks = {'10.0.2.0': {'controller_ip':"10.0.2.254",'mask': '255.255.255.0',
            #                         'next_hop': {"10.0.2.2": {'switch': 2, 'port': 2,'bandwidth': 0,'congested':0}},'best_hop':"10.0.2.2"},
            #         '10.0.1.0': {'controller_ip':"10.0.1.254",'mask': '255.255.255.0',
            #                         'next_hop': {"10.0.1.1": {'switch': 2, 'port': 1,'bandwidth': 0,'congested':0}},'best_hop':"10.0.1.1"},
            #         '172.16.0.0': {'controller_ip':"10.0.1.254",'mask': '255.255.255.0',
            #                         'next_hop': {"10.0.1.1": {'switch': 2, 'port': 1,'bandwidth': 0,'congested':0},
            #                                      "10.0.2.2": {'switch': 2, 'port': 2,'bandwidth': 0,'congested':0}},
            #                                      'best_hop': "10.0.1.1"},
            #         '10.0.254.0': {'controller_ip':"10.0.254.254",'mask': '255.255.255.0',
            #                         'next_hop': {"10.0.254.1": {'switch': 2, 'port': 6,'bandwidth': 0,'congested':0}},'best_hop':"10.0.254.1"}
            #         }
            # self.prefix_learned[ev.prefix]['next_hop'] = ev.nexthop
            # self.prefix_learned[ev.prefix]['neighbor'] = ev.path._source.ip_address
            # self.prefix_learned[ev.prefix]["port"] = self.neighbor[ev.path._source.ip_address]['port'],
            # self.prefix_learned[ev.prefix]['paths'] += ev.path.get_pattr(bgp.BGP_ATTR_TYPE_AS_PATH).value

        #   The result self.prefix_learned:
        # {'172.16.0.0/24': {'paths': [[65001]], 'next_hop': '192.168.25.101', 'port': 1, 'neighbor': '192.168.25.101'}}
        if ev.is_withdraw:  # Remove prefix that is withdraw
            ip = IPNetwork(ev.prefix)  # ("172.16.0.0/24")
            ip_network = str(ip.network)
            next_hop = ev.nexthop
Example #36
0
    command += '/super/noreturn'
    command += ' 2> /dev/null'

    return command

class bgpevent(event.EventBase):
    def __init__(self,ev):
        self.remote_as = ev.remote_as
        self.prefix = ev.prefix
        self.nexthop = ev.nexthop
        #self.is_withdraw = ev.is_withdraw


if __name__=="__main__":
    speaker = BGPSpeaker(as_number=20,router_id='1.1.1.2',
                         best_path_change_handler=dump_remote_best_path_change,
                         peer_down_handler=detect_peer_down
                         )
    #speaker.neighbor_add("10.108.90.1",10)
    speaker.neighbor_add("10.108.91.1",30)
    speaker.neighbor_add("10.108.92.1",10)


    print 111111
    print speaker.rib_get()
    print 222222
    #speaker.neighbor_add("10.108.91.1",30)




    #uncomment the below line if the speaker needs to talk with a bmp server
Example #37
0
    def __init__(self, hosts=None, networks=None, *args, **kwargs):
        super(BGP_Speaker, self).__init__(*args, **kwargs)
        self.networks = networks
        self.hosts = hosts
        # Configuring AS 65501:
        self.as_number = 65001
        #self.remote_as = 65501
        self.router_id = '192.168.25.7'
        self.router_next_hop = "10.0.254.254"  # The source IP of the BGP
        self.listen_port = 179
        self.bgp_speaker = \
            BGPSpeaker(self.as_number,
                       self.router_id,
                       bgp_server_port=self.listen_port,
                       best_path_change_handler=self.best_path_change_handler,
                       peer_down_handler=self.peer_down_handler,
                       peer_up_handler=self.peer_up_handler)
        # print "<<<<<<<<<",self.bgp_speaker

        # speaker = BGPSpeaker(as_number=65001, router_id='192.168.25.7',
        #                      best_path_change_handler=dump_remote_best_path_change,
        #                      peer_down_handler=detect_peer_down)
        self.neighbor1 = Neighbor(ip="192.168.25.2",
                                  asn=65002,
                                  next_hop="10.0.1.254",
                                  border_switch=2,
                                  sw_port=1,
                                  controller_ip="10.0.1.254")
        #self.neighbor2 = Neighbor(ip="10.0.2.2", asn=65002,next_hop="10.0.1.254", border_switch=2, sw_port=2, controller_ip="10.0.1.254")
        # self.neighbor = {"10.0.1.1": {'asn': 65001,'switch':2, 'port': 1,'controller_ip':"10.0.1.254"},
        #                  "10.0.2.2": {'asn': 65002,'switch':2, 'port': 2,'controller_ip':"10.0.2.254"},
        #                  }
        self.neighbors = [self.neighbor1]  #,self.neighbor2]
        #self.local_networks = {"192.168.2.0/24":{'controller_ip':"192.168.2.254"}}
        self.prefix_add(prefix="192.168.2.0/24", next_hop="192.168.2.254")
        # Adding neighbors:
        #TODO: Verify the option of next_hop
        for neighbor in self.neighbors:
            # self.bgp_speaker.neighbor_add(address=neighbor, remote_as=self.neighbor[neighbor]['asn'],
            #                               next_hop=self.router_next_hop,
            #                               is_next_hop_self=True)
            self.neighbors_add(neighbor)
            # for network in self.local_networks:
            #     # Adding prefixes:
            #     self.bgp_speaker.prefix_add(network, self.neighbor[neighbor]['controller_ip'])  # next_hop (how to reach the network)
            #     #self.bgp_speaker.prefix_add("192.168.2.0/24", "10.0.2.254")  # next_hop (how to reach the network)
            #     # self.bgp_speaker.prefix_add("10.0.0.0/24", "10.0.1.1")

        # "10.0.3.1": 'fe:00:00:00:00:03'}
        # self.arp_controller = '00:00:00:00:00:fe'
        # self.monitor_thread = hub.spawn(self._monitor)
        # self.best_paths ={}

        self.prefix_learned = {}  # "198.51.100.0/24",'10.0.1.0/24'}

        self.is_load_balancer_active = False
        self.load_balancer = {}

        #self.monitor_thread = hub.spawn(self.stand_alone)
        print "BGP Speaker started! ;)"
        self.stand_alone()
Example #38
0

def dump_remote_best_path_change(event):
    prefix = {"remote_as": event.remote_as, "prefix": event.prefix, "nexthop": event.nexthop}
    prefix_list.append(prefix)
    print "the best path changed:", event.remote_as, event.prefix, event.nexthop, event.is_withdraw


def detect_peer_down(remote_ip, remote_as):
    print "Peer down:", remote_ip, remote_as


if __name__ == "__main__":
    speaker = BGPSpeaker(
        as_number=65000,
        router_id="172.0.255.254",
        best_path_change_handler=dump_remote_best_path_change,
        peer_down_handler=detect_peer_down,
    )

    speaker.neighbor_add("172.0.0.1", 65000, enable_ipv4=True, enable_vpnv4=True, is_next_hop_self=True)
    speaker.neighbor_add("172.0.0.2", 65000, enable_ipv4=True, enable_vpnv4=True, is_next_hop_self=True)
    speaker.neighbor_add("172.0.0.3", 65000, enable_ipv4=True, enable_vpnv4=True, is_next_hop_self=True)
    # uncomment the below line if the speaker needs to talk with a bmp server.
    # speaker.bmp_server_add('192.168.177.2', 11019)
    count = 1
    i_prefix_list = True
    while True:
        eventlet.sleep(5)
        print prefix_list
        if i_prefix_list:
            for prefix in prefix_list:
Example #39
0
    null = ''
    true = 'True'
    false = 'False'
    Flag = False
    status_bgp = speaker.neighbor_state_get()
    status = json.loads(status_bgp)
    for key in status.keys():
        if status[key]['info']['bgp_state'] != 'Established':
            logging.info('neighbor is abornamal .please check peer {}'.format(key))
            Flag = True
    return Flag


if __name__ == "__main__":
    speaker = BGPSpeaker(as_number=100, router_id='10.0.0.82',
                         best_path_change_handler=dump_remote_best_path_change,
                         peer_down_handler=detect_peer_down)

    speaker.neighbor_add('10.0.0.81', 100)

    # uncomment the below line if the speaker needs to talk with a bmp server.
    # speaker.bmp_server_add('192.168.177.2', 11019)
    time.sleep(5)
    while True:
        print(datetime.datetime.now())
        if (get_bgp_status()):
            logging.warning("~~~~~~~~~~~~~~~~~~~~~")
            db_from_bgp.clear()
        else:
            compare_db()
        eventlet.sleep(6)
Example #40
0
class RyuBGPSpeaker(RyuApp):
    def __init__(self, *args, **kwargs):
        super(RyuBGPSpeaker, self).__init__(*args, **kwargs)
        self.config_file = CONF.config_file

        # BGPSpeaker instance (not instantiated yet)
        self.speaker = None

    def start(self):
        super(RyuBGPSpeaker, self).start()

        # If configuration file was provided and loaded successfully, we start
        # BGPSpeaker using the given settings.
        # If no configuration file is provided or if any minimum required
        # setting is missing, BGPSpeaker will not be started.
        if self.config_file:
            LOG.debug('Loading config file %s...', self.config_file)
            settings = load_config(self.config_file)

            # Configure logging settings, if available.
            if hasattr(settings, 'LOGGING'):
                # Not implemented yet.
                LOG.debug('Loading LOGGING settings... (NOT implemented yet)')
                # from logging.config import dictConfig
                # logging_settings = dictConfig(settings.LOGGING)

            # Configure BGP settings, if available.
            if hasattr(settings, 'BGP'):
                LOG.debug('Loading BGP settings...')
                self._start_speaker(settings.BGP)

            # Configure SSH settings, if available.
            if hasattr(settings, 'SSH'):
                LOG.debug('Loading SSH settings...')
                hub.spawn(SSH_CLI_CONTROLLER.start, **settings.SSH)

        # Start RPC server with the given RPC settings.
        rpc_settings = {
            NC_RPC_BIND_PORT: CONF.rpc_port,
            NC_RPC_BIND_IP: validate_rpc_host(CONF.rpc_host),
        }
        return hub.spawn(NET_CONTROLLER.start, **rpc_settings)

    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Settings for starting BGPSpeaker
        bgp_settings = {}

        # Get required settings.
        try:
            bgp_settings['as_number'] = settings.get(LOCAL_AS)
            bgp_settings['router_id'] = settings.get(ROUTER_ID)
        except KeyError as e:
            raise ApplicationException(
                desc='Required BGP configuration missing: %s' % e)

        # Get optional settings.
        bgp_settings[BGP_SERVER_PORT] = settings.get(BGP_SERVER_PORT,
                                                     DEFAULT_BGP_SERVER_PORT)
        bgp_settings[REFRESH_STALEPATH_TIME] = settings.get(
            REFRESH_STALEPATH_TIME, DEFAULT_REFRESH_STALEPATH_TIME)
        bgp_settings[REFRESH_MAX_EOR_TIME] = settings.get(
            REFRESH_MAX_EOR_TIME, DEFAULT_REFRESH_MAX_EOR_TIME)
        bgp_settings[LABEL_RANGE] = settings.get(LABEL_RANGE,
                                                 DEFAULT_LABEL_RANGE)

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        self.speaker = BGPSpeaker(**bgp_settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(settings.get('neighbors', []))

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(settings.get('vrfs', []))

        # Add Networks
        LOG.debug('Adding routes...')
        self._add_routes(settings.get('routes', []))

    def _add_neighbors(self, settings):
        """
        Add BGP neighbors from the given settings.

        All valid neighbors are loaded.
        Miss-configured neighbors are ignored and errors are logged.
        """
        for neighbor_settings in settings:
            LOG.debug('Adding neighbor settings: %s', neighbor_settings)
            try:
                self.speaker.neighbor_add(**neighbor_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_vrfs(self, settings):
        """
        Add BGP VRFs from the given settings.

        All valid VRFs are loaded.
        Miss-configured VRFs are ignored and errors are logged.
        """
        for vrf_settings in settings:
            LOG.debug('Adding VRF settings: %s', vrf_settings)
            try:
                self.speaker.vrf_add(**vrf_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_routes(self, settings):
        """
        Add BGP routes from given settings.

        All valid routes are loaded.
        Miss-configured routes are ignored and errors are logged.
        """
        for route_settings in settings:
            if 'prefix' in route_settings:
                prefix_add = self.speaker.prefix_add
            elif 'route_type' in route_settings:
                prefix_add = self.speaker.evpn_prefix_add
            else:
                LOG.debug('Skip invalid route settings: %s', route_settings)
                continue

            LOG.debug('Adding route settings: %s', route_settings)
            try:
                prefix_add(**route_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)
Example #41
0
class RyuBGPSpeaker(RyuApp):
    """
    Base application for implementing BGP applications.

    This application will notifies
     - ``EventBestPathChanged``
     - ``EventPeerDown``
     - ``EventPeerUp``
    to other BGP applications.
    To catch these events, specify ``@set_ev_cls()`` decorator to the event
    handlers in the Ryu applications.

    Example::

        ...
        from ryu.base import app_manager
        from ryu.controller.handler import set_ev_cls
        from ryu.services.protocols.bgp import application as bgp_application
        ...

        class MyBGPApp(app_manager.RyuApp):
            _CONTEXTS = {
                'ryubgpspeaker': bgp_application.RyuBGPSpeaker,
            }

            ...
            @set_ev_cls(bgp_application.EventBestPathChanged)
            def _best_patch_changed_handler(self, ev):
                self.logger.info(
                    'Best path changed: is_withdraw=%s, path=%s',
                    ev.is_withdraw, ev.path)
    """
    _EVENTS = [
        EventBestPathChanged,
        EventPeerDown,
        EventPeerUp,
    ]

    def __init__(self, *args, **kwargs):
        super(RyuBGPSpeaker, self).__init__(*args, **kwargs)
        self.config_file = CONF.config_file

        # BGPSpeaker instance (not instantiated yet)
        self.speaker = None

    def start(self):
        super(RyuBGPSpeaker, self).start()

        # If configuration file was provided and loaded successfully, we start
        # BGPSpeaker using the given settings.
        # If no configuration file is provided or if any minimum required
        # setting is missing, BGPSpeaker will not be started.
        if self.config_file:
            LOG.debug('Loading config file %s...', self.config_file)
            settings = load_config(self.config_file)

            # Configure logging settings, if available.
            if hasattr(settings, 'LOGGING'):
                # Not implemented yet.
                LOG.debug('Loading LOGGING settings... (NOT implemented yet)')
                # from logging.config import dictConfig
                # logging_settings = dictConfig(settings.LOGGING)

            # Configure BGP settings, if available.
            if hasattr(settings, 'BGP'):
                LOG.debug('Loading BGP settings...')
                self._start_speaker(settings.BGP)

            # Configure SSH settings, if available.
            if hasattr(settings, 'SSH'):
                LOG.debug('Loading SSH settings...')
                # Note: paramiko used in bgp.operator.ssh is the optional
                # requirements, imports bgp.operator.ssh here.
                from ryu.services.protocols.bgp.operator import ssh
                hub.spawn(ssh.SSH_CLI_CONTROLLER.start, **settings.SSH)

        # Start RPC server with the given RPC settings.
        rpc_settings = {
            NC_RPC_BIND_PORT: CONF.rpc_port,
            NC_RPC_BIND_IP: validate_rpc_host(CONF.rpc_host),
        }
        return hub.spawn(NET_CONTROLLER.start, **rpc_settings)

    def _start_speaker(self, settings):
        """
        Starts BGPSpeaker using the given settings.
        """
        # Check required settings.
        _required_settings = (
            LOCAL_AS,
            ROUTER_ID,
        )
        for required in _required_settings:
            if required not in settings:
                raise ApplicationException(
                    desc='Required BGP configuration missing: %s' % required)

        # Set event notify handlers if no corresponding handler specified.
        settings.setdefault(
            'best_path_change_handler', self._notify_best_path_changed_event)
        settings.setdefault(
            'peer_down_handler', self._notify_peer_down_event)
        settings.setdefault(
            'peer_up_handler', self._notify_peer_up_event)

        # Pop settings other than creating BGPSpeaker instance.
        neighbors_settings = settings.pop('neighbors', [])
        vrfs_settings = settings.pop('vrfs', [])
        routes_settings = settings.pop('routes', [])

        # Create BGPSpeaker instance.
        LOG.debug('Starting BGPSpeaker...')
        settings.setdefault('as_number', settings.pop(LOCAL_AS))
        self.speaker = BGPSpeaker(**settings)

        # Add neighbors.
        LOG.debug('Adding neighbors...')
        self._add_neighbors(neighbors_settings)

        # Add VRFs.
        LOG.debug('Adding VRFs...')
        self._add_vrfs(vrfs_settings)

        # Add routes
        LOG.debug('Adding routes...')
        self._add_routes(routes_settings)

    def _notify_best_path_changed_event(self, ev):
        ev = EventBestPathChanged(ev.path, ev.is_withdraw)
        self.send_event_to_observers(ev)

    def _notify_peer_down_event(self, remote_ip, remote_as):
        ev = EventPeerDown(remote_ip, remote_as)
        self.send_event_to_observers(ev)

    def _notify_peer_up_event(self, remote_ip, remote_as):
        ev = EventPeerUp(remote_ip, remote_as)
        self.send_event_to_observers(ev)

    def _add_neighbors(self, settings):
        """
        Add BGP neighbors from the given settings.

        All valid neighbors are loaded.
        Miss-configured neighbors are ignored and errors are logged.
        """
        for neighbor_settings in settings:
            LOG.debug('Adding neighbor settings: %s', neighbor_settings)
            try:
                self.speaker.neighbor_add(**neighbor_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_vrfs(self, settings):
        """
        Add BGP VRFs from the given settings.

        All valid VRFs are loaded.
        Miss-configured VRFs are ignored and errors are logged.
        """
        for vrf_settings in settings:
            LOG.debug('Adding VRF settings: %s', vrf_settings)
            try:
                self.speaker.vrf_add(**vrf_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)

    def _add_routes(self, settings):
        """
        Add BGP routes from given settings.

        All valid routes are loaded.
        Miss-configured routes are ignored and errors are logged.
        """
        for route_settings in settings:
            if 'prefix' in route_settings:
                prefix_add = self.speaker.prefix_add
            elif 'route_type' in route_settings:
                prefix_add = self.speaker.evpn_prefix_add
            elif 'flowspec_family' in route_settings:
                prefix_add = self.speaker.flowspec_prefix_add
            else:
                LOG.debug('Skip invalid route settings: %s', route_settings)
                continue

            LOG.debug('Adding route settings: %s', route_settings)
            try:
                prefix_add(**route_settings)
            except RuntimeConfigError as e:
                LOG.exception(e)
Example #42
0
class SDNIPSApp(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
    _CONTEXTS = {'wsgi': WSGIApplication}

    def __init__(self, *args, **kwargs):
        super(SDNIPSApp, self).__init__(*args, **kwargs)
        self.net = nx.DiGraph()
        wsgi = kwargs['wsgi']
        wsgi.register(SDNIPSWSGIApp, {myapp_name: self})
        self.eline_map = {}
        self.bgp_config = {}
        self.bgp_speaker = None
        self.rcv_prefixes = []
        self.flows = {}
        self.contention_vrf = {}
        self.quarantine = {}
        load_config_thread = Thread(target=self.load_config, args=())
        load_config_thread.start()

    def __exit__(self, exc_type, exc_value, traceback):
        for prefix in self.rcv_prefixes:
            os.system('/sbin/ip route del %s' % prefix)

    def load_config(self):
        try:
            with open('sdn-ips-config.json', 'r') as fp:
                data = jsonpickle.decode(fp.read())
        except Exception as e:
            print "Fail to load SDN-IPS config. Error: %s" % (e)
            return

        retry = 0
        sleep(15)
        while set(data['nodes']) != set(self.net.nodes()) and retry < 10:
            print "Nodes are missing or topology is different! Trying in 15s.."
            sleep(15)
            retry += 1

        if retry == 10:
            print "Could not load config because some nodes are missing or topology is different!"
            return

        # Reinstall flows
        for dpid in data.get('flows', []):
            for flow in data['flows'][dpid]:
                dp = self.net.node[int(dpid)]['conn']
                self.add_flow(dp, flow['priority'], flow['match'],
                              flow['actions'])

        # Recreate BGP speaker
        if 'as_number' in data['bgp'] and 'router_id' in data['bgp']:
            self.bgp_create(data['bgp']['as_number'],
                            str(data['bgp']['router_id']))
            for neigh in data['bgp'].get('neighbors', []):
                neigh['address'] = str(neigh['address'])
                self.bgp_add_neighbor(**neigh)
            for prefix in data['bgp'].get('adv_prefixes', []):
                self.bgp_add_prefix(str(prefix))

        # save contention VRF
        self.contention_vrf = data['contention_vrf']

    def persist_config(self):
        data = {}
        # Topology information
        data['nodes'] = self.net.nodes()
        # BGP config
        data['bgp'] = self.bgp_config
        # OpenFlow rules
        data['flows'] = self.flows
        # Contention VRF
        data['contention_vrf'] = self.contention_vrf

        try:
            with open('sdn-ips-config.json', 'w') as fp:
                fp.write(jsonpickle.encode(data))
        except Exception as e:
            print "Fail to save SDN-IPS config! Error: %s" % (e)

    @set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
    def datapath_handler(self, ev):
        ofproto = ev.dp.ofproto
        if ev.enter:
            ports = {}
            for p in ev.ports:
                if p.port_no != ofproto.OFPP_LOCAL:
                    ports[p.port_no] = {'name': p.name, 'hw_addr': p.hw_addr}
            self.net.add_node(ev.dp.id, **{'ports': ports, 'conn': ev.dp})
            print 'OFPStateChange switch entered: dpid=%s' % (
                dpid_lib.dpid_to_str(ev.dp.id))
        else:
            print 'OFPStateChange switch leaves: dpid=%s' % (
                dpid_lib.dpid_to_str(ev.dp.id))
            self.net.remove_node(ev.dp.id)

    topo_events = [
        event.EventSwitchEnter, event.EventPortAdd, event.EventLinkAdd
    ]

    @set_ev_cls(topo_events)
    def get_topology_data(self, ev):
        switch_list = get_switch(self, None)
        links_list = get_link(self, None)
        links = []
        for link in links_list:
            # check for unwanted nodes and links
            if link.src.dpid not in self.net.nodes(
            ) or link.dst.dpid not in self.net.nodes():
                continue
            if self.net.has_edge(link.src.dpid, link.dst.dpid):
                continue
            links.append((link.src.dpid, link.dst.dpid, {
                'sport': link.src.port_no,
                'dport': link.dst.port_no
            }))
        if not links:
            return
        print "Update graph edges:"
        for l in links:
            print "==> %s:%d <-> %s:%d" % (dpid_lib.dpid_to_str(
                l[0]), l[2]['sport'], dpid_lib.dpid_to_str(
                    l[1]), l[2]['dport'])
        self.net.add_edges_from(links)

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # invalidate all previews rules
        clear = parser.OFPFlowMod(datapath=datapath,
                                  command=ofproto.OFPFC_DELETE)
        datapath.send_msg(clear)

        # install table-miss flow entry
        match = {}
        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER)]
        self.add_flow(datapath, 65530, match, actions, visible=False)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        msg = ev.msg
        dpid = msg.datapath.id
        pkt = packet.Packet(msg.data)
        eth_pkt = pkt.get_protocol(ethernet.ethernet)

        if eth_pkt.ethertype == ether_types.ETH_TYPE_LLDP:
            return

        ip_pkt = pkt.get_protocol(ipv4.ipv4)
        if ip_pkt and str(ip_pkt.src) in self.quarantine:
            vlan_pkt = pkt.get_protocol(vlan.vlan)
            vlan_id = 0
            if vlan_pkt:
                vlan_id = vlan_pkt.vid
            if vlan_id not in self.eline_map:
                print "Error: packet received from an infected host but with wrong vlanid"
                return
            redirect_to = self.quarantine[str(ip_pkt.src)]
            self.contention_quarantine_redirect(msg.datapath, ip_pkt,
                                                redirect_to, vlan_id)
            return

        print "PacketIn dpid=%s inport=%s src=%s dst=%s ethertype=0x%04x" % \
                (dpid, msg.in_port, eth_pkt.src, eth_pkt.dst, eth_pkt.ethertype)

    def get_access_ports(self, sw):
        if sw not in self.net.nodes():
            return None
        ports = self.net.node[sw]['ports'].keys()
        for e in self.net.edge[sw]:
            ports.remove(self.net.edge[sw][e]['sport'])
        return ports

    def add_flow(self,
                 datapath,
                 priority,
                 match,
                 actions,
                 idle_timeout=0,
                 visible=True):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        match_ofp = self.build_match(datapath, **match)
        mod = parser.OFPFlowMod(datapath=datapath,
                                priority=priority,
                                idle_timeout=idle_timeout,
                                match=match_ofp,
                                actions=actions)
        datapath.send_msg(mod)

        if visible:
            self.flows.setdefault(datapath.id, [])
            self.flows[datapath.id].append({
                'match': match,
                'priority': priority,
                'actions': actions
            })
            self.persist_config()

    def build_match(self,
                    datapath,
                    in_port=0,
                    dl_type=0,
                    dl_src=0,
                    dl_dst=0,
                    dl_vlan=0,
                    nw_src=0,
                    src_mask=32,
                    nw_dst=0,
                    dst_mask=32,
                    nw_proto=0,
                    nw_tos=None,
                    tp_src=0,
                    tp_dst=0):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        # Match
        nw_tos = 0
        wildcards = ofp.OFPFW_ALL
        if in_port:
            wildcards &= ~ofp.OFPFW_IN_PORT
        if dl_type:
            wildcards &= ~ofp.OFPFW_DL_TYPE
        if dl_src:
            wildcards &= ~ofp.OFPFW_DL_SRC
        if dl_dst:
            wildcards &= ~ofp.OFPFW_DL_DST
        if dl_vlan:
            wildcards &= ~ofp.OFPFW_DL_VLAN
        if nw_tos:
            wildcards &= ~ofp.OFPFW_NW_TOS
        if nw_src:
            v = (32 - src_mask) << ofp.OFPFW_NW_SRC_SHIFT | \
                ~ofp.OFPFW_NW_SRC_MASK
            wildcards &= v
        if nw_dst:
            v = (32 - dst_mask) << ofp.OFPFW_NW_DST_SHIFT | \
                ~ofp.OFPFW_NW_DST_MASK
            wildcards &= v
        if nw_proto:
            wildcards &= ~ofp.OFPFW_NW_PROTO
        if tp_src:
            wildcards &= ~ofp.OFPFW_TP_SRC
        if tp_dst:
            wildcards &= ~ofp.OFPFW_TP_DST

        match = ofp_parser.OFPMatch(wildcards, in_port, dl_src, dl_dst,
                                    dl_vlan, 0, dl_type, nw_tos, nw_proto,
                                    nw_src, nw_dst, tp_src, tp_dst, src_mask,
                                    dst_mask)
        return match

    def create_eline(self, uniA_sw, uniA_port, uniB_sw, uniB_port, vlanid):
        # sanity check
        if vlanid in self.eline_map:
            return (
                False,
                "E-line already exists with the same vlan_id! Choose another vlanid"
            )

        path = nx.shortest_path(self.net, uniA_sw, uniB_sw)
        print "==> create_eline(UNI-A=%s:%s, UNI-B=%s:%s, vlanid=%d): %s" % \
                (uniA_sw, uniA_port, uniB_sw, uniB_port, vlanid, path)
        for i in range(len(path)):
            sw = path[i]
            buff_id = None
            if i == 0:  # first switch
                match_in_port = uniA_port
            else:
                prev_sw = path[i - 1]
                match_in_port = self.net.edge[prev_sw][sw]['dport']
            if i == len(path) - 1:
                action_out_port = uniB_port
            else:
                next_sw = path[i + 1]
                action_out_port = self.net.edge[sw][next_sw]['sport']
            dp = self.net.node[sw]['conn']
            # uniA -> uniB
            self.logger.info(
                "==> add_flow sw=%s (->) in_port=%s vlanid=%d action_out_port=%s",
                sw, match_in_port, vlanid, action_out_port)
            match = {'in_port': match_in_port, 'dl_vlan': vlanid}
            actions = [dp.ofproto_parser.OFPActionOutput(action_out_port)]
            self.add_flow(dp, 65533, match, actions)
            # uniB -> uniA
            match_in_port, action_out_port = action_out_port, match_in_port
            self.logger.info(
                "==> add_flow sw=%s (<-) in_port=%s vlanid=%d action_out_port=%s",
                sw, match_in_port, vlanid, action_out_port)
            match = {'in_port': match_in_port, 'dl_vlan': vlanid}
            actions = [dp.ofproto_parser.OFPActionOutput(action_out_port)]
            self.add_flow(dp, 65533, match, actions)

        uniA_bkbport = self.net.edge[uniA_sw][path[1]]['sport']
        uniB_bkbport = self.net.edge[path[-2]][uniB_sw]['dport']
        self.eline_map.setdefault(vlanid, {})
        self.eline_map[vlanid][uniA_sw] = {
            'access_port': uniA_port,
            'bkb_port': uniA_bkbport
        }
        self.eline_map[vlanid][uniB_sw] = {
            'access_port': uniB_port,
            'bkb_port': uniB_bkbport
        }

        return (True, 'Success')

    def bgp_create(self, as_number, router_id):
        # MUDAR AQUI - INICIO
        try:
            self.bgp_speaker = BGPSpeaker(
                as_number=as_number,
                router_id=router_id,
                best_path_change_handler=self.best_path_change_handler,
                adj_rib_in_change_handler=self.adj_rib_in_change_handler,
                peer_down_handler=self.peer_down_handler,
                peer_up_handler=self.peer_up_handler)
        except Exception as e:
            print "Error creating bgp speaker: %s" % (e)
            return (False, 'Failed to create BGP speaker')
        # MUDAR AQUI - FIM

        self.bgp_config['as_number'] = as_number
        self.bgp_config['router_id'] = router_id
        self.bgp_config['neighbors'] = []
        self.bgp_config['adv_prefixes'] = []
        self.persist_config()
        return (True, 'Success')

    def bgp_add_neighbor(self,
                         address,
                         remote_as,
                         enable_ipv4=True,
                         enable_ipv6=False,
                         enable_ipv4fs=False,
                         enable_ipv6fs=False):
        # MUDAR AQUI - INICIO
        try:
            self.bgp_speaker.neighbor_add(address,
                                          remote_as,
                                          enable_ipv4=enable_ipv4,
                                          enable_ipv6=enable_ipv6,
                                          enable_ipv4fs=enable_ipv4fs,
                                          enable_ipv6fs=enable_ipv6fs)
        except Exception as e:
            print "Error on bgp_add_neighbor: %s" % (e)
            return (False, 'Failed to add BGP neighbor')
        # MUDAR AQUI - FIM

        self.bgp_config['neighbors'].append({
            'address': address,
            'remote_as': remote_as,
            'enable_ipv4': enable_ipv4,
            'enable_ipv6': enable_ipv6,
            'enable_ipv4fs': enable_ipv4fs,
            'enable_ipv6fs': enable_ipv6fs
        })
        self.persist_config()
        return (True, 'Success')

    def bgp_add_prefix(self, prefix):
        # MUDAR AQUI - INICIO
        try:
            self.bgp_speaker.prefix_add(prefix)
        except Exception as e:
            print "Error on bgp_add_prefix: %s" % (e)
            return (False, 'Failed to add prefix')
        # MUDAR AQUI - FIM

        self.bgp_config['adv_prefixes'].append(prefix)
        self.persist_config()
        return (True, 'Success')

    def best_path_change_handler(self, event):
        action = 'del' if event.is_withdraw else 'add'
        print 'the best path changed: remote-as=%s prefix=%s next-hop=%s action=%s' % \
                (event.remote_as, event.prefix, event.nexthop, action)
        os.system('/sbin/sysctl net.ipv4.ip_forward=1')
        os.system('/sbin/ip route %s %s via %s' %
                  (action, event.prefix, event.nexthop))
        if event.is_withdraw:
            try:
                self.rcv_prefixes.remove(event.prefix)
            except:
                pass
        else:
            self.rcv_prefixes.append(event.prefix)

    def adj_rib_in_change_handler(self, event, peer_ip, peer_asn):
        if isinstance(event.path, (IPv4FlowSpecPath, IPv6FlowSpecPath)):
            #print "formatted_nlri=%s" % (event.path.nlri.formatted_nlri_str)
            #print "path=%s" % (event.path)
            #print "pattrs=%s" % (event.path.pathattr_map)
            extcomm = event.path.get_pattr(
                bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES, [])
            if extcomm:
                extcomm = extcomm.communities
            #print "BGPExtendedCommunities=%s" % (extcomm)
            self.bgp_update_flowspec(event.path.nlri.rules, extcomm)

    def bgp_update_flowspec(self, nlri_rules, extcomm):
        matches = {}
        for rule in nlri_rules:
            if isinstance(rule, bgp.FlowSpecDestPrefix):
                matches['nw_dst'] = rule.addr
                matches['dst_mask'] = rule.length
            elif isinstance(rule, bgp.FlowSpecSrcPrefix):
                matches['nw_src'] = rule.addr
                matches['src_mask'] = rule.length
            elif isinstance(rule, bgp.FlowSpecIPProtocol):
                matches['nw_proto'] = rule.value
            elif isinstance(rule, bgp.FlowSpecPort):
                #TODO: since openflow rules does not have an operator to OR (dst port
                # or src port), then we should create two rules: one for src port and
                # other for dst port
                pass
            elif isinstance(rule, bgp.FlowSpecDestPort):
                matches['tp_dst'] = rule.value
            elif isinstance(rule, bgp.FlowSpecSrcPort):
                matches['tp_src'] = rule.value
        print "matches: %s" % (matches)
        actions = {}
        for c in extcomm:
            if isinstance(c, bgp.BGPFlowSpecTrafficRateCommunity):
                if c.rate_info > 0.0:
                    actions['rate-limit'] = c.rate_info
                    # TODO: implement rate-limit when QoS queues is available
                else:
                    actions['discard'] = True
                    # TODO: make use of the other matches attributes such as tp_dst, proto,...
                    self.contention_block(matches['nw_src'])
            elif isinstance(c, bgp.BGPFlowSpecRedirectCommunity):
                rtcomm = "%d:%d" % (c.as_number, c.local_administrator)
                nexthop = self.contention_vrf.get(rtcomm, None)
                if nexthop:
                    actions['redirect-to-nexthop'] = nexthop
                    # TODO: make use of the other matches attributes such as tp_dst, proto,...
                    self.contention_quarantine(matches['nw_src'], nexthop)
        print "actions: %s" % (actions)

    def peer_down_handler(self, remote_ip, remote_as):
        print 'Peer down:', remote_ip, remote_as

    def peer_up_handler(self, remote_ip, remote_as):
        print 'Peer up:', remote_ip, remote_as

    def flow_create_mirror(self, dpid, flow, to_port):
        try:
            dp = self.net.node[dpid]['conn']
        except:
            return (False, 'dpid not found!')
        parser = dp.ofproto_parser

        new_action = parser.OFPActionOutput(to_port)

        # check if the port is already on flow actions, and just return
        # in this case since we have nothing to do
        if new_action in flow['actions']:
            return (True, 'Success - to_port already in flow actions')

        flow['actions'].append(new_action)

        try:
            match_ofp = self.build_match(dp, **flow['match'])
            mod = parser.OFPFlowMod(datapath=dp,
                                    priority=flow['priority'],
                                    command=dp.ofproto.OFPFC_MODIFY_STRICT,
                                    match=match_ofp,
                                    actions=flow['actions'])
            dp.send_msg(mod)
        except Exception as e:
            return (False, 'Error installing flow_mod: %s' % (e))

        return (True, 'Success')

    def flows_create_mirror(self, dpid, flows, target_sw, target_port):
        try:
            path = nx.shortest_path(self.net, dpid, target_sw)
        except:
            return (
                False,
                'Failed to create mirror! Could not find a path from %s to %s'
                %
                (dpid_lib.dpid_to_str(dpid), dpid_lib.dpid_to_str(target_sw)))

        # determine the first output port for remote mirroring
        if len(path) == 1:
            return (
                False,
                'Failed to create mirror. Currently we dont support mirror to the same switch'
            )

        # for the first switch, we just modify the openflow rules adding a new action
        # to output the traffic to the next switch (remote mirroring)
        next_sw = path[1]
        first_port = self.net.edge[dpid][next_sw]['sport']
        for flow in flows:
            self.flow_create_mirror(dpid, flow, first_port)

        for i in range(1, len(path)):
            sw = path[i]
            dp = self.net.node[sw]['conn']
            prev_sw = path[i - 1]
            match_in_port = self.net.edge[prev_sw][sw]['dport']

            actions = []
            if i == len(path) - 1:
                action_out_port = target_port
                actions.append(
                    dp.ofproto_parser.OFPActionSetDlDst(
                        mac.haddr_to_bin('ff:ff:ff:ff:ff:ff')))
            else:
                next_sw = path[i + 1]
                action_out_port = self.net.edge[sw][next_sw]['sport']

            match = {'in_port': match_in_port}
            actions.append(dp.ofproto_parser.OFPActionOutput(action_out_port))
            self.add_flow(dp, 65533, match, actions)

        return (True, 'Success')

    # contention_add_vrf(rtcomm, nexthop)
    #  - rtcomm: Route-Target Community, describes the VRF
    #  - nexthop: ipv4 address which will be used for redirect
    #
    # Add a fake VRF which will be used just for traffic
    # redirection to a nexthop. Usefull for FlowSpec redirect
    # action, since draft-simpson-idr-flowspec-redirect-02 is
    # not yet avaliable
    def contention_add_vrf(self, rtcomm, nexthop):
        self.contention_vrf[rtcomm] = nexthop
        self.persist_config()
        return (True, 'Success')

    def contention_quarantine(self, ipaddr, redirect_to):
        for sw in self.net.nodes():
            dp = self.net.node[sw]['conn']
            actions = [
                dp.ofproto_parser.OFPActionOutput(dp.ofproto.OFPP_CONTROLLER)
            ]
            for port in self.get_access_ports(sw):
                for vlan in self.eline_map:
                    # the dl_vlan match is a workaround because flowvisor seems to bug when using
                    # dl_type=0x0800
                    match = {
                        'in_port': port,
                        'dl_type': 0x0800,
                        'dl_vlan': vlan,
                        'nw_src': ipaddr
                    }
                    self.add_flow(dp, 65534, match, actions)
        self.quarantine[ipaddr] = redirect_to
        return (True, 'Success')

    def contention_block(self, ipaddr):
        print "==> contention_block ipaddr=%s in all switches" % (ipaddr)
        actions = []
        for sw in self.net.nodes():
            dp = self.net.node[sw]['conn']
            for port in self.get_access_ports(sw):
                for vlan in self.eline_map:
                    # the dl_vlan match is a workaround because flowvisor seems to bug when using
                    # dl_type=0x0800
                    match = {
                        'in_port': port,
                        'dl_type': 0x0800,
                        'dl_vlan': vlan,
                        'nw_src': ipaddr
                    }
                    self.add_flow(dp, 65534, match, actions)
        return (True, 'Success')

    def contention_quarantine_redirect(self, dp, ip_pkt, redirect_to, vlan_id):
        print "==> create contention_quarantine_redirect in dpid=%s src=%s dst=%s redirect_to=%s" % (
            dpid_lib.dpid_to_str(dp.id), ip_pkt.src, ip_pkt.dst, redirect_to)
        # the dl_vlan match is a workaround because flowvisor seems to bug when using
        # dl_type=0x0800
        match = {
            'nw_src': ip_pkt.src,
            'nw_dst': ip_pkt.dst,
            'dl_type': 0x0800,
            'dl_vlan': vlan_id
        }
        actions = []
        actions.append(dp.ofproto_parser.OFPActionSetNwDst(redirect_to))
        actions.append(
            dp.ofproto_parser.OFPActionOutput(
                self.eline_map[vlan_id][dp.id]['bkb_port']))
        self.add_flow(dp, 65535, match, actions, idle_timeout=120)

        match = {
            'nw_src': redirect_to,
            'nw_dst': ip_pkt.src,
            'dl_type': 0x0800,
            'dl_vlan': vlan_id
        }
        actions = []
        actions.append(dp.ofproto_parser.OFPActionSetNwSrc(str(ip_pkt.dst)))
        actions.append(
            dp.ofproto_parser.OFPActionOutput(
                self.eline_map[vlan_id][dp.id]['access_port']))
        self.add_flow(dp, 65535, match, actions, idle_timeout=120)
Example #43
0
from ryu.services.protocols.bgp.bgpspeaker import BGPSpeaker


def dump_remote_best_path_change(event):
    print 'the best path changed:', event.remote_as, event.prefix,\
        event.nexthop, event.is_withdraw


def detect_peer_down(remote_ip, remote_as):
    print 'Peer down:', remote_ip, remote_as


if __name__ == "__main__":
    print "BHKA"
    speaker = BGPSpeaker(as_number=64517,
                         router_id='10.0.0.2',
                         best_path_change_handler=dump_remote_best_path_change,
                         peer_down_handler=detect_peer_down)
    print 'gamiesai'
    speaker.neighbor_add('192.168.1.4', 64518)
    # uncomment the below line ifthe speaker needs to talk with a bmp server.
    # speaker.bmp_server_add('192.168.177.2', 11019)
    count = 1
    while True:
        eventlet.sleep(30)
        prefix = '10.20.' + str(count) + '.0/24'
        print "add a new prefix", prefix
        speaker.prefix_add(prefix)
        count += 1
        if count == 4:
            speaker.shutdown()
            break