int main(void) { const unsigned int FrameLen = 36; unsigned char *macframe = malloc(FrameLen); // alloc MAC header until frame body // fill header with junk, to make this more interesting for (unsigned int i = 0; i < FrameLen; i++) { macframe[i] = 0xde; } set_proto_version(macframe, 0); set_type(macframe, 1); set_subtype(macframe, 1); set_to_ds(macframe, 1); set_from_ds(macframe, 0); set_retry(macframe, 0); set_more_data(macframe, 0); print_header(macframe); printf("Protocol version: %d\n", get_proto_version(macframe)); printf("Type: %d\n", get_type(macframe)); printf("Subtype: %d\n", get_subtype(macframe)); printf("Flags: To DS: %d From DS: %d Retry: %d More Data: %d\n", get_to_ds(macframe) != 0, get_from_ds(macframe) != 0, get_retry(macframe) != 0, get_more_data(macframe) != 0); free(macframe); }
void wlan_to_wlan(msdu_indicate_t *msdu, CIPHER_T ct, UWORD8 key_type, UWORD8 key_index, TYPESUBTYPE_T frm_type, asoc_entry_t *ae, BOOL_T use_same_buffer) { UWORD8 q_num = 0; UWORD8 tx_rate = 0; UWORD8 pream = 0; UWORD8 service_class= 0; UWORD8 *mac_hdr = 0; UWORD8 *tx_dscr = 0; UWORD16 mac_hdr_len = 0; void *amsdu_ctxt = NULL; UWORD8 is_amsdu = 0; BOOL_T is_qos = BFALSE; BOOL_T is_htc = BFALSE; msdu_desc_t *buff_desc = &(msdu->frame_desc); UWORD32 phy_tx_mode = 0; UWORD32 sta_index = INVALID_ID; buffer_desc_t buffer_desc = {0}; UWORD32 retry_set[2] = {0}; #ifdef DEBUG_MODE g_mac_stats.w2w++; #endif /* DEBUG_MODE */ /* Find the queue to which this packet needs to be added */ q_num = get_w2w_txq_num_ap(msdu->priority); if(ae != NULL) sta_index = ae->sta_index; /* If the queue for which this packet belongs is full, then return */ if(is_txq_full(q_num, sta_index) == BTRUE) { return; } /* Prepare the buffer descriptor for the payload based on the flag to */ /* use the same buffer. If the frame is to be sent on both WLAN as well */ /* as the host there may be cases in which the payload portion needs to */ /* be modified to be sent to the host. This causes the packet being sent */ /* on WLAN to be altered if the same buffer is used. As a result the */ /* same buffer cannot be used for transmitting on WLAN in this case. */ /* However if the packet is to be sent only on WLAN this problem does */ /* not occur and hence the same buffer can be used. */ if(use_same_buffer == BTRUE) { /* Add one user to the incoming buffer. This ensures that the buffer */ /* will remain allocated even after the process rx frame function */ /* frees it. */ mem_add_users(g_shared_pkt_mem_handle, buff_desc->buffer_addr, 1); /* Prepare a buffer descriptor with required information */ buffer_desc.buff_hdl = buff_desc->buffer_addr; buffer_desc.data_offset = buff_desc->data_offset; buffer_desc.data_length = buff_desc->data_len; } else { UWORD8 *out_data = 0; /* Allocate a new buffer for the payload outgoing on WLAN */ out_data = (UWORD8*)pkt_mem_alloc(MEM_PRI_TX); if(out_data == NULL) return; /* Prepare a buffer descriptor with required information */ buffer_desc.buff_hdl = out_data; buffer_desc.data_offset = MAX_MAC_HDR_LEN; buffer_desc.data_length = buff_desc->data_len; if(buffer_desc.data_offset + buff_desc->data_len > SHARED_PKT_MEM_BUFFER_SIZE){ printk("@@@:BUG! bad memcpy offset:%d, len:%d\n", buffer_desc.data_offset, buff_desc->data_len); } /* Copy the payload from the incoming packet to the outgoing buffer */ memcpy(buffer_desc.buff_hdl + buffer_desc.data_offset, buff_desc->buffer_addr + buff_desc->data_offset, buff_desc->data_len); } /* Set the transmit rate to the required value. To support Multi-Rate */ /* the transmit rate is set to the maximum basic rate and the preamble */ /* is set to Long. */ if(is_group(msdu->da) == BTRUE) { /* For multicast frames send frames at maximum rate */ tx_rate = get_max_basic_rate(); pream = 1; service_class = BCAST_NO_ACK; /* Update the retry set information for this frame */ update_retry_rate_set(0, tx_rate, 0, retry_set); } else { /* Get the transmit rate for the associated station based on the */ /* auto-rate, multi-rate or user-rate settings. The preamble must be */ /* set accordingly. */ if(!ae) printk("@@@:BUG ae==NULL to get rate\n"); tx_rate = get_tx_rate_to_sta(ae); pream = get_preamble(tx_rate); service_class = g_ack_policy; /* Update the retry set information for this frame */ update_retry_rate_set(1, tx_rate, ae, retry_set); } /* AMSDU on WLAN-WLAN path is disabled since no space currently exists */ /* in the RX-Buffer to add the sub-MSDU header */ #ifdef TX_MACHDR_IN_DSCR_MEM /* Check whether AMSDU aggregation is possible */ amsdu_ctxt = get_amsdu_handle(msdu->da, msdu->priority, q_num, ae, buff_desc->data_len, 1, tx_rate); #endif /* TX_MACHDR_IN_DSCR_MEM */ /* Check whether AMSDU option is enabled */ is_amsdu = (amsdu_ctxt != NULL); /* Check whether AMSDU aggregation is not supported or if this is the */ /* first sub-MSDU of an AMSDU. */ if((0 == is_amsdu) || (NULL == amsdu_get_tx_dscr(amsdu_ctxt))) { /* Check whether QoS option is implemented */ is_qos = is_qos_required(sta_index); /* Check whether the receiver is HT capable */ is_htc = is_htc_capable(ae); /* Create the transmit descriptor and set default contents */ tx_dscr = create_default_tx_dscr(is_qos, msdu->priority, is_amsdu); if(tx_dscr == NULL) { if(is_amsdu == 1) { /* If allocation of the AMSDU decriptor has failed, then */ /* attempt transmission of the MSDU as a normal-MSDU. */ free_amsdu_handle(amsdu_ctxt); is_amsdu = 0; amsdu_ctxt = NULL; tx_dscr = create_default_tx_dscr(is_qos, msdu->priority, is_amsdu); } if(tx_dscr == NULL) { //caisf add 2013-02-15 if(g_mac_net_stats) g_mac_net_stats->tx_dropped++; pkt_mem_free(buffer_desc.buff_hdl); return; } } /* Update the AMSDU handle with the tx descriptor */ if(1 == is_amsdu) amsdu_set_tx_dscr(amsdu_ctxt, tx_dscr); /* Create the MAC header of the out-going frame */ #ifdef TX_MACHDR_IN_DSCR_MEM mac_hdr = mem_alloc(g_shared_dscr_mem_handle, MAX_MAC_HDR_LEN); if(NULL == mac_hdr) { free_tx_dscr((UWORD32 *)tx_dscr); //caisf add 2013-02-15 if(g_mac_net_stats) g_mac_net_stats->tx_dropped++; pkt_mem_free(buffer_desc.buff_hdl); free_amsdu_handle(amsdu_ctxt); return; } #else /* TX_MACHDR_IN_DSCR_MEM */ mac_hdr = buffer_desc.buff_hdl + buffer_desc.data_offset - MAX_MAC_HDR_LEN; #endif /* TX_MACHDR_IN_DSCR_MEM */ /* Reset the frame control field. Set type/subtype extracted from the */ /* incoming frame and set 'from_ds' bit in the outgoing frame. */ /* Also set the Security type for the outgoing frame based on cipher type*/ mac_hdr_len = set_mac_hdr_prot(mac_hdr, msdu->priority, service_class, is_qos, is_htc, is_amsdu); set_from_ds(mac_hdr, 1); if(ct != NO_ENCRYP) set_wep(mac_hdr, 1); /* Set Destination Address (DA), BSSID and Source Address (SA) in the */ /* outgoing frame. */ set_address1(mac_hdr, msdu->da); set_address2(mac_hdr, mget_bssid()); set_address3(mac_hdr, msdu->sa); /* Set the mac header related parameters in the Tx descriptor */ set_tx_dscr_buffer_addr((UWORD32 *)tx_dscr, (UWORD32)mac_hdr); set_tx_dscr_mh_len((UWORD32 *)tx_dscr, mac_hdr_len); set_tx_dscr_mh_offset((UWORD32 *)tx_dscr, 0); /* Get the PHY transmit mode based on the transmit rate and preamble */ phy_tx_mode = get_dscr_phy_tx_mode(tx_rate, pream, (void *)ae); /* Set the Tx-descriptor parameters */ set_tx_params(tx_dscr, tx_rate, pream, service_class, phy_tx_mode, retry_set); set_tx_dscr_q_num((UWORD32 *)tx_dscr, q_num); /* Set Security Parameters for the frame */ set_tx_security(tx_dscr, ct, key_type, key_index); /* Set the HT power save parameters */ set_ht_ps_params(tx_dscr, (void *)ae, tx_rate); /* Set the receiver address LUT index */ set_ht_ra_lut_index(tx_dscr, get_ht_handle_entry((void *)ae), msdu->priority, tx_rate); } else tx_dscr = amsdu_get_tx_dscr(amsdu_ctxt); /* Set the sub-MSDU info table in the Tx-Descriptor */ set_submsdu_info(tx_dscr, &buffer_desc, 1, buffer_desc.data_length, mac_hdr_len, msdu->sa, msdu->da, amsdu_ctxt); /* Update the TSF timestamp */ update_tx_dscr_tsf_ts((UWORD32 *)tx_dscr); /* Transmit the MSDU */ if(BTRUE == is_tx_ready(amsdu_ctxt)) { // 20120709 caisf mod, merged ittiam mac v1.2 code if(BTRUE == tx_data_packet((UWORD8 *)ae, msdu->da, msdu->priority, q_num, tx_dscr, amsdu_ctxt)) { /* Increment count indicating packet added to Hw queue */ /* Check if packet Bcast/Mcast or Unicast */ if(is_group(msdu->da) == BTRUE) { g_num_mc_bc_qd_pkt++; } else { ae->num_qd_pkt++; } } } }