Exemple #1
0
    def _update_received(self, timestamp, msg):
        # if self.msg_recv_stat['Updates'] % 1000 == 0:
        #     LOG.info(self.msg_recv_stat['Updates'])
        #     LOG.info(time.time())
        """Called when a BGP Update message was received."""
        result = Update().parse(timestamp, msg, self.fourbytesas,
                                self.add_path_ipv4_receive,
                                self.add_path_ipv4_send)
        if result['sub_error']:
            msg = {
                'attr': result['attr'],
                'nlri': result['nlri'],
                'withdraw': result['withdraw'],
                'hex': repr(result['hex'])
            }

            self.handler.on_update_error(self, timestamp, msg)

            LOG.error('[%s] Update message error: sub error=%s',
                      self.factory.peer_addr, result['sub_error'])
            self.msg_recv_stat['Updates'] += 1
            self.fsm.update_received()
            return

        afi_safi = None
        # process messages
        if result['nlri'] or result['withdraw']:
            afi_safi = 'ipv4'
        elif result['attr'].get(14):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']]
        elif result['attr'].get(15):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']]

        msg = {
            'attr': result['attr'],
            'nlri': result['nlri'],
            'withdraw': result['withdraw'],
            'afi_safi': afi_safi
        }

        self.update_receive_verion(result['attr'], result['nlri'],
                                   result['withdraw'])

        if CONF.bgp.rib:
            # try to update bgp rib in
            if msg.get('afi_safi') == 'ipv4':
                self.update_rib_in_ipv4(msg)
                # LOG.info(msg)
        self.handler.update_received(self, timestamp, msg)

        self.msg_recv_stat['Updates'] += 1
        self.fsm.update_received()
Exemple #2
0
    def update_received(self, timestamp, msg):

        """Called when a BGP Update message was received."""
        result = Update().parse(timestamp, msg, self.fourbytesas, self.add_path_ipv4_receive, self.add_path_ipv4_send)
        if result['sub_error']:
            msg = {
                'attr': result['attr'],
                'nlri': result['nlri'],
                'withdraw': result['withdraw'],
                'hex': repr(result['hex'])
            }
            self.factory.write_msg(
                timestamp=result['time'],
                msg_type=6,
                msg={'msg': msg},
                flush=True
            )
            LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error'])
            self.msg_recv_stat['Updates'] += 1
            self.fsm.update_received()
            return
        afi_safi = None
        # process messages
        if result['nlri'] or result['withdraw']:
            afi_safi = 'ipv4'
        elif result['attr'].get(14):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']]
        elif result['attr'].get(15):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']]
        msg = {
            'attr': result['attr'],
            'nlri': result['nlri'],
            'withdraw': result['withdraw'],
            'afi_safi': afi_safi
        }

        # write message to disk
        self.factory.write_msg(
            timestamp=result['time'],
            msg_type=bgp_cons.MSG_UPDATE,
            msg={"msg": msg}
        )
        self.factory.flush_and_check_file_size()

        # check channel filter
        if not CONF.standalone and self.factory.tag in \
                [channel_cons.SOURCE_ROUTER_TAG, channel_cons.SOURCE_AND_TARGET_ROUTER_TAG]:
            self.channel_filter(msg=msg)
        # update rib
        self.update_rib(msg)
        self.msg_recv_stat['Updates'] += 1
        self.fsm.update_received()
Exemple #3
0
 def construct_update_to_bin(self, msg):
     """
     construct update message to binary
     :param msg: message dictionary
     :return:
     """
     try:
         msg_update = Update().construct(msg, self.fourbytesas,
                                         self.add_path_ipv4_send)
         return msg_update
     except Exception as e:
         LOG.error(e)
         return "construct failed"
Exemple #4
0
 def send_update(self, msg):
     """
     send update message to the peer
     :param msg: message dictionary
     :return:
     """
     try:
         msg_update = Update().construct(msg, self.fourbytesas)
         self.transport.write(msg_update)
         self.msg_sent_stat['Updates'] += 1
         return True
     except Exception as e:
         LOG.error(e)
         return False
Exemple #5
0
 def send_update(self, msg):
     """
     send update message to the peer
     :param msg: message dictionary
     :return:
     """
     try:
         msg_update = Update().construct(msg, self.fourbytesas, self.add_path_ipv4_send)
         reactor.callFromThread(self.write_tcp_thread, msg_update)
         self.msg_sent_stat['Updates'] += 1
         return True
     except Exception as e:
         LOG.error(e)
         return False
