Files
kunlun/plc/halmac/crc/mac_crc.c
2024-09-28 14:24:04 +08:00

695 lines
19 KiB
C
Executable File

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "iot_io.h"
#include "mac_rx_buf_ring.h"
#include "hw_tonemap.h"
#include "iot_config.h"
#include "mac_txq_hw.h"
#include "plc_mac_header.h"
#include "plc_const.h"
#include "mac_tx_hw.h"
#include "rx_pb_reorder.h"
#include "mac_crc.h"
#include "mac_rx_hw.h"
#include "hw_tonemap.h"
#include "mpdu_header.h"
#include "mac_sched_hw.h"
#include "iot_system_api.h"
const uint32_t mac_crc24_init_proto_tab[] = {
CRC24_INIT_VECT_SG, /* 0: PLC_PROTO_TYPE_SG */
CRC24_INIT_VECT_GP, /* 1: PLC_PROTO_TYPE_GP */ //TODO: need to confirm
CRC24_INIT_VECT_GP, /* 2: PLC_PROTO_TYPE_AV */ //TODO: need to confirm
CRC24_INIT_VECT_SPG /* 3: PLC_PROTO_TYPE_SPG */
};
/* fc crc */
uint32_t mac_crc_get_fc_swcrc(uint32_t proto, void *fc)
{
IOT_ASSERT(fc);
uint8_t mpdu_fc_len = mac_get_mpdu_fc_len(proto);
uint8_t mpdu_fccs_len = mac_get_mpdu_fccs_len(proto);
IOT_ASSERT(mpdu_fc_len > mpdu_fccs_len);
return iot_getcrc24((uint8_t *)fc, (uint8_t)(mpdu_fc_len - mpdu_fccs_len));
}
/* pb crc */
/**
* if fw set pb_header fill in payload, pb_head = NULL;
* otherwise pb_head = actual pb header buffer point
*/
uint32_t mac_crc_get_pb_swcrc(uint32_t proto, void *pb_head, uint8_t *payload,
uint32_t pb_sz, uint8_t delimiter)
{
uint32_t crc = 0;
uint8_t pb_crc_len = 0, pb_hdr_crc_len = 0, pb_hdr_len = 0;
#if IOT_CRC_DBG_ENABLE
uint32_t buffer[4] = {0};
buffer[0] = pb_sz;
buffer[1] = (uint32_t)pb_head;
buffer[2] = (uint32_t)payload;
IOT_ASSERT_DUMP(((pb_sz >= PB_SIZE_72 && pb_sz <= PB_SIZE_520)
&& (iot_data_addr_legal((uint32_t)pb_head))
&& (iot_data_addr_legal((uint32_t)payload))), buffer, 4);
#endif
switch(delimiter)
{
case FC_DELIM_BEACON:
pb_hdr_crc_len = mac_get_pb_hdr_crc_len(FC_DELIM_BEACON, proto);
#if SUPPORT_IEEE_1901
crc = iot_getcrc32_update(CRC32_INIT_VECT_I1901, payload,
pb_sz - pb_hdr_crc_len);
#else
crc = iot_getcrc24((uint8_t *)payload, pb_sz - pb_hdr_crc_len);
#endif
break;
case FC_DELIM_SOF:
pb_crc_len = mac_get_pb_crc_len(FC_DELIM_SOF, proto);
pb_hdr_crc_len = mac_get_pb_hdr_crc_len(FC_DELIM_SOF, proto);
pb_hdr_len = mac_get_pb_hdr_len(FC_DELIM_SOF, proto);
if (NULL == pb_head)
{
#if SUPPORT_IEEE_1901
crc = iot_getcrc32_update(CRC32_INIT_VECT_I1901, payload,
pb_sz - pb_crc_len);
#else
crc = iot_getcrc24(payload, pb_sz - pb_crc_len);
#endif
}
else
{
#if IOT_CRC_DBG_ENABLE
buffer[3] = pb_hdr_crc_len;
IOT_ASSERT_DUMP((pb_sz > pb_hdr_crc_len), buffer, 4);
#endif
#if SUPPORT_IEEE_1901
crc = iot_getcrc32_update(CRC32_INIT_VECT_I1901, (uint8_t *)pb_head,
pb_hdr_len);
crc = iot_getcrc32_update(crc, payload, pb_sz - pb_hdr_crc_len);
#else
crc = iot_getcrc24_update(mac_crc24_init_proto_tab[proto],
(uint8_t *)pb_head, pb_hdr_len);
crc = iot_getcrc24_update(crc, payload, pb_sz - pb_hdr_crc_len);
#endif
}
break;
default:
crc = (uint32_t)CRC_INIT_VECT_DEFAULT;
break;
}
return crc;
}
/* bcn crc */
uint32_t mac_crc_get_bcn_swcrc(uint32_t proto, void *payload, uint32_t pb_sz,
uint32_t *crc_value)
{
IOT_ASSERT(payload);
uint8_t pb_pld_crc_len = mac_get_pb_pld_crc_len(FC_DELIM_BEACON, proto);
uint8_t pb_crc_len = mac_get_pb_crc_len(FC_DELIM_BEACON, proto);
uint8_t pb_resv_len = 0;
if (PLC_PROTO_TYPE_SPG == proto)
pb_resv_len = 1;
int32_t sl = pb_sz - pb_crc_len - pb_pld_crc_len - pb_resv_len;
if(sl < 0)
{
return ERR_CRC_LEN;
}
#if SUPPORT_IEEE_1901
*crc_value = iot_getcrc32_update(CRC32_INIT_VECT_I1901, (uint8_t *)payload,
(uint32_t)sl);
#else
*crc_value = iot_getcrc32((uint8_t *)payload, (uint32_t)sl);
#endif
return ERR_OK;
}
uint8_t mac_crc_set_bcn_swcrc(uint32_t proto, void *payload, uint32_t pb_sz)
{
uint32_t crc = 0, data_len = 0;
uint8_t pb_crc_len = 0;
uint8_t pb_pld_crc_len = 0;
uint8_t pb_resv_len = 0;
IOT_ASSERT(payload);
switch (proto)
{
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
break;
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
pb_resv_len = 1;
break;
#endif
default:
return ERR_NOSUPP;
}
pb_crc_len = mac_get_pb_crc_len(FC_DELIM_BEACON, proto);
pb_pld_crc_len = mac_get_pb_pld_crc_len(FC_DELIM_BEACON, proto);
if (mac_tx_hw_get_bcn_swcrc_cfg())
{
IOT_ASSERT(payload);
uint32_t ret = 0;
ret = mac_crc_get_bcn_swcrc(proto, payload, pb_sz, &crc);
if(ret){
return (uint8_t)ret;
}
data_len = pb_sz - pb_crc_len - pb_pld_crc_len - pb_resv_len;
os_mem_cpy((uint8_t *)payload + data_len, &crc,
pb_pld_crc_len);
}
return ERR_OK;
}
uint32_t mac_crc_get_msdu_swcrc(uint32_t proto, iot_pkt_t *msdu)
{
uint8_t *data = NULL, crc_len = 0;
uint16_t msdu_len = 0;
uint32_t crc = 0;
IOT_ASSERT(msdu);
switch (proto)
{
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
mac_header_t *sg_mac = (mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)sg_mac;
if (sg_mac->mac_exist_flag)
{
data += MAC_HDR_LEN_WITH_ADDR;
}
else
{
data += MAC_HDR_LEN_NO_ADDR;
}
msdu_len = sg_mac->msdu_len;
crc_len = SG_MAC_MSDU_CRC_LEN;
break;
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
spg_mac_header_t *spg_mac = (spg_mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)spg_mac;
if (spg_mac->mac_hdr_type)
{
data += sizeof(spg_mac_header_t);
}
else
{
data += sizeof(spg_mac_header_t) + sizeof(spg_mac_lheader_tail_t);
}
msdu_len = spg_mac->msdu_len;
crc_len = SPG_MAC_MSDU_CRC_LEN;
break;
}
#endif
#if SUPPORT_GREEN_PHY
case PLC_PROTO_TYPE_GP:
{
gp_mac_header_t *gp_mac = (gp_mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)gp_mac;
if (gp_mac->mft == 0 || gp_mac->mft == 1)
{
data += sizeof(gp_mac_header_t);
}
else
{
data += sizeof(gp_mac_header_t) + sizeof(gp_ats_or_cfder_t);
}
msdu_len = gp_mac->mfl;
crc_len = GP_MAC_MSDU_CRC_LEN;
break;
}
#endif
default:
return (uint32_t)CRC_INIT_VECT_DEFAULT;
}
if (iot_pkt_data_len(msdu) < (uint32_t)((uint32_t)msdu_len +
(uint32_t)crc_len + (uint32_t)(data - iot_pkt_data(msdu))))
{
return (uint32_t)CRC_INIT_VECT_DEFAULT;
}
crc = iot_getcrc32(data, msdu_len);
return crc;
}
uint32_t mac_crc_get_msdu_srccrc(uint32_t proto, iot_pkt_t *msdu)
{
uint8_t *data = NULL, crc_len = 0;
uint16_t msdu_len = 0;
uint32_t crc = 0;
IOT_ASSERT(msdu);
switch (proto)
{
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
mac_header_t *sg_mac = (mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)sg_mac;
if (sg_mac->mac_exist_flag)
{
data += MAC_HDR_LEN_WITH_ADDR;
}
else
{
data += MAC_HDR_LEN_NO_ADDR;
}
msdu_len = sg_mac->msdu_len;
crc_len = SG_MAC_MSDU_CRC_LEN;
break;
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
spg_mac_header_t *spg_mac = (spg_mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)spg_mac;
if (spg_mac->mac_hdr_type)
{
data += sizeof(spg_mac_header_t);
}
else
{
data += sizeof(spg_mac_header_t) + sizeof(spg_mac_lheader_tail_t);
}
msdu_len = spg_mac->msdu_len;
crc_len = SPG_MAC_MSDU_CRC_LEN;
break;
}
#endif
#if SUPPORT_GREEN_PHY
case PLC_PROTO_TYPE_GP:
{
gp_mac_header_t *gp_mac = (gp_mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)gp_mac;
if (gp_mac->mft == 0 || gp_mac->mft == 1)
{
data += sizeof(gp_mac_header_t);
}
else
{
data += sizeof(gp_mac_header_t) + sizeof(gp_ats_or_cfder_t);
}
msdu_len = gp_mac->mfl;
crc_len = GP_MAC_MSDU_CRC_LEN;
break;
}
#endif
default:
return (uint32_t)CRC_INIT_VECT_DEFAULT;
}
if (iot_pkt_data_len(msdu) < (uint32_t)((uint32_t)msdu_len +
(uint32_t)crc_len + (uint32_t)(data - iot_pkt_data(msdu))))
{
return (uint32_t)CRC_INIT_VECT_DEFAULT;
}
os_mem_cpy(&crc, data + msdu_len, crc_len);
return crc;
}
uint8_t mac_crc_set_msdu_swcrc(uint32_t proto, iot_pkt_t *msdu)
{
uint8_t *data = NULL, crc_len = 0;
uint16_t msdu_len = 0;
uint32_t crc = 0;
IOT_ASSERT(msdu);
switch (proto)
{
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
#if SUPPORT_IEEE_1901
i1901_mac_header_t *i1901_mac;
i1901_mac = (i1901_mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)i1901_mac;
if (i1901_mac_hdr_var_is_valid(i1901_mac)) {
if (i1901_mac_hdr_var_addr_is_valid(i1901_mac)) {
data += MAC_HDR_LEN_WITH_VAR_ADDR_I1901;
} else {
data += MAC_HDR_LEN_WITH_VAR_I1901;
}
} else {
data += MAC_HDR_LEN_NO_VAR_I1901;
}
msdu_len = i1901_mac->msdu_len;
crc_len = I1901_MAC_MSDU_CRC_LEN;
#else /* SUPPORT_IEEE_1901 */
mac_header_t *sg_mac = (mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)sg_mac;
if (sg_mac->version == MAC_HEADER_SHORT_VER) {
mac_short_header_t *sg_mac_s =
(mac_short_header_t *)iot_pkt_data(msdu);
data += MAC_HDR_LEN_SHORT;
msdu_len = sg_mac_s->msdu_len;
} else {
if (sg_mac->mac_exist_flag)
{
data += MAC_HDR_LEN_WITH_ADDR;
}
else
{
data += MAC_HDR_LEN_NO_ADDR;
}
msdu_len = sg_mac->msdu_len;
#if SIMU_DBG == 1
if (sg_mac->msdu_type == 48)
{
iot_printf("mac sending msdu_type = 48, iot_pkt=0x%x\n",
msdu);
}
#endif
}
crc_len = SG_MAC_MSDU_CRC_LEN;
#endif /* SUPPORT_IEEE_1901 */
break;
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
spg_mac_header_t *spg_mac = (spg_mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)spg_mac;
if (spg_mac->version == SPG_MAC_HEADER_SHORT_VER) {
spg_mac_short_header_t *spg_mac_s =
(spg_mac_short_header_t *)iot_pkt_data(msdu);
data += MAC_SINGLE_HOP_HDR_LEN_SPG;
msdu_len = spg_mac_s->msdu_len;
} else {
if (spg_mac->mac_hdr_type) {
data += sizeof(spg_mac_header_t);
} else {
data += sizeof(spg_mac_header_t) +
sizeof(spg_mac_lheader_tail_t);
}
msdu_len = spg_mac->msdu_len;
}
crc_len = SPG_MAC_MSDU_CRC_LEN;
break;
}
#endif
#if SUPPORT_GREEN_PHY
case PLC_PROTO_TYPE_GP:
{
gp_mac_header_t *gp_mac = (gp_mac_header_t *)iot_pkt_data(msdu);
data = (uint8_t *)gp_mac;
if (gp_mac->mft == 0 || gp_mac->mft == 1)
{
data += sizeof(gp_mac_header_t);
}
else
{
data += sizeof(gp_mac_header_t) + sizeof(gp_ats_or_cfder_t);
}
msdu_len = gp_mac->mfl;
crc_len = GP_MAC_MSDU_CRC_LEN;
break;
}
#endif
default:
return ERR_NOSUPP;
}
if (iot_pkt_data_len(msdu) < (uint32_t)((uint32_t)msdu_len +
(uint32_t)crc_len + (uint32_t)(data - iot_pkt_data(msdu))))
{
return ERR_INVAL;
}
IOT_ASSERT(msdu_len);
#if SUPPORT_IEEE_1901
crc = iot_getcrc32_update(CRC32_INIT_VECT_I1901, data, msdu_len);
#else
crc = iot_getcrc32(data, msdu_len);
#endif
os_mem_cpy(data + msdu_len, &crc, crc_len);
return ERR_OK;
}
uint8_t mac_crc_mpdu_swcrc_verify(uint32_t proto, rx_buf_hdr_t *rx_buf_hdr,
uint8_t bit_mask)
{
uint8_t crc_ret = 0;
uint32_t pb_sz = 0;
uint32_t crc_src = 0, crc_cal = 0;
uint8_t *pb_payload = NULL;
uint8_t *tmp = NULL;
IOT_ASSERT(rx_buf_hdr);
pb_payload = (uint8_t *)rx_buf_hdr + PB_PAYLOAD_OFFSET;
uint8_t delimiter = (uint8_t)mac_get_rx_delimiter_from_fc(proto,
mac_rx_mpdu_st_get_fc_addr(&rx_buf_hdr->mpdu_st));
/* get rx fc message */
rx_fc_msg_t rx_fc_msg = {0};
mac_get_rx_frm_msg_from_fc(proto,
mac_rx_mpdu_st_get_fc_addr(&rx_buf_hdr->mpdu_st), &rx_fc_msg);
/* get pb size */
switch (delimiter)
{
case FC_DELIM_BEACON:
{
phy_get_pb_size(proto, rx_fc_msg.tmi, 0, &pb_sz);
break;
}
case FC_DELIM_SOF:
{
phy_get_pb_size(proto, rx_fc_msg.tmi, rx_fc_msg.tmi_ext, &pb_sz);
break;
}
default:
pb_sz = 0;
break;
}
/* debug msg */
#if (MAC_CRC_DEBUG_LEVEL > 1)
iot_printf("pb_sz = 0x%X, pb data is:\r\n", pb_sz);
uint32_t i = 0;
for (i = 0; i < pb_sz; i++)
{
iot_printf("0x%02X ", *(pb_payload + i));
}
iot_printf("\r\n");
#endif
/* fc - crc24 */
if (bit_mask & FC_CRC_ERR_MASK)
{
tmp = (uint8_t *)mac_rx_mpdu_st_get_fc_addr(&rx_buf_hdr->mpdu_st);
crc_cal = mac_crc_get_fc_swcrc(proto, tmp);
crc_src = rx_fc_msg.fccs;
if (crc_src != crc_cal)
{
crc_ret |= FC_CRC_ERR_MASK;
}
else
{
crc_ret &= ~FC_CRC_ERR_MASK;
}
#if (MAC_CRC_DEBUG_LEVEL)
iot_printf("fc crc, src=0x%08X, cal=0x%08X\r\n", crc_src, crc_cal);
#endif
}
/* pb crc - crc24 */
if (bit_mask & PB_CRC_ERR_MASK)
{
crc_src = mac_rx_pb_end_get_pb_crc(&rx_buf_hdr->pb_ed);
if (mac_rx_get_pb_hdr_to_buf_cfg())
{
crc_cal = mac_crc_get_pb_swcrc(proto, NULL,
pb_payload, pb_sz, delimiter);
}
else
{
switch (proto)
{
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
sg_sof_pb_hdr_t sg_pb_head = {0};
sg_pb_head.mac_frame_start =
(uint8_t)rx_buf_hdr->pb_st.first_pb;
sg_pb_head.mac_frame_end =
(uint8_t)rx_buf_hdr->pb_st.last_pb;
sg_pb_head.seq = (uint8_t)rx_buf_hdr->pb_st.ssn;
crc_cal = mac_crc_get_pb_swcrc(proto, &sg_pb_head,
pb_payload, pb_sz, delimiter);
break;
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
spg_sof_pb_hdr_t spg_pb_head = {0};
spg_pb_head.seq = (uint16_t)rx_buf_hdr->pb_st.ssn;
spg_pb_head.resv = 0;
crc_cal = mac_crc_get_pb_swcrc(proto, &spg_pb_head,
pb_payload, pb_sz, delimiter);
break;
}
#endif
#if SUPPORT_GREEN_PHY
case PLC_PROTO_TYPE_GP:
{
gp_sof_pb_hdr_t gp_pb_head = {0};
gp_pb_head.ssn = (uint16_t)rx_buf_hdr->pb_st.ssn;
crc_cal = mac_crc_get_pb_swcrc(proto, &gp_pb_head,
pb_payload, pb_sz, delimiter);
break;
}
#endif
default:
crc_cal = 0;
break;
}
}
if (crc_src != crc_cal)
{
crc_ret |= PB_CRC_ERR_MASK;
}
else
{
crc_ret &= ~PB_CRC_ERR_MASK;
}
#if (MAC_CRC_DEBUG_LEVEL)
iot_printf("pb crc, src=0x%08X, cal=0x%08X\r\n",
crc_src, crc_cal);
#endif
}
/* payload crc - crc32 */
if ((bit_mask & PAYLOAD_CRC_ERR_MASK) && (FC_DELIM_BEACON == delimiter))
{
uint8_t pb_hdr_resv_crc_len = mac_get_pb_hdr_resv_crc_len(FC_DELIM_BEACON, proto);
uint8_t pb_pld_crc_len = mac_get_pb_pld_crc_len(FC_DELIM_BEACON, proto);
tmp = pb_payload + pb_sz - pb_hdr_resv_crc_len - pb_pld_crc_len;
os_mem_cpy(&crc_src, tmp, pb_pld_crc_len);
mac_crc_get_bcn_swcrc(proto, pb_payload, pb_sz, &crc_cal);
if (crc_src != crc_cal)
{
crc_ret |= PAYLOAD_CRC_ERR_MASK;
}
else
{
crc_ret &= ~PAYLOAD_CRC_ERR_MASK;
}
#if (MAC_CRC_DEBUG_LEVEL)
iot_printf("bcn payload crc, src=0x%08X, cal=0x%08X\r\n",
crc_src, crc_cal);
#endif
}
#if (MAC_CRC_DEBUG_LEVEL)
if (NULL != rx_buf_hdr)
{
iot_printf("hw crc:bcn_crc=%d,pb_crc=%d,fc_crc=%d\r\n",
rx_buf_hdr->pb_ed.rx_beacon_pld_crc_err,
rx_buf_hdr->pb_ed.rx_pb_crc_err,
rx_buf_hdr->att.is_fcserr);
}
else
{
iot_printf("None rx pb\r\n");
}
iot_printf("sw crc cfg bit_mask = 0x%02X\r\n", bit_mask);
iot_printf("sw crc:payload_crc=%d,pb_crc=%d,fc_crc=%d\r\n",
(crc_ret & PAYLOAD_CRC_ERR_MASK) ? 1 : 0,
(crc_ret & PB_CRC_ERR_MASK) ? 1 : 0,
(crc_ret & FC_CRC_ERR_MASK) ? 1 : 0);
#endif
return crc_ret;
}
uint8_t mac_crc_msdu_swcrc_verify(uint32_t proto, iot_pkt_t *msdu)
{
uint8_t crc_ret = 0;
uint32_t crc_src, crc_cal;
IOT_ASSERT(msdu);
crc_src = mac_crc_get_msdu_srccrc(proto, msdu);
crc_cal = mac_crc_get_msdu_swcrc(proto, msdu);
if (crc_src != crc_cal)
{
crc_ret |= PAYLOAD_CRC_ERR_MASK;
}
else
{
crc_ret &= ~PAYLOAD_CRC_ERR_MASK;
}
#if (MAC_CRC_DEBUG_LEVEL)
iot_printf("msdu crc, src=0x%08X, cal=0x%08X\r\n",
crc_src, crc_cal);
#endif
return crc_ret;
}