mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-pcu.git
				synced 2025-11-03 21:53:32 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			0.5.0
			...
			jerlbeck/w
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7a4bd9661b | ||
| 
						 | 
					66ba0844be | 
@@ -586,6 +586,23 @@ static uint32_t get_and_reset_avg_queue_delay(void)
 | 
				
			|||||||
	return avg_delay_ms;
 | 
						return avg_delay_ms;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int get_and_reset_measured_leak_rate(int num_pdch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rate; /* byte per second */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (the_pcu.queue_frames_sent == 0)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* 20ms/num_pdch is the average RLC block duration */
 | 
				
			||||||
 | 
						rate = the_pcu.queue_bytes_recv * 1000 * num_pdch /
 | 
				
			||||||
 | 
							(20 * the_pcu.queue_frames_sent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						the_pcu.queue_frames_sent = 0;
 | 
				
			||||||
 | 
						the_pcu.queue_bytes_recv = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rate;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int gprs_bssgp_tx_fc_bvc(void)
 | 
					int gprs_bssgp_tx_fc_bvc(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct gprs_rlcmac_bts *bts;
 | 
						struct gprs_rlcmac_bts *bts;
 | 
				
			||||||
@@ -624,6 +641,20 @@ int gprs_bssgp_tx_fc_bvc(void)
 | 
				
			|||||||
	ms_bucket_size = bts->fc_ms_bucket_size;
 | 
						ms_bucket_size = bts->fc_ms_bucket_size;
 | 
				
			||||||
	ms_leak_rate = bts->fc_ms_leak_rate;
 | 
						ms_leak_rate = bts->fc_ms_leak_rate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (leak_rate == 0) {
 | 
				
			||||||
 | 
							int meas_rate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (num_pdch < 0)
 | 
				
			||||||
 | 
								num_pdch = count_pdch(bts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							meas_rate = get_and_reset_measured_leak_rate(num_pdch);
 | 
				
			||||||
 | 
							if (meas_rate > 0) {
 | 
				
			||||||
 | 
								leak_rate = meas_rate;
 | 
				
			||||||
 | 
								LOGP(DBSSGP, LOGL_DEBUG,
 | 
				
			||||||
 | 
									"Measured BVC leak rate = %d\n", leak_rate);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (leak_rate == 0) {
 | 
						if (leak_rate == 0) {
 | 
				
			||||||
		if (num_pdch < 0)
 | 
							if (num_pdch < 0)
 | 
				
			||||||
			num_pdch = count_pdch(bts);
 | 
								num_pdch = count_pdch(bts);
 | 
				
			||||||
@@ -823,6 +854,16 @@ struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void)
 | 
				
			|||||||
	return the_pcu.bctx;
 | 
						return the_pcu.bctx;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void gprs_bssgp_update_frames_sent()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						the_pcu.queue_frames_sent += 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void gprs_bssgp_update_bytes_received(unsigned bytes_recv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						the_pcu.queue_bytes_recv += bytes_recv;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void gprs_bssgp_update_queue_delay(const struct timeval *tv_recv,
 | 
					void gprs_bssgp_update_queue_delay(const struct timeval *tv_recv,
 | 
				
			||||||
	const struct timeval *tv_now)
 | 
						const struct timeval *tv_now)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,6 +62,8 @@ struct gprs_bssgp_pcu {
 | 
				
			|||||||
	struct timeval queue_delay_sum;
 | 
						struct timeval queue_delay_sum;
 | 
				
			||||||
	unsigned queue_delay_count;
 | 
						unsigned queue_delay_count;
 | 
				
			||||||
	uint8_t fc_tag;
 | 
						uint8_t fc_tag;
 | 
				
			||||||
 | 
						unsigned queue_frames_sent;
 | 
				
			||||||
 | 
						unsigned queue_bytes_recv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/** callbacks below */
 | 
						/** callbacks below */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -85,5 +87,7 @@ struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void gprs_bssgp_update_queue_delay(const struct timeval *tv_recv,
 | 
					void gprs_bssgp_update_queue_delay(const struct timeval *tv_recv,
 | 
				
			||||||
		const struct timeval *tv_now);
 | 
							const struct timeval *tv_now);
 | 
				
			||||||
 | 
					void gprs_bssgp_update_frames_sent();
 | 
				
			||||||
 | 
					void gprs_bssgp_update_bytes_received(unsigned bytes_recv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // GPRS_BSSGP_PCU_H
 | 
					#endif // GPRS_BSSGP_PCU_H
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -321,6 +321,10 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
 | 
				
			|||||||
	if (!msg)
 | 
						if (!msg)
 | 
				
			||||||
		msg = sched_select_downlink(bts, trx, ts, fn, block_nr, pdch);
 | 
							msg = sched_select_downlink(bts, trx, ts, fn, block_nr, pdch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Used to calculate the net leak rate, must not include dummy messages */
 | 
				
			||||||
 | 
						if (msg)
 | 
				
			||||||
 | 
							gprs_bssgp_update_frames_sent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Prio 3: send dummy contol message */
 | 
						/* Prio 3: send dummy contol message */
 | 
				
			||||||
	if (!msg)
 | 
						if (!msg)
 | 
				
			||||||
		msg = sched_dummy();
 | 
							msg = sched_dummy();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -505,7 +505,8 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int find_multi_slots(struct gprs_rlcmac_bts *bts,
 | 
					static int find_multi_slots(struct gprs_rlcmac_bts *bts,
 | 
				
			||||||
	struct gprs_rlcmac_trx *trx,
 | 
						struct gprs_rlcmac_trx *trx,
 | 
				
			||||||
	const GprsMs *ms, uint8_t *ul_slots, uint8_t *dl_slots)
 | 
						const GprsMs *ms, uint8_t *ul_slots, uint8_t *dl_slots,
 | 
				
			||||||
 | 
						int first_common_ts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct gprs_ms_multislot_class *ms_class;
 | 
						const struct gprs_ms_multislot_class *ms_class;
 | 
				
			||||||
	uint8_t Tx, Sum;	/* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
 | 
						uint8_t Tx, Sum;	/* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
 | 
				
			||||||
@@ -523,6 +524,8 @@ static int find_multi_slots(struct gprs_rlcmac_bts *bts,
 | 
				
			|||||||
	unsigned num_tx;
 | 
						unsigned num_tx;
 | 
				
			||||||
	enum {MASK_TT, MASK_TR};
 | 
						enum {MASK_TT, MASK_TR};
 | 
				
			||||||
	unsigned mask_sel;
 | 
						unsigned mask_sel;
 | 
				
			||||||
 | 
						uint8_t common_mask = 0;
 | 
				
			||||||
 | 
						uint8_t common_req = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ms->ms_class() >= 32) {
 | 
						if (ms->ms_class() >= 32) {
 | 
				
			||||||
		LOGP(DRLCMAC, LOGL_ERROR, "Multislot class %d out of range.\n",
 | 
							LOGP(DRLCMAC, LOGL_ERROR, "Multislot class %d out of range.\n",
 | 
				
			||||||
@@ -599,6 +602,11 @@ static int find_multi_slots(struct gprs_rlcmac_bts *bts,
 | 
				
			|||||||
	max_ul_slots = 0;
 | 
						max_ul_slots = 0;
 | 
				
			||||||
	max_dl_slots = 0;
 | 
						max_dl_slots = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (first_common_ts >= 0) {
 | 
				
			||||||
 | 
							common_req = 1 << first_common_ts;
 | 
				
			||||||
 | 
							common_mask = (common_req << 1) - 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Iterate through possible numbers of TX slots */
 | 
						/* Iterate through possible numbers of TX slots */
 | 
				
			||||||
	for (num_tx = 1; num_tx <= ms_class->tx; num_tx += 1) {
 | 
						for (num_tx = 1; num_tx <= ms_class->tx; num_tx += 1) {
 | 
				
			||||||
		uint16_t tx_valid_win = (1 << num_tx) - 1;
 | 
							uint16_t tx_valid_win = (1 << num_tx) - 1;
 | 
				
			||||||
@@ -735,6 +743,15 @@ static int find_multi_slots(struct gprs_rlcmac_bts *bts,
 | 
				
			|||||||
		if (!rx_window)
 | 
							if (!rx_window)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Check required common slots */
 | 
				
			||||||
 | 
							if (((tx_window & rx_window) & common_mask) != common_req) {
 | 
				
			||||||
 | 
								LOGP(DRLCMAC, LOGL_INFO,
 | 
				
			||||||
 | 
									"Common slot pre-selection mismatch: "
 | 
				
			||||||
 | 
									"%02x %02x %02x %02x\n",
 | 
				
			||||||
 | 
									tx_window, rx_window, common_mask, common_req);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Check number of common slots according to TS 54.002, 6.4.2.2 */
 | 
							/* Check number of common slots according to TS 54.002, 6.4.2.2 */
 | 
				
			||||||
		common_slot_count = bitcount(tx_window & rx_window);
 | 
							common_slot_count = bitcount(tx_window & rx_window);
 | 
				
			||||||
		req_common_slots = OSMO_MIN(tx_slot_count, rx_slot_count);
 | 
							req_common_slots = OSMO_MIN(tx_slot_count, rx_slot_count);
 | 
				
			||||||
@@ -873,7 +890,8 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
 | 
				
			|||||||
		trx = &bts->trx[trx_no];
 | 
							trx = &bts->trx[trx_no];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!dl_slots || !ul_slots) {
 | 
						if (!dl_slots || !ul_slots) {
 | 
				
			||||||
		rc = find_multi_slots(bts, trx, ms, &ul_slots, &dl_slots);
 | 
							rc = find_multi_slots(bts, trx, ms, &ul_slots, &dl_slots,
 | 
				
			||||||
 | 
								first_common_ts);
 | 
				
			||||||
		if (rc < 0)
 | 
							if (rc < 0)
 | 
				
			||||||
			return rc;
 | 
								return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -355,6 +355,13 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
 | 
				
			|||||||
	} m_bw;
 | 
						} m_bw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
 | 
						struct ana_result {
 | 
				
			||||||
 | 
							unsigned received_packets;
 | 
				
			||||||
 | 
							unsigned lost_packets;
 | 
				
			||||||
 | 
							unsigned received_bytes;
 | 
				
			||||||
 | 
							unsigned lost_bytes;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct msgb *create_new_bsn(const uint32_t fn, const uint8_t ts);
 | 
						struct msgb *create_new_bsn(const uint32_t fn, const uint8_t ts);
 | 
				
			||||||
	struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
 | 
						struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
 | 
				
			||||||
					const int index);
 | 
										const int index);
 | 
				
			||||||
@@ -363,7 +370,7 @@ protected:
 | 
				
			|||||||
	bool dl_window_stalled() const;
 | 
						bool dl_window_stalled() const;
 | 
				
			||||||
	void reuse_tbf();
 | 
						void reuse_tbf();
 | 
				
			||||||
	void start_llc_timer();
 | 
						void start_llc_timer();
 | 
				
			||||||
	int analyse_errors(char *show_rbb, uint8_t ssn);
 | 
						int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res);
 | 
				
			||||||
	void schedule_next_frame();
 | 
						void schedule_next_frame();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct osmo_timer_list m_llc_timer;
 | 
						struct osmo_timer_list m_llc_timer;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -689,7 +689,8 @@ static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn, uint16_t mod_sns)
 | 
				
			|||||||
	return (ssn - 1 - bitnum) & mod_sns;
 | 
						return (ssn - 1 - bitnum) & mod_sns;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn)
 | 
					int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn,
 | 
				
			||||||
 | 
						ana_result *res)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	gprs_rlc_data *rlc_data;
 | 
						gprs_rlc_data *rlc_data;
 | 
				
			||||||
	uint16_t lost = 0, received = 0, skipped = 0;
 | 
						uint16_t lost = 0, received = 0, skipped = 0;
 | 
				
			||||||
@@ -697,9 +698,13 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn)
 | 
				
			|||||||
	memset(info, '.', sizeof(info));
 | 
						memset(info, '.', sizeof(info));
 | 
				
			||||||
	info[64] = 0;
 | 
						info[64] = 0;
 | 
				
			||||||
	uint16_t bsn = 0;
 | 
						uint16_t bsn = 0;
 | 
				
			||||||
 | 
						unsigned received_bytes = 0, lost_bytes = 0;
 | 
				
			||||||
 | 
						unsigned received_packets = 0, lost_packets = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* SSN - 1 is in range V(A)..V(S)-1 */
 | 
						/* SSN - 1 is in range V(A)..V(S)-1 */
 | 
				
			||||||
	for (int bitpos = 0; bitpos < m_window.ws(); bitpos++) {
 | 
						for (int bitpos = 0; bitpos < m_window.ws(); bitpos++) {
 | 
				
			||||||
 | 
							bool is_received = show_rbb[m_window.ws() - 1 - bitpos] == 'R';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bsn = bitnum_to_bsn(bitpos, ssn, m_window.mod_sns());
 | 
							bsn = bitnum_to_bsn(bitpos, ssn, m_window.mod_sns());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (bsn == ((m_window.v_a() - 1) & m_window.mod_sns())) {
 | 
							if (bsn == ((m_window.v_a() - 1) & m_window.mod_sns())) {
 | 
				
			||||||
@@ -713,6 +718,17 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn)
 | 
				
			|||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Get general statistics */
 | 
				
			||||||
 | 
							if (is_received && !m_window.m_v_b.is_acked(bsn)) {
 | 
				
			||||||
 | 
								received_packets += 1;
 | 
				
			||||||
 | 
								received_bytes += rlc_data->len;
 | 
				
			||||||
 | 
							} else if (!is_received) {
 | 
				
			||||||
 | 
								lost_packets += 1;
 | 
				
			||||||
 | 
								lost_bytes += rlc_data->len;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Get statistics for current CS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (rlc_data->cs != current_cs()) {
 | 
							if (rlc_data->cs != current_cs()) {
 | 
				
			||||||
			/* This block has already been encoded with a different
 | 
								/* This block has already been encoded with a different
 | 
				
			||||||
			 * CS, so it doesn't help us to decide, whether the
 | 
								 * CS, so it doesn't help us to decide, whether the
 | 
				
			||||||
@@ -722,7 +738,7 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn)
 | 
				
			|||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (show_rbb[m_window.ws() - 1 - bitpos] == 'R') {
 | 
							if (is_received) {
 | 
				
			||||||
			if (!m_window.m_v_b.is_acked(bsn)) {
 | 
								if (!m_window.m_v_b.is_acked(bsn)) {
 | 
				
			||||||
				received += 1;
 | 
									received += 1;
 | 
				
			||||||
				info[bitpos] = 'R';
 | 
									info[bitpos] = 'R';
 | 
				
			||||||
@@ -740,6 +756,11 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn)
 | 
				
			|||||||
		name(), m_window.v_a(), m_window.v_s(), lost, received,
 | 
							name(), m_window.v_a(), m_window.v_s(), lost, received,
 | 
				
			||||||
		skipped, bsn, info);
 | 
							skipped, bsn, info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res->received_packets = received_packets;
 | 
				
			||||||
 | 
						res->lost_packets = lost_packets;
 | 
				
			||||||
 | 
						res->received_bytes = received_bytes;
 | 
				
			||||||
 | 
						res->lost_bytes = lost_bytes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (lost + received <= 1)
 | 
						if (lost + received <= 1)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -755,6 +776,7 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
 | 
				
			|||||||
	char show_v_b[RLC_MAX_SNS + 1];
 | 
						char show_v_b[RLC_MAX_SNS + 1];
 | 
				
			||||||
	const uint16_t mod_sns = m_window.mod_sns();
 | 
						const uint16_t mod_sns = m_window.mod_sns();
 | 
				
			||||||
	int error_rate;
 | 
						int error_rate;
 | 
				
			||||||
 | 
						struct ana_result ana_res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Decoding::extract_rbb(rbb, show_rbb);
 | 
						Decoding::extract_rbb(rbb, show_rbb);
 | 
				
			||||||
	/* show received array in debug (bit 64..1) */
 | 
						/* show received array in debug (bit 64..1) */
 | 
				
			||||||
@@ -777,10 +799,10 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
 | 
				
			|||||||
		return 1; /* indicate to free TBF */
 | 
							return 1; /* indicate to free TBF */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bts_data()->cs_adj_enabled && ms()) {
 | 
						error_rate = analyse_errors(show_rbb, ssn, &ana_res);
 | 
				
			||||||
		error_rate = analyse_errors(show_rbb, ssn);
 | 
					
 | 
				
			||||||
 | 
						if (bts_data()->cs_adj_enabled && ms())
 | 
				
			||||||
		ms()->update_error_rate(this, error_rate);
 | 
							ms()->update_error_rate(this, error_rate);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m_window.update(bts, show_rbb, ssn,
 | 
						m_window.update(bts, show_rbb, ssn,
 | 
				
			||||||
			&lost, &received);
 | 
								&lost, &received);
 | 
				
			||||||
@@ -788,6 +810,9 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
 | 
				
			|||||||
	/* report lost and received packets */
 | 
						/* report lost and received packets */
 | 
				
			||||||
	gprs_rlcmac_received_lost(this, received, lost);
 | 
						gprs_rlcmac_received_lost(this, received, lost);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Used to calculate the net leak rate */
 | 
				
			||||||
 | 
						gprs_bssgp_update_bytes_received(ana_res.received_bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* raise V(A), if possible */
 | 
						/* raise V(A), if possible */
 | 
				
			||||||
	m_window.raise(m_window.move_window());
 | 
						m_window.raise(m_window.move_window());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user