Exemple #6
0
    def update_received(self, timestamp, msg):

        """Called when a BGP Update message was received."""
        result = Update().parse(timestamp, msg, self.fourbytesas, self.add_path_ipv4_receive, self.add_path_ipv4_send)
        if result['sub_error']:
            msg = {
                'attr': result['attr'],
                'nlri': result['nlri'],
                'withdraw': result['withdraw'],
                'hex': repr(result['hex'])
            }
            self.factory.write_msg(
                timestamp=result['time'],
                msg_type=6,
                msg={'msg': msg},
                flush=True
            )
            LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error'])
            self.msg_recv_stat['Updates'] += 1
            self.fsm.update_received()
            return

        # process messages
        msg = {
            'attr': result['attr'],
            'nlri': result['nlri'],
            'withdraw': result['withdraw']
        }

        # write message to disk
        self.factory.write_msg(
            timestamp=result['time'],
            msg_type=bgp_cons.MSG_UPDATE,
            msg={"msg": msg}
        )
        if self.factory.flush_and_check_file_size():
            for afi, safi in CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote']['afi_safi']:
                self.send_route_refresh(afi=afi, safi=safi)

        # check channel filter
        if not CONF.standalone and self.factory.tag in \
                [channel_cons.SOURCE_ROUTER_TAG, channel_cons.SOURCE_AND_TARGET_ROUTER_TAG]:
            self.channel_filter(msg=msg)
        # update rib
        self.update_rib(msg)
        self.msg_recv_stat['Updates'] += 1
        self.fsm.update_received()
Exemple #7
0
    def update_received(self, timestamp, msg):
        """Called when a BGP Update message was received."""
        result = Update().parse(timestamp, msg, self.fourbytesas,
                                self.add_path_ipv4_receive,
                                self.add_path_ipv4_send)
        if result['sub_error']:
            msg = {
                'attr': result['attr'],
                'nlri': result['nlri'],
                'withdraw': result['withdraw'],
                'hex': repr(result['hex'])
            }
            self.factory.write_msg(timestamp=result['time'],
                                   msg_type=6,
                                   msg=msg,
                                   flush=True)
            LOG.error('[%s] Update message error: sub error=%s',
                      self.factory.peer_addr, result['sub_error'])
            self.msg_recv_stat['Updates'] += 1
            self.fsm.update_received()
            return
        afi_safi = None
        # process messages
        if result['nlri'] or result['withdraw']:
            afi_safi = 'ipv4'
        elif result['attr'].get(14):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']]
        elif result['attr'].get(15):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']]
        msg = {
            'attr': result['attr'],
            'nlri': result['nlri'],
            'withdraw': result['withdraw'],
            'afi_safi': afi_safi
        }

        # write message to disk
        self.factory.write_msg(timestamp=result['time'],
                               msg_type=bgp_cons.MSG_UPDATE,
                               msg=msg)
        self.factory.flush_and_check_file_size()

        self.msg_recv_stat['Updates'] += 1
        self.fsm.update_received()
Exemple #8
0
    def update_received(self, timestamp, msg):

        """Called when a BGP Update message was received."""
        result = Update().parse([timestamp, self.fourbytesas, msg])
        if result['sub_error']:
            self.factory.write_msg(
                timestamp=result['time'],
                msg_type=6,
                msg={
                    'attr': result['attr'],
                    'nlri': result['nlri'],
                    'withdraw': result['withdraw']
                },
                flush=True
            )
            LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error'])
        else:
            msg = {
                'attr': result['attr'],
                'nlri': result['nlri'],
                'withdraw': result['withdraw']
            }
            self.factory.write_msg(
                timestamp=result['time'],
                msg_type=bgp_cons.MSG_UPDATE,
                msg=msg,
                flush=True
            )
            # update rib in ipv4
            for prefix in msg['nlri']:
                self._adj_rib_in['ipv4'][prefix] = msg['attr']
            for prefix in msg['withdraw']:
                if prefix in self._adj_rib_in['ipv4']:
                    self._adj_rib_in['ipv4'].pop(prefix)
                else:
                    LOG.warning('withdraw prefix which does not exist in rib table!')
            if not CONF.standalone:
                self.factory.channel.send_message(exchange='', routing_key=self.factory.peer_addr, message=str(msg))

        self.msg_recv_stat['Updates'] += 1
        self.fsm.update_received()
Exemple #9
0
    def _update_received(self, timestamp, msg):
        """Called when a BGP Update message was received."""
        result = Update().parse(timestamp, msg, self.fourbytesas,
                                self.add_path_ipv4_receive,
                                self.add_path_ipv4_send)
        if result['sub_error']:
            msg = {
                'attr': result['attr'],
                'nlri': result['nlri'],
                'withdraw': result['withdraw'],
                'hex': repr(result['hex'])
            }

            self.handler.on_update_error(self, timestamp, msg)

            LOG.error('[%s] Update message error: sub error=%s',
                      self.factory.peer_addr, result['sub_error'])
            self.msg_recv_stat['Updates'] += 1
            self.fsm.update_received()
            return

        afi_safi = None
        # process messages
        if result['nlri'] or result['withdraw']:
            afi_safi = 'ipv4'
        elif result['attr'].get(14):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']]
        elif result['attr'].get(15):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']]

        msg = {
            'attr': result['attr'],
            'nlri': result['nlri'],
            'withdraw': result['withdraw'],
            'afi_safi': afi_safi
        }

        self.handler.update_received(self, timestamp, msg)

        self.msg_recv_stat['Updates'] += 1
        self.fsm.update_received()
