<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _validate_update_msg(self, update_msg):
 """Validate update message as per RFC. Here we validate the message after it has been parsed. Message has already been validated against some errors inside parsing library. """

        # TODO(PH): finish providing implementation, currently low priority
        assert update_msg.type == BGP_MSG_UPDATE
        # An UPDATE message may be received only in the Established state.
        # Receiving an UPDATE message in any other state is an error.
        if self.state.bgp_state != const.BGP_FSM_ESTABLISHED:
            LOG.error('Received UPDATE message when not in ESTABLISHED'
                      ' state.')
            raise bgp.FiniteStateMachineError()

        mp_reach_attr = update_msg.get_path_attr(
            BGP_ATTR_TYPE_MP_REACH_NLRI
        )
        mp_unreach_attr = update_msg.get_path_attr(
            BGP_ATTR_TYPE_MP_UNREACH_NLRI
        )

        # non-MPBGP Update msg.
        if not (mp_reach_attr or mp_unreach_attr):
            if not self.is_mpbgp_cap_valid(RF_IPv4_UC):
                LOG.error('Got UPDATE message with un-available'
                          ' afi/safi %s', RF_IPv4_UC)
            nlri_list = update_msg.nlri
            if len(nlri_list) > 0:
                # Check for missing well-known mandatory attributes.
                aspath = update_msg.get_path_attr(BGP_ATTR_TYPE_AS_PATH)
                if not aspath:
                    raise bgp.MissingWellKnown(
                        BGP_ATTR_TYPE_AS_PATH)

                if (self.check_first_as and self.is_ebgp_peer() and
                        not aspath.has_matching_leftmost(self.remote_as)):
                    LOG.error('First AS check fails. Raise appropriate'
                              ' exception.')
                    raise bgp.MalformedAsPath()

                origin = update_msg.get_path_attr(BGP_ATTR_TYPE_ORIGIN)
                if not origin:
                    raise bgp.MissingWellKnown(BGP_ATTR_TYPE_ORIGIN)

                nexthop = update_msg.get_path_attr(BGP_ATTR_TYPE_NEXT_HOP)
                if not nexthop:
                    raise bgp.MissingWellKnown(BGP_ATTR_TYPE_NEXT_HOP)

            return True

        # Check if received MP_UNREACH path attribute is of available afi/safi
        if mp_unreach_attr:
            if not self.is_mpbgp_cap_valid(mp_unreach_attr.route_family):
                LOG.error('Got UPDATE message with un-available afi/safi for'
                          ' MP_UNREACH path attribute (non-negotiated'
                          ' afi/safi) %s', mp_unreach_attr.route_family)
                # raise bgp.OptAttrError()

        if mp_reach_attr:
            # Check if received MP_REACH path attribute is of available
            # afi/safi
            if not self.is_mpbgp_cap_valid(mp_reach_attr.route_family):
                LOG.error('Got UPDATE message with un-available afi/safi for'
                          ' MP_UNREACH path attribute (non-negotiated'
                          ' afi/safi) %s', mp_reach_attr.route_family)
                # raise bgp.OptAttrError()

            # Check for missing well-known mandatory attributes.
            aspath = update_msg.get_path_attr(BGP_ATTR_TYPE_AS_PATH)
            if not aspath:
                raise bgp.MissingWellKnown(BGP_ATTR_TYPE_AS_PATH)

            if (self.check_first_as and self.is_ebgp_peer() and
                    not aspath.has_matching_leftmost(self.remote_as)):
                LOG.error('First AS check fails. Raise appropriate exception.')
                raise bgp.MalformedAsPath()

            origin = update_msg.get_path_attr(BGP_ATTR_TYPE_ORIGIN)
            if not origin:
                raise bgp.MissingWellKnown(BGP_ATTR_TYPE_ORIGIN)

            # Validate Next hop.
            if mp_reach_attr.route_family.safi in (
                    subaddr_family.IP_FLOWSPEC,
                    subaddr_family.VPN_FLOWSPEC):
                # Because the Flow Specification does not have nexthop,
                # skips check.
                pass
            elif (not mp_reach_attr.next_hop or
                  mp_reach_attr.next_hop == self.host_bind_ip):
                LOG.error('Nexthop of received UPDATE msg. (%s) same as local'
                          ' interface address %s.',
                          mp_reach_attr.next_hop,
                          self.host_bind_ip)
                return False

        return True