When a BGP message is received, send it to peer.

        Open messages are validated here. Peer handler is called to handle each
        message except for *Open* and *Notification* message. On receiving
        *Notification* message we close connection with peer.

def _handle_msg(self, msg):
        """When a BGP message is received, send it to peer.

        Open messages are validated here. Peer handler is called to handle each
        message except for *Open* and *Notification* message. On receiving
        *Notification* message we close connection with peer.
        """
        LOG.debug('Received msg from %s << %s', self._remotename, msg)

        # If we receive open message we try to bind to protocol
        if msg.type == BGP_MSG_OPEN:
            if self.state == BGP_FSM_OPEN_SENT:
                # Validate open message.
                self._validate_open_msg(msg)
                self.recv_open_msg = msg
                self.state = BGP_FSM_OPEN_CONFIRM
                self._peer.state.bgp_state = self.state

                # Try to bind this protocol to peer.
                self._is_bound = self._peer.bind_protocol(self)

                # If this protocol failed to bind to peer.
                if not self._is_bound:
                    # Failure to bind to peer indicates connection collision
                    # resolution choose different instance of protocol and this
                    # instance has to close. Before closing it sends
                    # appropriate notification msg. to peer.
                    raise bgp.CollisionResolution()

                # If peer sends Hold Time as zero, then according to RFC we do
                # not set Hold Time and Keep Alive timer.
                if msg.hold_time == 0:
                    LOG.info('The Hold Time sent by the peer is zero, hence '
                             'not setting any Hold Time and Keep Alive'
                             ' timers.')
                else:
                    # Start Keep Alive timer considering Hold Time preference
                    # of the peer.
                    self._start_timers(msg.hold_time)
                    self._send_keepalive()

                # Peer does not see open message.
                return
            else:
                # If we receive a Open message out of order
                LOG.error('Open message received when current state is not '
                          'OpenSent')
                # Received out-of-order open message
                # We raise Finite state machine error
                raise bgp.FiniteStateMachineError()
        elif msg.type == BGP_MSG_NOTIFICATION:
            if self._peer:
                self._signal_bus.bgp_notification_received(self._peer, msg)
            # If we receive notification message
            LOG.error('Received notification message, hence closing '
                      'connection %s', msg)
            self._socket.close()
            return

        # If we receive keepalive or update message, we reset expire timer.
        if (msg.type == BGP_MSG_KEEPALIVE or
                msg.type == BGP_MSG_UPDATE):
            if self._expiry:
                self._expiry.reset()

        # Call peer message handler for appropriate messages.
        if (msg.type in
                (BGP_MSG_UPDATE, BGP_MSG_KEEPALIVE, BGP_MSG_ROUTE_REFRESH)):
            self._peer.handle_msg(msg)
        # We give chance to other threads to run.
        self.pause(0)