Exemple #10
0
 def parse_route_monitoring_msg(msg):
     """
         Route Monitoring messages are used for initial synchronization of
     ADJ-RIBs-In. They are also used for ongoing monitoring of received
     advertisements and withdraws.
     Following the common BMP header and per-peer header is a BGP Update
     PDU.
     :param msg:
     :return:
     """
     LOG.debug('decode route monitoring message')
     bgp_msg_type = struct.unpack('!B', msg[18])[0]
     LOG.debug('bgp message type=%s' % bgp_msg_type)
     msg = msg[bgp_cons.HDR_LEN:]
     if bgp_msg_type == 2:
         # decode update message
         results = Update().parse(None, msg, asn4=True)
         if results['sub_error']:
             LOG.error(
                 'error: decode update message error!, error code: %s' %
                 results['sub_error'])
             LOG.error('Raw data: %s' % repr(results['hex']))
             return None
         return_result = {
             'attr': results['attr'],
             'nlri': results['nlri'],
             'withdraw': results['withdraw']
         }
         LOG.debug('bgp update message: %s' % return_result)
         return bgp_msg_type, return_result
     elif bgp_msg_type == 5:
         bgp_route_refresh_msg = RouteRefresh().parse(msg=msg)
         LOG.debug('bgp route refresh message: afi=%s,res=%s,safi=%s' %
                   (bgp_route_refresh_msg[0], bgp_route_refresh_msg[1],
                    bgp_route_refresh_msg[2]))
         return bgp_msg_type, {
             'afi': bgp_route_refresh_msg[0],
             'sub_type': bgp_route_refresh_msg[1],
             'safi': bgp_route_refresh_msg[2]
         }
Exemple #11
0
    def parse_route_mirroring_msg(msg):
        """
            Route Mirroring messages are used for verbatim duplication of
        messages as received. Following the common BMP header and per-peer
        header is a set of TLVs that contain information about a message
        or set of messages.
        :param msg:
        :return:
        """
        LOG.debug('decode route mirroring message')

        msg_dict = {}
        open_l = []
        update = []
        notification = []
        route_refresh = []
        while msg:
            mirror_type, length = struct.unpack('!HH', msg[0:4])
            mirror_value = msg[4:4 + length]
            msg = msg[4 + length:]
            if mirror_type == 0:
                # BGP message type
                bgp_msg_type = struct.unpack('!B', mirror_value[18])[0]
                LOG.debug('bgp message type=%s' % bgp_msg_type)
                bgp_msg_body = mirror_value[bgp_cons.HDR_LEN:]
                if bgp_msg_type == 2:
                    # Update message
                    bgp_update_msg = Update().parse(None,
                                                    bgp_msg_body,
                                                    asn4=True)
                    if bgp_update_msg['sub_error']:
                        LOG.error(
                            'error: decode update message error!, error code: %s'
                            % bgp_update_msg['sub_error'])
                        LOG.error('Raw data: %s' % repr(bgp_update_msg['hex']))
                    else:
                        update.append(bgp_update_msg)
                elif bgp_msg_type == 5:
                    # Route Refresh message
                    bgp_route_refresh_msg = RouteRefresh().parse(
                        msg=bgp_msg_body)
                    LOG.debug(
                        'bgp route refresh message: afi=%s,res=%s,safi=%s' %
                        (bgp_route_refresh_msg[0], bgp_route_refresh_msg[1],
                         bgp_route_refresh_msg[2]))
                    route_refresh.append(bgp_route_refresh_msg)
                elif bgp_msg_type == 1:
                    # Open message
                    open_msg = Open().parse(bgp_msg_body)
                    open_l.append(open_msg)
                elif bgp_msg_type == 3:
                    # Notification message
                    notification_msg = Notification().parse(bgp_msg_body)
                    notification.append(notification_msg)
            elif mirror_type == 1:
                # Information type.
                # Amount of this TLV is not specified but we can assume
                # only one per mirroring message is present.
                info_code_type = struct.unpack('!H', mirror_value)[0]
                msg_dict['1'] = info_code_type
            else:
                msg_dict[mirror_type] = binascii.unhexlify(
                    binascii.hexlify(mirror_value))
                LOG.info('unknow mirroring type, type = %s' % mirror_type)

        msg_dict['0'] = {
            'update': update,
            'route_refresh': route_refresh,
            'open': open_l,
            'notification': notification
        }
        return msg_dict