📄 mac.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 + -