⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mac.c

📁 wimax BS simulation code,implemented under linux.
💻 C
字号:
/* * This piece of code is totally free. If any pitfalls found,  * please feel free to contact me at jetmotor@21cn.com * THANKS A LOT! */#include <string.h>#include "list.h"#include "bitops.h"#include "mac.h"#include "que.h"#include "wxtimer.h"#include "wxsched.h"/* Our bs decide to support a maximum of 256 ss; each ss has a maximum of 256 service flows. * so there will be 256 basic cids and 256 primary cids. * Notice that management service flow are dualplex, they are not allowed to perform  * fragmentation on them, so that's no need to reserve a softque for those uplink ones. *//* 0:		initial ranging cid * 1~m:		basic cid * m+1~2m:	primary cid * 2m+1~0xfe9f:	transportation cid, secondary management cid * 0xfffe:	padding cid * 0xffff:	broadcast cid */bsinfo_t g_bsinfo;/* for ss `i', the basic cid is `i+1', the primary cid is `256+i+1', * and the transportation cid should be allocated individually. * There is only sig thread to use `alloc_ss' or `alloc_trans_cid', so * no need to use mutex. */ssinfo_t g_ssinfo[MAX_SS_NUM];struct list_head g_sspool;sfattr_t g_serviceflow[MAX_SF_NUM];struct list_head g_sfpool;softq_t g_softque[MAX_SF_NUM];static void release_mng_sf(sfattr_t *sf);static void release_trans_sf(sfattr_t *sf);static void set_bs_default();static void set_ss0_default();static void set_sf_default();/* initialize all the global tables. */int32_t mac_init(){		int32_t i;		/* init serviceflow and softque table */	INIT_LIST_HEAD(&g_sfpool);	for ( i = 0; i < MAX_SF_NUM; i++ ) {		memset((uint8_t *)&g_serviceflow[i]+sizeof(g_serviceflow[i].mutex), 0,		       sizeof(g_serviceflow[i])-sizeof(g_serviceflow[i].mutex));		pthread_mutex_init(&g_serviceflow[i].mutex ,NULL);		INIT_LIST_HEAD(&g_serviceflow[i].link);		INIT_LIST_HEAD(&g_serviceflow[i].dlink);		INIT_LIST_HEAD(&g_serviceflow[i].ulink);				if ( (i >= 0 && i <= 512) || i == 0xffff ) {//sfid should be 32 bits			g_serviceflow[i].request_transmission_policy |= NO_FRAG;		}				if ( i >= 513 || i <= 0xfea0 )			list_add_tail(&g_serviceflow[i].link, &g_sfpool);/*双向循环链表,把g_serviceflow[i].link 插入到g_sfpool的尾部*/				softq_init(&g_softque[i]);	}	       	/* init ssinfo table */	INIT_LIST_HEAD(&g_sspool);	for ( i = 0; i < MAX_SS_NUM; i++ ) {		memset((uint8_t *)&g_ssinfo[i]+sizeof(g_ssinfo[i].mutex), 0, 		       sizeof(g_ssinfo[i])-sizeof(g_ssinfo[i].mutex));		pthread_mutex_init(&g_ssinfo[i].mutex, NULL);		INIT_LIST_HEAD(&g_ssinfo[i].link);		INIT_LIST_HEAD(&g_ssinfo[i].dscheded_link);		INIT_LIST_HEAD(&g_ssinfo[i].uscheded_link);		INIT_LIST_HEAD(&g_ssinfo[i].active_link);				if ( i > 0 )			list_add_tail(&g_ssinfo[i].link, &g_sspool);	}		/* init bsinfo */	memset((uint8_t *)&g_bsinfo+sizeof(g_bsinfo.mutex), 0,	       sizeof(g_bsinfo)-sizeof(g_bsinfo.mutex));	pthread_mutex_init(&g_bsinfo.mutex, NULL);	for ( i = 0; i < 5; i++ )		INIT_LIST_HEAD(&g_bsinfo.ss_que[i]);/*5个队列分别存放5 种不同状态的SS*/	g_bsinfo.bp_active = &g_bsinfo.set[0];//burst profile set	g_bsinfo.bp_expired = &g_bsinfo.set[1];	set_bs_default();	set_ss0_default();	set_sf_default();	return 0;}int32_t is_fcfsn_valid(int8_t ofc, int16_t ofsn, int8_t nfc, int16_t nfsn, int8_t ext){	if ( ofsn != nfsn )		return 0;		switch ( ofc ) {	case NO_FRAG :		return (nfc == NO_FRAG || nfc == FIRST_FRAG);	case FIRST_FRAG :	case MIDDLE_FRAG :		return (nfc == MIDDLE_FRAG || nfc == LAST_FRAG);	case LAST_FRAG :		return (nfc == NO_FRAG || nfc == FIRST_FRAG || nfc == LAST_FRAG);	}	return 0;}uint32_t bytes_perslot(uint8_t xiuc, uint8_t doru)//doru:dl or ul{	int32_t fec;	pthread_mutex_lock(&g_bsinfo.mutex);	fec = g_bsinfo.bp_active->xiuc_fec[doru][xiuc]; 	pthread_mutex_unlock(&g_bsinfo.mutex);	if ( fec == _QPSK_CC_12 || _QPSK_CTC_12 )		return BYTES_PER_SLOT_QPSK_12;	else if ( fec == _QPSK_CC_34 || _QPSK_CTC_34 )		return BYTES_PER_SLOT_QPSK_34;	else if ( fec == _16QAM_CC_12 || _16QAM_CTC_12 )		return BYTES_PER_SLOT_16QAM_12;	else if ( fec == _16QAM_CC_34 || _16QAM_CTC_34 )		return BYTES_PER_SLOT_16QAM_34;	else if ( fec == _64QAM_CC_12 || _64QAM_CTC_12 )		return BYTES_PER_SLOT_64QAM_12;	else if ( fec == _64QAM_CC_23 || _64QAM_CTC_23 )		return BYTES_PER_SLOT_64QAM_23;	else if ( fec == _64QAM_CC_34 || _64QAM_CTC_34 )		return BYTES_PER_SLOT_64QAM_34;}int32_t alloc_ss(){	int32_t index;	ssinfo_t *ss;	if ( list_empty(&g_sspool) )//indicate the list is empty		return -1;		ss = list_entry(g_sspool.next, ssinfo_t, link);/*  链表中存放的是所有ssinfo 类型的节点.											*但是通过ssinfo 类型中的link 连接起来g_sspool.next 就是ssinfo											中的link,这个宏做的事情就是把链表中的第一个节点取											出来*/	list_del_init(g_sspool.next);	index = ((uint32_t)ss - (uint32_t)g_ssinfo) / sizeof(ssinfo_t);/*一共有256个SS ,g_ssinfo是数组的首地址														*,也是第一个SS的地址,这一句的作用是														找出来该ss是第几个SS*/		ss->stat = SS_INVALID;	ss->sf[0] = &g_serviceflow[index+1];	ss->sf[1] = &g_serviceflow[256+index+1];	ss->nr_sf = 2;	ss->sf[0]->ss = ss->sf[1]->ss = index;	ss->sf[0]->dir = ss->sf[1]->dir = DIR_DUPLEX;	ss->sf[0]->sfid = ss->sf[0]->cid = index+1;	ss->sf[0]->sfid = ss->sf[1]->cid = 256+index+1;//here may be a mistake	ss->sf[0]->service_flow_scheduling_type = ss->sf[1]->service_flow_scheduling_type = 0;	ss->sf[0]->request_transmission_policy = ss->sf[1]->request_transmission_policy = NO_PACK_FRAGMENT;	ss->sf[0]->fixed_variable_length_indicator = ss->sf[1]->fixed_variable_length_indicator = VARIABLE_LENGTH_SDU;	ss->sf[0]->maximum_sustained_traffic_rate = ss->sf[1]->maximum_sustained_traffic_rate = ~0;	ss->sf[0]->maximum_traffic_burst = ss->sf[1]->maximum_traffic_burst = ~0;		return index;}int16_t alloc_tran_sf(){	int32_t index;	sfattr_t *sf;	if ( list_empty(&g_sfpool) )		return -1;	sf = list_entry(g_sfpool.next, sfattr_t, link);	list_del_init(g_sfpool.next);	index = ((uint32_t)sf - (uint32_t)g_serviceflow) / sizeof(sfattr_t);	sf->sfid = sf->cid = index;	return index;}void release_ss(ssinfo_t *ss){	int32_t i;	/* delete from BS registration */	pthread_mutex_lock(&g_bsinfo.mutex);	if ( ! list_empty(&ss->active_link) )		list_del(&ss->active_link);	if ( ss->stat == SS_RANGING )/*BS 对处在各种状态的SS 进行计数*/		g_bsinfo.nr_ranging--;	else if ( ss->stat == SS_ACTIVE )		g_bsinfo.nr_active--;	else if ( ss->stat == SS_HO )		g_bsinfo.nr_ho--;	else if ( ss->stat == SS_SLEEP )		g_bsinfo.nr_sleep--;	else if ( ss->stat == SS_IDLE )		g_bsinfo.nr_idle--;	pthread_mutex_unlock(&g_bsinfo.mutex);	/* delete from scheduling */	pthread_mutex_lock(&g_ulschedque.mutex);	if ( ! list_empty(&ss->dscheded_link) )		list_del(&ss->dscheded_link);	pthread_mutex_unlock(&g_ulschedque.mutex);	pthread_mutex_lock(&g_ulschedque.mutex);	if ( ! list_empty(&ss->uscheded_link) )		list_del(&ss->uscheded_link);	pthread_mutex_unlock(&g_ulschedque.mutex);	/* release SS resources */	pthread_mutex_lock(&ss->mutex);	release_mng_sf(ss->sf[0]);/*sf[0] and sf[1] are mng sf */	release_mng_sf(ss->sf[1]);		for ( i = 2; i < ss->nr_sf; i++ )		release_trans_sf(ss->sf[i]);		for ( i = 0; i < ss->nr_timer; i++ )		cancel_timer(ss->timer[i]);	memset((uint8_t *)ss+sizeof(ss->mutex), 0, sizeof(*ss)-sizeof(ss->mutex));	INIT_LIST_HEAD(&g_ssinfo[i].dscheded_link);	INIT_LIST_HEAD(&g_ssinfo[i].uscheded_link);	INIT_LIST_HEAD(&g_ssinfo[i].active_link);	pthread_mutex_unlock(&ss->mutex);		list_add_tail(&ss->link, &g_sspool);/*释放的SS又加到sspool 中*/		return;}void release_mng_sf(sfattr_t *sf){	wxbuff_t *wxb;	struct list_head hdr, *pos, *tmp;	pthread_mutex_lock(&g_dlschedque.mutex);	if ( ! list_empty(&sf->dlink) )		list_del(&sf->dlink);	pthread_mutex_unlock(&g_dlschedque.mutex);	pthread_mutex_lock(&g_ulschedque.mutex);	if ( ! list_empty(&sf->ulink) )		list_del(&sf->ulink);	pthread_mutex_unlock(&g_ulschedque.mutex);			pthread_mutex_lock(&sf->mutex);	memset((uint8_t *)sf+sizeof(sf->mutex), 0, sizeof(*sf)-sizeof(sf->mutex));	INIT_LIST_HEAD(&sf->dlink);	INIT_LIST_HEAD(&sf->ulink);	pthread_mutex_unlock(&sf->mutex);	wxb = softq_dump(&g_softque[sf->cid]);	list_add_tail(&hdr, &wxb->junior);	list_for_each_safe(pos, tmp, &hdr) {		wxb = list_entry(pos, wxbuff_t, junior);		put_wxbuff(wxb);	}	return;}void release_trans_sf(sfattr_t *sf){	release_mng_sf(sf);	list_add_tail(&sf->link, &g_sfpool);		return;}void set_bs_default(){	int32_t i;	g_bsinfo.channel_nr		= 30;	g_bsinfo.ttg			= 296;//reder:unit of us??	g_bsinfo.rtg			= 168;	g_bsinfo.frequency		= 3500;	g_bsinfo.mac_addr[0]		= 0x01;	g_bsinfo.mac_addr[1]		= 0x02;	g_bsinfo.mac_addr[2]		= 0x03;	g_bsinfo.mac_addr[3]		= 0x04;	g_bsinfo.mac_addr[4]		= 0x05;	g_bsinfo.mac_addr[5]		= 0x06;	g_bsinfo.frame_duration_code	= 2;	g_bsinfo.mac_version		= 4;	g_bsinfo.ranging_backoff_start	= 0;	g_bsinfo.ranging_backoff_end	= 5;	g_bsinfo.request_backoff_start	= 0;	g_bsinfo.request_backoff_end	= 5;	g_bsinfo.initial_ranging_codes	= 4;	g_bsinfo.periodic_ranging_codes	= 4;	g_bsinfo.bandwidth_request_codes= 4;	g_bsinfo.periodic_ranging_backoff_start	= 2;	g_bsinfo.periodic_ranging_backoff_end	= 6;	g_bsinfo.start_of_ranging_codes_group	= 0;	g_bsinfo.bp_active->nr = 16;	for ( i = 0; i < g_bsinfo.bp_active->nr; i++ ) {		g_bsinfo.bp_active->xiuc_fec[0][i] = i;//DIUC?? 4 bits 16 values		g_bsinfo.bp_active->xiuc_fec[1][i] = i;//UIUC??	}	g_bsinfo.allocation_start_time	= 9527;	g_bsinfo.dl_sym_slot		= DL_SYMBOLS_PER_SLOT;///2	g_bsinfo.ul_sym_slot		= UL_SYMBOLS_PER_SLOT;///3	g_bsinfo.nr_dlsymbol		= 28;	g_bsinfo.nr_ulsymbol		= 18;	g_bsinfo.dcd_interval		= 10000;//unit is ms	g_bsinfo.ucd_interval		= 10000;	g_bsinfo.ucd_transition		= 100;//unit is ms	g_bsinfo.dcd_transition		= 100;	return;}void set_ss0_default(){	int32_t i;	//配置第0个SS 的上下行突发描述类型	for ( i = 0; i < g_bsinfo.bp_active->nr; i++ )///16		if ( g_bsinfo.bp_active->xiuc_fec[0][i] == _QPSK_CC_12 )//xiuc_fec[0][i]  DIUC 			break;	g_ssinfo[0].diuc = i;	for ( i = 0; i < g_bsinfo.bp_active->nr; i++ )		if ( g_bsinfo.bp_active->xiuc_fec[1][i] == _QPSK_CC_12 )//xiuc_fec[1][i] UIUC 			break;	g_ssinfo[0].uiuc = i;	return;}void set_sf_default(){	sfattr_t *sf;//从这个函数可以看出来,所有的服务流包括广播服务流都是有服务流参数的//sf 就是g_serviceflow[0]	/* setup initial serviceflow */	sf = &g_serviceflow[0];	sf->ss = 0;	sf->sfid = sf->cid = 0;	sf->dir = DIR_DUPLEX;	sf->service_flow_scheduling_type = UPLINK_GRANT_SCHEDULING_TYPE_SIG;	sf->fixed_variable_length_indicator = VARIABLE_LENGTH_SDU;	sf->maximum_sustained_traffic_rate = ~0;	sf->maximum_traffic_burst = ~0;		/* setup broadcast serviceflow */	sf = &g_serviceflow[0xffff];	sf->ss = 0;	sf->sfid = sf->cid = 0xffff;	sf->dir = DIR_DOWNLINK;	sf->service_flow_scheduling_type = UPLINK_GRANT_SCHEDULING_TYPE_SIG;	sf->request_transmission_policy = 0;/*NO_FRAGMENT;*//*NO_PACK_FRAGMENT;*/	sf->fixed_variable_length_indicator = VARIABLE_LENGTH_SDU;	sf->maximum_sustained_traffic_rate = ~0;	sf->maximum_traffic_burst = ~0;	return;}int32_t sf_active(uint16_t cid){	sfattr_t *sf = &g_serviceflow[cid];	pthread_mutex_lock(&sf->mutex);	if ( sf->stat == SF_ACTIVE ) {		pthread_mutex_unlock(&sf->mutex);		return -1;	}	sf->stat = SF_ACTIVE;	switch ( sf->service_flow_scheduling_type ) {	case UPLINK_GRANT_SCHEDULING_TYPE_SIG :		sf->policy = SCHED_POLICY_SIG;		break;	case UPLINK_GRANT_SCHEDULING_TYPE_UGS :		sf->policy = SCHED_POLICY_UGS;		break;	case UPLINK_GRANT_SCHEDULING_TYPE_ERTPS :		sf->policy = SCHED_POLICY_ERTPS;		break;	case UPLINK_GRANT_SCHEDULING_TYPE_RTPS :		sf->policy = SCHED_POLICY_RTPS;		break;	case UPLINK_GRANT_SCHEDULING_TYPE_NRTPS :		sf->policy = SCHED_POLICY_NRTPS;		break;	case UPLINK_GRANT_SCHEDULING_TYPE_BE :	default :		sf->policy = SCHED_POLICY_BE;		break;	}	sf->priority = sf->policy;		pthread_mutex_lock(&g_dlschedque.mutex);	list_add_tail(&sf->dlink, &g_dlschedque.active->queue[sf->priority]);	set_bit(sf->priority, (volatile unsigned long *)g_dlschedque.active->bitmap);	g_dlschedque.active->nr_active++;	pthread_mutex_unlock(&g_dlschedque.mutex);	pthread_mutex_unlock(&sf->mutex);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -