📄 ingress.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 <stdlib.h>#include <string.h>#include "list.h"#include "task.h"#include "mac.h"#include "wxbuff.h"static void macpdu_decode(wxbuff_t *wxb);static void grantmngshdr_decode(uint8_t *buffer, uint16_t cid);static void fragment_decode(wxbuff_t *wxb, uint32_t offset, uint32_t length, uint16_t cid, int8_t ext);static void packing_decode(wxbuff_t *wxb, uint32_t offset, uint32_t length, uint16_t cid, int8_t ext);static void macsignalinghdr1_decode(uint8_t *buffer);static void macsignalinghdr2_decode(uint8_t *buffer);int32_t ingress_init(){ return 0;}void * do_task_burst_decode(void *arg){ struct list_head hdr, *pos, *tmp; wxbuff_t *wxb; genmachdr_t machdr; uint32_t len; int32_t exit; for ( ; ; ) { pos = ringq_deque(&tq_bst_rx); wxb = list_entry(pos, wxbuff_t, senior); list_add_tail(&hdr, &wxb->junior); exit = 0; list_for_each_safe(pos, tmp, &hdr) { wxb = list_entry(pos, wxbuff_t, junior); job: while ( wxb->len >= sizeof(genmachdr_t) ) { wxb->mac = (genmachdr_t *)wxb->beg; /* if HCS checksum fails, which means we cannot * deduce len correctly from MAC header, `exit = 1; break;' * discard all the remaining burst. */ /* ... */ if ( genmachdr_get_cid(wxb->mac) == 0xfffe ) { exit = 1; break; } if ( wxb->mac->ht == 0 ) { len = genmachdr_get_len(wxb->mac); if ( len < sizeof(genmachdr_t) || len > 2048 ) { exit = 1; break; } if ( len > wxb->len ) { wxbuff_t *_wxb = wxb; uint32_t _len = len; if ( (wxb = get_wxbuff(NULL)) == NULL ) break; wxbuff_push(wxb, _wxb->beg, _wxb->len); _len -= _wxb->len; _wxb = list_entry(tmp, wxbuff_t, junior); wxbuff_push(wxb, _wxb->beg, _len); _wxb->beg += _len; _wxb->len -= _len; list_add(&wxb->junior, pos); pos = pos->next; } } else len = sizeof(bwrmachdr_t); macpdu_decode(wxb); wxb->beg += len; wxb->len -= len; } if ( exit ) break; if ( wxb->len > 0 && tmp != &hdr ) { wxbuff_t *_wxb = list_entry(tmp, wxbuff_t, junior); uint32_t _len = sizeof(genmachdr_t) - wxb->len; if ( _wxb->len < _len ) break; memcpy(&machdr, wxb->beg, wxb->len); memcpy((uint8_t *)&machdr+wxb->len, _wxb->beg, _len); /* if HCS checksum fails, which means we cannot * deduce len correctly from MAC header, `break;' * discard all the remaining burst. */ /* ... */ if ( genmachdr_get_cid(&machdr) == 0xfffe ) break; if ( machdr.ht == 0 ) { len = genmachdr_get_len(&machdr); if ( len < sizeof(genmachdr_t) || len > 2048 ) break; if ( (wxb = get_wxbuff(NULL)) == NULL ) break; wxbuff_push(wxb, (uint8_t *)&machdr, sizeof(genmachdr_t)); _wxb->beg += _len; _wxb->len -= _len; wxbuff_push(wxb, _wxb->beg, len-_len); list_add(&wxb->junior, pos); pos = pos->next; goto job; } else { if ( machdr.ec == 0 ) macsignalinghdr1_decode((uint8_t *)&machdr); else macsignalinghdr2_decode((uint8_t *)&machdr); _wxb->beg += _len; _wxb->len -= _len; } } } list_for_each_safe(pos, tmp, &hdr) { wxb = list_entry(pos, wxbuff_t, junior); put_wxbuff(wxb); } } return NULL;}/* @length: the length of all the remaining data in the burst, including the current pdu. */void macpdu_decode(wxbuff_t *wxb){ uint32_t m, len = 0, off = 0; uint16_t cid; int8_t ext = 0; wxbuff_t *_wxb; wxb->mac = (genmachdr_t *)wxb->beg; /* if generic MAC header. */ if ( wxb->mac->ht == 0 ) { len = genmachdr_get_len(wxb->mac); cid = genmachdr_get_cid(wxb->mac); /* if the cid is not valid/active at all. */ pthread_mutex_lock(&g_serviceflow[cid].mutex); if ( g_serviceflow[cid].stat == SF_INVALID ) { pthread_mutex_unlock(&g_serviceflow[cid].mutex); return; } pthread_mutex_unlock(&g_serviceflow[cid].mutex); g_serviceflow[cid]._data += len; /* if CRC checksum fails, `return; wxb->beg += len; wxb->len -= len;' * discard just the current MAC message. */ /* ... */ off += sizeof(*(wxb->mac)); m = len - (wxb->mac->ci==1 ? 4 : 0) - sizeof(*(wxb->mac)); if ( wxb->mac->type & MESH_SUBHDR_MASK ) { /* Obviously, we have no need to support MESH mode. */ } if ( wxb->mac->type & GRANT_MANAGEMENT_SUBHDR_MASK ) { grantmngshdr_decode(wxb->beg+off, cid); off += sizeof(grantmngshdr_t); m -= sizeof(grantmngshdr_t); } if ( wxb->mac->type & ARQ_FEEDBACK_PAYLOAD_MASK ) { /* we will not implement this in step ONE. */ } if ( wxb->mac->type & EXTENDED_TYPE_MASK ) ext = 1; if ( wxb->mac->type & FRAGMENTATION_SUBHDR_MASK ) { fragment_decode(wxb, off, m, cid, ext); return; } else if ( wxb->mac->type & PACKING_SUBHDR_MASK ) { packing_decode(wxb, off, m, cid, ext); return; } /* standalone sdu, definitely no more than 2K bytes, * just use one wxbuff to reference the data. */ if ( (_wxb = get_wxbuff(wxb)) == NULL ) return; _wxb->beg = wxb->beg + off; _wxb->end = _wxb->beg + m; _wxb->tolen = _wxb->len = m; _wxb->cid = cid; if ( is_basic_cid(cid) || is_primary_cid(cid) || cid == 0 ) ringq_enque(&tq_sig_rx, &_wxb->junior); else ringq_enque(&tq_logger, &_wxb->junior); } else { wxb->mac->ec == 0 ? macsignalinghdr1_decode(wxb->beg) : macsignalinghdr2_decode(wxb->beg); } return;}/* @length: the length of the fragment, including fragmentation subheader but excluding other subheaders or mac header. */void fragment_decode(wxbuff_t *wxb, uint32_t offset, uint32_t length, uint16_t cid, int8_t ext){ uint32_t fc, fsn; wxbuff_t *_wxb; if ( ext == 1 ) { extfragshdr_t *efshdr = (extfragshdr_t *)(wxb->beg+offset); fc = efshdr->fc; fsn = extfragshdr_get_fsn(efshdr); offset += sizeof(extfragshdr_t); length -= sizeof(extfragshdr_t); } else { fragshdr_t *fshdr = (fragshdr_t *)(wxb->beg+offset); fc = fshdr->fc; fsn = fshdr->fsn; offset += sizeof(fragshdr_t); length -= sizeof(fragshdr_t); } /* becase there are no other threads want to modify fc and fsn, don't lock mutex. */ if ( is_fcfsn_valid(g_serviceflow[cid].fc, g_serviceflow[cid].fsn, fc, fsn, ext) ) { g_serviceflow[cid].fc = fc; g_serviceflow[cid].fsn = ext ? (fsn+1) & 0x7ff : (fsn+1) & 0x7; if ( (_wxb = get_wxbuff(wxb)) == NULL ) goto clean; _wxb->beg = wxb->beg + offset; _wxb->end = wxb->beg + length; _wxb->len = length; if ( softq_enque_tail(&g_softque[cid], _wxb) < 0 ) { put_wxbuff(_wxb); goto clean; } if ( fc == NO_FRAG || fc == LAST_FRAG ) { uint32_t l = g_softque[cid].size; _wxb = softq_dump(&g_softque[cid]); _wxb->tolen = l; _wxb->cid = cid; if ( is_basic_cid(cid) || is_primary_cid(cid) || cid == 0 ) ringq_enque(&tq_sig_rx, &_wxb->senior); else ringq_enque(&tq_logger, &_wxb->senior); } } else { //g_serviceflow[cid].fc = NO_FRAGMENTATION; struct list_head hdr, *pos, *tmp; clean: if ( (_wxb = softq_dump(&g_softque[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;}/* @length: the length of the packing, including all the the packing subheader but excluing other subheaders or mac header. */void packing_decode(wxbuff_t *wxb, uint32_t offset, uint32_t length, uint16_t cid, int8_t ext){ uint32_t len, off; uint32_t fc, fsn; wxbuff_t *_wxb; off = len = 0; while ( off < length ) { if ( ext ) { extpackshdr_t *epshdr = (extpackshdr_t *)(wxb->beg+offset+off); len = extpackshdr_get_len(epshdr) - sizeof(extpackshdr_t); fc = epshdr->fc; fsn = extpackshdr_get_fsn(epshdr); off += sizeof(extpackshdr_t); } else { packshdr_t *pshdr = (packshdr_t *)(wxb->beg+offset+off); len = packshdr_get_len(pshdr) - sizeof(packshdr_t); fc = pshdr->fc; fsn = pshdr->fsn; off += sizeof(packshdr_t); } if ( is_fcfsn_valid(g_serviceflow[cid].fc, g_serviceflow[cid].fsn, fc, fsn, ext) ) { g_serviceflow[cid].fc = fc; g_serviceflow[cid].fsn = ext ? (fsn+1) & 0x7ff : (fsn+1) & 0x7; if ( (_wxb = get_wxbuff(wxb)) == NULL ) goto clean; _wxb->beg = wxb->beg + offset + off; _wxb->end = _wxb->beg + len; _wxb->len = len; if ( softq_enque_tail(&g_softque[cid], _wxb) < 0 ) { put_wxbuff(_wxb); goto clean; } if ( fc == NO_FRAG || fc == LAST_FRAG ) { uint32_t l = g_softque[cid].size; _wxb = softq_dump(&g_softque[cid]); _wxb->tolen = l; _wxb->cid = cid; if ( is_basic_cid(cid) || is_primary_cid(cid) || cid == 0 ) ringq_enque(&tq_sig_rx, &_wxb->senior); else ringq_enque(&tq_logger, &_wxb->senior); } } else { //g_serviceflow[cid].fc = NO_FRAGMENTATION; struct list_head hdr, *pos, *tmp; clean: if ( (_wxb = softq_dump(&g_softque[cid])) ) { list_add_tail(&hdr, &_wxb->junior); list_for_each_safe(pos, tmp, &hdr) { _wxb = list_entry(pos, wxbuff_t, junior); put_wxbuff(_wxb); } } } off += len; } return;}void grantmngshdr_decode(uint8_t *buffer, uint16_t cid){ grantmngshdr_t *hdr = (grantmngshdr_t *)buffer; if ( g_serviceflow[cid].service_flow_scheduling_type == UPLINK_GRANT_SCHEDULING_TYPE_UGS) { } else if ( g_serviceflow[cid].service_flow_scheduling_type == UPLINK_GRANT_SCHEDULING_TYPE_ERTPS) { } else { g_serviceflow[cid].bwr += hdr->none.pbr; } return;}void macsignalinghdr1_decode(uint8_t *buffer){ uint16_t cid; bwrmachdr_t *hdr = (bwrmachdr_t *)buffer; cid = bwrmachdr_get_cid(hdr); pthread_mutex_lock(&g_serviceflow[cid].mutex); if ( g_serviceflow[cid].stat == SF_INVALID ) { pthread_mutex_unlock(&g_serviceflow[cid].mutex); return ; } pthread_mutex_unlock(&g_serviceflow[cid].mutex); if ( hdr->type == BR_INCREMENTAL ) { g_serviceflow[cid].bwr += bwrmachdr_get_bwr(hdr); g_serviceflow[cid]._bwr += bwrmachdr_get_bwr(hdr); } else if ( hdr->type == BR_AGGREGATE ) { g_serviceflow[cid].bwr = bwrmachdr_get_bwr(hdr); g_serviceflow[cid]._bwr += bwrmachdr_get_bwr(hdr); } else if ( hdr->type == PHY_CHANNEL_REPORT ) { /* not implemented yet */ } else if ( hdr->type == BR_WITH_UL_TX_POWER_REPORT ) { /* not implemented yet */ } else if ( hdr->type == BANDWIDTH_REQUEST_AND_CINR_REPORT ) { /* not implemented yet */ } else if ( hdr->type == BR_WITH_UL_SLEEP_CONTROL ) { /* not implemented yet */ } else if ( hdr->type == SN_REPORT ) { /* not implemented yet */ } else if ( hdr->type == CQICH_ALLOCATION_REQUEST ) { /* not implemented yet */ } return;}void macsignalinghdr2_decode(uint8_t *buffer){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -