/* Measurements
 *
 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
#include <gprs_rlcmac.h>
#include <gprs_debug.h>
#include <pcu_l1_if.h>
#include <tbf.h>

#include <string.h>
#include <errno.h>

/*
 * downlink measurement
 */
/* TODO: trigger the measurement report from the pollcontroller and use it for flow control */

/* received Measurement Report */
int gprs_rlcmac_meas_rep(Packet_Measurement_Report_t *pmr)
{
	NC_Measurement_Report_t *ncr;
	NC_Measurements_t *nc;
	int i;

	LOGP(DRLCMACMEAS, LOGL_INFO, "Measuement Report of TLLI=0x%08x:",
		pmr->TLLI);

	switch (pmr->UnionType) {
	case 0:
		ncr = &pmr->u.NC_Measurement_Report;
		LOGPC(DRLCMACMEAS, LOGL_INFO, " NC%u Serv %d dbm",
			ncr->NC_MODE + 1,
			ncr->Serving_Cell_Data.RXLEV_SERVING_CELL - 110);
		for (i = 0; i < ncr->NUMBER_OF_NC_MEASUREMENTS; i++) {
			nc = &ncr->NC_Measurements[i];
			LOGPC(DRLCMACMEAS, LOGL_DEBUG, ", Neigh %u %d dbm",
				nc->FREQUENCY_N, nc->RXLEV_N - 110);
		}
		LOGPC(DRLCMACMEAS, LOGL_INFO, "\n");

		break;
	case 1:
		LOGPC(DRLCMACMEAS, LOGL_INFO,
			" <EXT Reporting not supported!>\n");
		break;
	}

	return 0;
}


/*
 * uplink measurement
 */

/* RSSI values received from MS */
int gprs_rlcmac_rssi(struct gprs_rlcmac_tbf *tbf, int8_t rssi)
{
	struct timeval now_tv, *rssi_tv = &tbf->meas.rssi_tv;
	uint32_t elapsed;

	tbf->meas.rssi_sum += rssi;
	tbf->meas.rssi_num++;

	gettimeofday(&now_tv, NULL);
	elapsed = ((now_tv.tv_sec - rssi_tv->tv_sec) << 7)
		+ ((now_tv.tv_usec - rssi_tv->tv_usec) << 7) / 1000000;
	if (elapsed < 128)
		return 0;

	gprs_rlcmac_rssi_rep(tbf);

	/* reset rssi values and timestamp */
	memcpy(rssi_tv, &now_tv, sizeof(struct timeval));
	tbf->meas.rssi_sum = 0;
	tbf->meas.rssi_num = 0;

	return 0;
}

/* Give RSSI report */
int gprs_rlcmac_rssi_rep(struct gprs_rlcmac_tbf *tbf)
{
	/* No measurement values */
	if (!tbf->meas.rssi_num)
		return -EINVAL;

	LOGP(DRLCMACMEAS, LOGL_INFO, "UL RSSI of TLLI=0x%08x: %d dBm\n",
		tbf->tlli(), tbf->meas.rssi_sum / tbf->meas.rssi_num);

	return 0;
}


/*
 * lost frames
 */

/* Lost frames reported from RLCMAC layer */
int gprs_rlcmac_received_lost(struct gprs_rlcmac_dl_tbf *tbf, uint16_t received,
	uint16_t lost)
{
	struct timeval now_tv, *loss_tv = &tbf->m_bw.dl_loss_tv;
	uint32_t elapsed;
	uint16_t sum = received + lost;

	/* No measurement values */
	if (!sum)
		return -EINVAL;

	LOGP(DRLCMACMEAS, LOGL_DEBUG, "DL Loss of TLLI 0x%08x: Received: %4d  "
		"Lost: %4d  Sum: %4d\n", tbf->tlli(), received, lost, sum);

	tbf->m_bw.dl_loss_received += received;
	tbf->m_bw.dl_loss_lost += lost;

	gettimeofday(&now_tv, NULL);
	elapsed = ((now_tv.tv_sec - loss_tv->tv_sec) << 7)
		+ ((now_tv.tv_usec - loss_tv->tv_usec) << 7) / 1000000;
	if (elapsed < 128)
		return 0;

	gprs_rlcmac_lost_rep(tbf);

	/* reset lost values and timestamp */
	memcpy(loss_tv, &now_tv, sizeof(struct timeval));
	tbf->m_bw.dl_loss_received = 0;
	tbf->m_bw.dl_loss_lost = 0;

	return 0;
}

/* Give Lost report */
int gprs_rlcmac_lost_rep(struct gprs_rlcmac_dl_tbf *tbf)
{
	uint16_t sum = tbf->m_bw.dl_loss_lost + tbf->m_bw.dl_loss_received;

	/* No measurement values */
	if (!sum)
		return -EINVAL;

	LOGP(DRLCMACMEAS, LOGL_INFO, "DL packet loss of IMSI=%s / TLLI=0x%08x: "
		"%d%%\n", tbf->imsi(), tbf->tlli(),
		tbf->m_bw.dl_loss_lost * 100 / sum);

	return 0;
}


/*
 * downlink bandwidth
 */

int gprs_rlcmac_dl_bw(struct gprs_rlcmac_dl_tbf *tbf, uint16_t octets)
{
	struct timeval now_tv, *bw_tv = &tbf->m_bw.dl_bw_tv;
	uint32_t elapsed;

	tbf->m_bw.dl_bw_octets += octets;

	gettimeofday(&now_tv, NULL);
	elapsed = ((now_tv.tv_sec - bw_tv->tv_sec) << 7)
		+ ((now_tv.tv_usec - bw_tv->tv_usec) << 7) / 1000000;
	if (elapsed < 128)
		return 0;

	tbf->m_bw.dl_throughput = (tbf->m_bw.dl_bw_octets/elapsed);

	LOGP(DRLCMACMEAS, LOGL_INFO, "DL Bandwitdh of IMSI=%s / TLLI=0x%08x: "
		"%d KBits/s\n", tbf->imsi(), tbf->tlli(),
		tbf->m_bw.dl_bw_octets / elapsed);

	/* reset bandwidth values timestamp */
	memcpy(bw_tv, &now_tv, sizeof(struct timeval));
	tbf->m_bw.dl_bw_octets = 0;

	return 0;
}

