code: def _is_looped_path_attrs(self, update_msg):
          
          umsg_pattrs = update_msg.pathattr_map
          recv_open_msg = self.protocol.recv_open_msg
  
          # Check if AS_PATH has loops.
          aspath = umsg_pattrs.get(BGP_ATTR_TYPE_AS_PATH)
          if (aspath is not None
                  and aspath.has_local_as(
                      self.local_as,
                      max_count=self._common_conf.allow_local_as_in_count)):
              LOG.error(
                  'AS_PATH on UPDATE message has loops. '
                  'Ignoring this message: %s',
                  update_msg)
              return
  
          # Check if ORIGINATOR_ID has loops. [RFC4456]
          originator_id = umsg_pattrs.get(BGP_ATTR_TYPE_ORIGINATOR_ID, None)
          if (originator_id
                  and recv_open_msg.bgp_identifier == originator_id):
              LOG.error(
                  'ORIGINATOR_ID on UPDATE message has loops. '
                  'Ignoring this message: %s',
                  update_msg)
              return
  
          # Check if CLUSTER_LIST has loops. [RFC4456]
          cluster_list = umsg_pattrs.get(BGP_ATTR_TYPE_CLUSTER_LIST, None)
          if (cluster_list
                  and self._common_conf.cluster_id in cluster_list.value):
              LOG.error(
                  'CLUSTER_LIST on UPDATE message has loops. '
                  'Ignoring this message: %s', update_msg)
              return
docs: Extracts path attributes from the given UPDATE message and checks
          if the given attributes have loops or not.
  
          :param update_msg: UPDATE message instance.
          :return: True if attributes have loops. Otherwise False.