- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/umac/src/txu/txu_cntrl.c

Go to the documentation of this file.

    00001
    00017 /*
    00018  * INCLUDE FILES
    00019  ****************************************************************************************
    00020  */
    00021 // for mode
    00022 #include "txl_cfm.h"
    00023 #include "txu_cntrl.h"
    00024 #include "ke_task.h"
    00025 #include "mac.h"
    00026 #include "mac_frame.h"
    00027 #include "sta_mgmt.h"
    00028 #include "llc.h"
    00029 #include "co_utils.h"
    00030 #include "co_endian.h"
    00031 #include "vif_mgmt.h"
    00032 #include "me_utils.h"
    00033 #include "bam.h"
    00034 #include "mm.h"
    00035 #include "tpc.h"
    00036 #if NX_MFP
    00037 #include "mfp.h"
    00038 #endif
    00039 #if (RW_MESH_EN)
    00040 #include "mesh.h"
    00041 #include "mesh_hwmp.h"
    00042 #include "mesh_ps.h"
    00043 #endif //(RW_MESH_EN)
    00044
    00045 /*
    00046  * PRIVATE FUNCTION DEFINITIONS
    00047  ****************************************************************************************
    00048  */
    00062 static bool txu_cntrl_logic_port_filter(uint8_t sta_idx, uint16_t eth_type,
    00063                                         uint16_t *flags)
    00064 {
    00065     uint8_t port_state = sta_mgmt_get_port_state(sta_idx);
    00066     uint16_t port_proto = sta_mgmt_get_port_ethertype(sta_idx);
    00067     bool is_port_proto = false;
    00068
    00069     if (eth_type == port_proto)
    00070     {
    00071         is_port_proto = true;
    00072         /* Don't use 4ADDR mode for connection frames */
    00073         *flags &= ~(TXU_CNTRL_USE_4ADDR);
    00074     }
    00075
    00076     /* Accept all packets if the port is OPEN */
    00077     if (port_state == PORT_OPEN)
    00078         return true;
    00079
    00080     /* Accept only port control packets if port is CONTROLED */
    00081     if ((port_state == PORT_CONTROLED) && (is_port_proto))
    00082     {
    00083         return true;
    00084     }
    00085
    00086     /* Discard all packets in all other cases */
    00087     return false;
    00088 }
    00089
    00102 static int txu_cntrl_sechdr_len_compute(struct txdesc *txdesc, int *tail_len)
    00103 {
    00104     struct hostdesc *host = &txdesc->host;
    00105     struct sta_info_tag *sta = &sta_info_tab[host->staid];
    00106     struct key_info_tag *key = *sta->sta_sec_info.cur_key;
    00107     struct vif_info_tag *vif = &vif_info_tab[host->vif_idx];
    00108     int head_len = 0;
    00109
    00110     // By default we consider that there won't be any tail
    00111     *tail_len = 0;
    00112
    00113     // Check if we have a valid key for this STA
    00114     if (!key || (vif->flags & CONTROL_PORT_NO_ENC &&
    00115                  co_ntohs(host->ethertype) == sta_mgmt_get_port_ethertype(host->staid)))
    00116         return 0;
    00117
    00118     // Check which type of security is used with this STA
    00119     switch(key->cipher)
    00120     {
    00121         case MAC_CIPHER_WEP40:
    00122         case MAC_CIPHER_WEP104:
    00123             head_len = IV_LEN;
    00124             *tail_len = ICV_LEN;
    00125             // Check if we need to get a fresh PN
    00126             if (!(host->flags & TXU_CNTRL_RETRY))
    00127             {
    00128                 key->tx_pn++;
    00129                 memcpy(host->pn, &key->tx_pn, 2 * sizeof(host->pn[0]));
    00130             }
    00131             break;
    00132         case MAC_CIPHER_TKIP:
    00133             head_len = IV_LEN + EIV_LEN;
    00134             *tail_len = MIC_LEN + ICV_LEN;
    00135             // Check if we need to get a fresh PN
    00136             if (!(host->flags & TXU_CNTRL_RETRY))
    00137             {
    00138                 key->tx_pn++;
    00139                 memcpy(host->pn, &key->tx_pn, 3 * sizeof(host->pn[0]));
    00140             }
    00141             break;
    00142         case MAC_CIPHER_CCMP:
    00143             head_len = IV_LEN + EIV_LEN;
    00144             *tail_len = MIC_LEN;
    00145             // Check if we need to get a fresh PN
    00146             if (!(host->flags & TXU_CNTRL_RETRY))
    00147             {
    00148                 key->tx_pn++;
    00149                 memcpy(host->pn, &key->tx_pn, 3 * sizeof(host->pn[0]));
    00150             }
    00151             break;
    00152         #if RW_WAPI_EN
    00153         case MAC_CIPHER_WPI_SMS4:
    00154             head_len = WPI_IV_LEN;
    00155             *tail_len = WPI_MIC_LEN;
    00156             if (!(host->flags & TXU_CNTRL_RETRY))
    00157             {
    00158                 if (key->hw_key_idx < MM_SEC_DEFAULT_KEY_COUNT) {
    00159                     // broadcast key
    00160                     key->tx_pn++;
    00161                 } else {
    00162                     // unicast key
    00163                     key->tx_pn+=2;
    00164                 }
    00165                 memcpy(host->pn, &key->tx_pn, 4 * sizeof(host->pn[0]));
    00166             }
    00167             break;
    00168         #endif
    00169         default:
    00170             ASSERT_ERR(0);
    00171             break;
    00172     }
    00173
    00174     return (head_len);
    00175 }
    00176
    00185 static void txu_cntrl_umacdesc_prep(struct txdesc *txdesc)
    00186 {
    00187     struct hostdesc *host = &txdesc->host;
    00188     struct umacdesc *umac = &txdesc->umac;
    00189     #if NX_HE
    00190     struct sta_info_tag *sta = &sta_info_tab[host->staid];
    00191     #endif
    00192     #if RW_MESH_EN || NX_HE
    00193     // Get VIF Information
    00194     struct vif_info_tag *vif = &vif_info_tab[host->vif_idx];
    00195     #endif //(RW_MESH_EN)
    00196     int head_len, tail_len, hdr_len_802_2 = 0;
    00197     uint16_t payl_len;
    00198
    00199     // Check if the STA has QoS enabled
    00200     if (host->tid != 0xFF)
    00201     {
    00202         // Packet shall be of type QoS
    00203         head_len = MAC_SHORT_QOS_MAC_HDR_LEN;
    00204         // Check if we need to get a fresh SN
    00205         if (!(host->flags & TXU_CNTRL_RETRY))
    00206             host->sn = sta_mgmt_get_tx_ssn_and_inc(host->staid, host->tid);
    00207
    00208         #if (RW_MESH_EN)
    00209         if (vif->type == VIF_MESH_POINT)
    00210         {
    00211             // Check if Mesh Control field is present
    00212             head_len += mesh_tx_data_prepare(vif, host, umac);
    00213         }
    00214         #endif //(RW_MESH_EN)
    00215     }
    00216     else
    00217     {
    00218         head_len = MAC_SHORT_MAC_HDR_LEN;
    00219     }
    00220
    00221     if (host->flags & TXU_CNTRL_USE_4ADDR)
    00222     {
    00223         head_len += (MAC_LONG_MAC_HDR_LEN - MAC_SHORT_MAC_HDR_LEN);
    00224     }
    00225
    00226     #if NX_HE
    00227     // Frames sent to a HE AP will include a +HTC HE Variant. If sent as HE SU, it will be
    00228     // set as the buffer status (BSR). If sent as HE TB, it will be set as the Uplink
    00229     // Power Headroom (UPH)
    00230     if ((vif->type == VIF_STA) && (STA_CAPA(sta, HE)))
    00231         head_len += MAC_HTC_LEN;
    00232     #endif
    00233
    00234     umac->machead_len = head_len;
    00235
    00236     // Update the header length
    00237     head_len += txu_cntrl_sechdr_len_compute(txdesc, &tail_len);
    00238
    00239     #if (RW_MESH_EN)
    00240     if (!(host->flags & TXU_CNTRL_MESH_FWD))
    00241     #endif //(RW_MESH_EN)
    00242     {
    00243         // Check if the Ethernet frame is of Type II or SNAP
    00244         if (co_ntohs(host->ethertype) > LLC_FRAMELENGTH_MAXVALUE)
    00245         {
    00246             // Update header length - LLC/SNAP will be added after buffer allocation
    00247             head_len += LLC_802_2_HDR_LEN;
    00248             hdr_len_802_2 = LLC_802_2_HDR_LEN;
    00249         }
    00250     }
    00251
    00252     // Compute payload length
    00253     #if NX_AMSDU_TX
    00254     if (host->flags & TXU_CNTRL_AMSDU)
    00255     {
    00256         head_len += sizeof_b(struct amsdu_hdr);
    00257     }
    00258
    00259     payl_len = 0;
    00260     for (int i = 0; i < host->packet_cnt; i++)
    00261     {
    00262         payl_len += host->packet_len[i];
    00263     }
    00264     #else
    00265     payl_len = host->packet_len;
    00266     #endif
    00267
    00268     // Update the different lengths
    00269     umac->payl_len = payl_len;
    00270     umac->head_len = head_len;
    00271     umac->tail_len = tail_len;
    00272     umac->hdr_len_802_2 = hdr_len_802_2;
    00273
    00274     #if NX_AMPDU_TX
    00275     umac->phy_flags = 0;
    00276     umac->flags = 0;
    00277     #endif
    00278 }
    00279
    00289 static void txu_cntrl_umacdesc_mgmt_prep(struct txdesc *txdesc, struct vif_info_tag *vif)
    00290 {
    00291     struct hostdesc *host = &txdesc->host;
    00292     struct umacdesc *umac = &txdesc->umac;
    00293     int head_len = 0, tail_len = 0;
    00294     uint8_t pwr_idx, i;
    00295
    00296     // Select the policy table to be used
    00297     if ((host->flags & TXU_CNTRL_MGMT_NO_CCK)
    00298             #if (NX_P2P)
    00299             || vif->p2p
    00300             #endif //(NX_P2P)
    00301         )
    00302     {
    00303         umac->buf_control = &txl_buffer_control_5G;
    00304     }
    00305     else
    00306     {
    00307         uint8_t band = vif->chan_ctxt->channel.band;
    00308
    00309         umac->buf_control = (band == PHY_BAND_2G4) ? &txl_buffer_control_24G : &txl_buffer_control_5G;
    00310     }
    00311
    00312     #if NX_MFP
    00313     if (host->flags & TXU_CNTRL_MGMT_ROBUST)
    00314     {
    00315         enum mfp_protection mfp;
    00316
    00317         /* still need to check if MFP is enable on this vif, and since
    00318            we don't know which mgmt frame is it, pretend it is DEAUTH */
    00319         mfp = mfp_protect_mgmt_frame(txdesc, MAC_FCTRL_DEAUTHENT, 0);
    00320
    00321         if (mfp == MFP_UNICAST_PROT)
    00322         {
    00323             head_len = txu_cntrl_sechdr_len_compute(txdesc, &tail_len);
    00324             //TODO: Use another policy table, as we will overwrite key index ?
    00325         }
    00326         else if (mfp == MFP_MULTICAST_PROT)
    00327         {
    00328             tail_len = MAC_MGMT_MIC_LEN;
    00329         }
    00330         else
    00331         {
    00332             host->flags &= ~TXU_CNTRL_MGMT_ROBUST;
    00333         }
    00334     }
    00335     #endif
    00336
    00337     // update TX Power in policy table
    00338     tpc_get_vif_tx_power(vif, NULL, &pwr_idx);
    00339     for (i = 0; i < RATE_CONTROL_STEPS; i++)
    00340     {
    00341         umac->buf_control->policy_tbl.powercntrlinfo[i] = TX_PWR_LEVEL_SET(pwr_idx);
    00342     }
    00343
    00344     // head_len and tail_len are used by LMAC.
    00345     umac->machead_len = 0;
    00346     umac->head_len = head_len;
    00347     umac->tail_len = tail_len;
    00348
    00349     #if (NX_AMPDU_TX)
    00350     umac->phy_flags = 0;
    00351     umac->flags = 0;
    00352     #endif //(NX_AMPDU_TX)
    00353 }
    00354
    00365 static uint32_t txu_cntrl_mac_hdr_append(struct txdesc *txdesc, uint32_t buf)
    00366 {
    00367     struct hostdesc *host = &txdesc->host;
    00368     #if (RW_MESH_EN)
    00369     struct umacdesc *umac_desc = &txdesc->umac;
    00370     #endif //(RW_MESH_EN)
    00371     struct vif_info_tag *vif = &vif_info_tab[host->vif_idx];
    00372     struct sta_info_tag *sta = &sta_info_tab[host->staid];
    00373     struct key_info_tag *key = *sta->sta_sec_info.cur_key;
    00374     struct mac_hdr_qos *machdr;
    00375     struct mac_hdr_long_qos *machdr_4a;
    00376     uint16_t *qos;
    00377     uint16_t order = 0;
    00378
    00379     #if NX_HE
    00380     // Write the +HTC HE Variant
    00381     if ((vif->type == VIF_STA) && (STA_CAPA(sta, HE)))
    00382     {
    00383         buf -= MAC_HTC_LEN;
    00384         co_write32p(buf, txl_he_htc_get(txdesc, sta));
    00385         order = MAC_FCTRL_ORDER;
    00386     }
    00387     #endif
    00388
    00389     buf -= MAC_SHORT_MAC_HDR_LEN;
    00390     if (host->tid != 0xFF)
    00391     {
    00392         buf -= MAC_HDR_QOS_CTRL_LEN;
    00393
    00394         #if (RW_MESH_EN)
    00395         if ((vif->type == VIF_MESH_POINT) && umac_desc->has_mesh_ctrl)
    00396         {
    00397             buf -= (MESH_CTRL_MIN_LEN + (umac_desc->nb_ext_addr * MAC_ADDR_LEN));
    00398         }
    00399         #endif //(RW_MESH_EN)
    00400     }
    00401
    00402     if (host->flags & TXU_CNTRL_USE_4ADDR)
    00403     {
    00404         buf -= (MAC_LONG_MAC_HDR_LEN - MAC_SHORT_MAC_HDR_LEN);
    00405         machdr = HW2CPU(buf);
    00406         machdr_4a = HW2CPU(buf);
    00407         qos = &(machdr_4a->qos);
    00408     }
    00409     else
    00410     {
    00411         machdr = HW2CPU(buf);
    00412         machdr_4a = NULL;
    00413         qos = &(machdr->qos);
    00414     }
    00415
    00416     // Check if the STA has QoS enabled
    00417     if (host->tid != 0xFF)
    00418     {
    00419         // Packet shall be of type QoS
    00420         machdr->fctl = MAC_QOS_ST_BIT;
    00421         *qos = host->tid << MAC_QOSCTRL_UP_OFT;
    00422         machdr->seq = host->sn << MAC_SEQCTRL_NUM_OFT;
    00423         #if NX_AMSDU_TX
    00424         if (host->flags & TXU_CNTRL_AMSDU)
    00425             *qos |= MAC_QOSCTRL_AMSDU_PRESENT;
    00426         #endif
    00427         if (host->flags & TXU_CNTRL_EOSP)
    00428         {
    00429             *qos |= MAC_QOSCTRL_EOSP;
    00430         }
    00431
    00432         #if (RW_MESH_EN)
    00433         if (vif->type == VIF_MESH_POINT)
    00434         {
    00435             if (umac_desc->has_mesh_ctrl)
    00436             {
    00437                 *qos |= MAC_QOSCTRL_MESH_CTRL_PRESENT;
    00438
    00439                 // Fill the Mesh Control Field
    00440                 mesh_tx_data_fill_mesh_ctrl(vif, CPU2HW(qos) + MAC_HDR_QOS_CTRL_LEN, host, umac_desc);
    00441             }
    00442             else if (host->flags & TXU_CNTRL_MESH_FWD)
    00443             {
    00444                 *qos |= MAC_QOSCTRL_MESH_CTRL_PRESENT;
    00445             }
    00446
    00447             if (txdesc->host.staid < NX_REMOTE_STA_MAX)
    00448             {
    00449                 // Set mesh PS information in the data frame
    00450                 mesh_ps_fill_qos(sta, qos);
    00451             }
    00452         }
    00453         #endif //(RW_MESH_EN)
    00454     }
    00455     else
    00456     {
    00457         machdr->fctl = 0;
    00458         machdr->seq = 0;
    00459     }
    00460
    00461     // Frame Control
    00462     machdr->fctl |= MAC_FCTRL_DATA_T | order;
    00463     // Check the type of VIF
    00464     if (txdesc->host.flags & TXU_CNTRL_TDLS)
    00465         machdr->fctl &= ~MAC_FCTRL_TODS_FROMDS;
    00466     else if (host->flags & TXU_CNTRL_USE_4ADDR)
    00467         machdr->fctl |= MAC_FCTRL_TODS_FROMDS;
    00468     else if (vif->type == VIF_STA)
    00469         machdr->fctl |= MAC_FCTRL_TODS;
    00470     else if (vif->type == VIF_AP)
    00471         machdr->fctl |= MAC_FCTRL_FROMDS;
    00472     #if (RW_MESH_EN)
    00473     else if (vif->type == VIF_MESH_POINT)
    00474     {
    00475         machdr->fctl |= MAC_FCTRL_FROMDS;
    00476     }
    00477     #endif //(RW_MESH_EN)
    00478
    00479     // Check if the more data bit shall be set
    00480     if (host->flags & TXU_CNTRL_MORE_DATA)
    00481         machdr->fctl |= MAC_FCTRL_MOREDATA;
    00482
    00483     /*
    00484      * Addresses
    00485      ************************************************
    00486      * IEEE 802.11 Address Field                    *
    00487      * See IEEE 802.11-2012 Table 8.19              *
    00488      *                                              *
    00489      *  ToDS FromDS Addr1 Addr2 Addr3 Addr4         *
    00490      *    0    0    DA    SA    BSSID n/a           *
    00491      *    0    1    DA    BSSID SA    n/a           *
    00492      *    1    0    BSSID SA    DA    n/a           *
    00493      *    1    1    RA    TA    DA    SA            *
    00494      ************************************************
    00495      */
    00496     MAC_ADDR_CPY(&machdr->addr2, &vif->mac_addr);
    00497     #if (RW_MESH_EN)
    00498     if (vif->type == VIF_MESH_POINT)
    00499     {
    00500         if (host->flags & TXU_CNTRL_USE_4ADDR)
    00501         {
    00502             // Get Mesh Path to be used
    00503             struct mesh_hwmp_path_tag *mpath = &mesh_hwmp_path_pool[umac_desc->path_idx];
    00504
    00505             MAC_ADDR_CPY(&machdr_4a->addr3, &mpath->tgt_mac_addr);
    00506             MAC_ADDR_CPY(&machdr_4a->addr1, &sta->mac_addr);
    00507
    00508             if (host->flags & TXU_CNTRL_MESH_FWD)
    00509             {
    00510                 MAC_ADDR_CPY(&machdr_4a->addr4, &host->eth_src_addr);
    00511             }
    00512             else
    00513             {
    00514                 MAC_ADDR_CPY(&machdr_4a->addr4, &vif->mac_addr);
    00515             }
    00516         }
    00517         else if ((machdr->fctl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_FROMDS)
    00518         {
    00519             MAC_ADDR_CPY(&machdr->addr1, &host->eth_dest_addr);
    00520             MAC_ADDR_CPY(&machdr->addr3, &vif->mac_addr);
    00521         }
    00522     }
    00523     else
    00524     #endif //(RW_MESH_EN)
    00525     {
    00526         if ((machdr->fctl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_TODS)
    00527         {
    00528             MAC_ADDR_CPY(&machdr->addr1, &sta->mac_addr);
    00529             MAC_ADDR_CPY(&machdr->addr3, &host->eth_dest_addr);
    00530         }
    00531         else if ((machdr->fctl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_FROMDS)
    00532         {
    00533             MAC_ADDR_CPY(&machdr->addr1, &host->eth_dest_addr);
    00534             MAC_ADDR_CPY(&machdr->addr3, &host->eth_src_addr);
    00535         }
    00536         else if ((machdr->fctl & MAC_FCTRL_TODS_FROMDS) == 0)
    00537         {
    00538             MAC_ADDR_CPY(&machdr->addr1, &host->eth_dest_addr);
    00539             MAC_ADDR_CPY(&machdr->addr3, &vif->bss_info.bssid);
    00540         }
    00541         else
    00542         {
    00543             MAC_ADDR_CPY(&machdr_4a->addr1, &sta->mac_addr);
    00544             MAC_ADDR_CPY(&machdr_4a->addr3, &host->eth_dest_addr);
    00545             MAC_ADDR_CPY(&machdr_4a->addr4, &host->eth_src_addr);
    00546         }
    00547     }
    00548
    00549     // Check if the frame will be protected
    00550     if (key && !(vif->flags & CONTROL_PORT_NO_ENC &&
    00551                  co_ntohs(host->ethertype) == sta_mgmt_get_port_ethertype(host->staid)))
    00552     {
    00553         machdr->fctl |= MAC_FCTRL_PROTECTEDFRAME;
    00554     }
    00555
    00556     return buf;
    00557 }
    00558
    00578 static uint32_t txu_cntrl_sec_hdr_append(struct txdesc *txdesc, uint32_t buf, bool umac_pol)
    00579 {
    00580     struct hostdesc *host = &txdesc->host;
    00581     struct umacdesc *umac = &txdesc->umac;
    00582     struct sta_info_tag *sta = &sta_info_tab[host->staid];
    00583     struct key_info_tag *key = *sta->sta_sec_info.cur_key;
    00584     struct vif_info_tag *vif = &vif_info_tab[host->vif_idx];
    00585     struct tx_policy_tbl *pol;
    00586     uint32_t mac_control_info1;
    00587     uint16_t *iv;
    00588
    00589     // Check if we have a valid key for this STA
    00590     if (!key || (vif->flags & CONTROL_PORT_NO_ENC &&
    00591                  co_ntohs(host->ethertype) == sta_mgmt_get_port_ethertype(host->staid)))
    00592         return buf;
    00593
    00594     // Check which type of security is used with this STA
    00595     // Check which encryption type has to be used
    00596     switch(key->cipher)
    00597     {
    00598         case MAC_CIPHER_WEP40:
    00599         case MAC_CIPHER_WEP104:
    00600             // Build IV
    00601             buf -= IV_LEN;
    00602             iv = HW2CPU(buf);
    00603             iv[0] = host->pn[0];
    00604             iv[1] = host->pn[1] | (key->key_idx << 14);
    00605             break;
    00606         case MAC_CIPHER_TKIP:
    00607             // Build IV/EIV
    00608             buf -= IV_LEN + EIV_LEN;
    00609             iv = HW2CPU(buf);
    00610             iv[0] = (host->pn[0] >> 8) | ((host->pn[0] | 0x2000) & 0x7F00);
    00611             iv[1] = (host->pn[0] & 0xFF) | (key->key_idx << 14) | EIV_PRESENT;
    00612             iv[2] = host->pn[1];
    00613             iv[3] = host->pn[2];
    00614             break;
    00615         case MAC_CIPHER_CCMP:
    00616         {
    00617             #if (RW_MESH_EN)
    00618             uint32_t offset = 0;
    00619
    00620             if ((vif->type == VIF_MESH_POINT) && umac->has_mesh_ctrl)
    00621             {
    00622                 // Get Mesh VIF Information
    00623                 struct mesh_vif_info_tag *mvif = &mesh_vif_info_tab[vif->mvif_idx];
    00624
    00625                 if (mvif->is_auth)
    00626                 {
    00627                     offset += (MESH_CTRL_MIN_LEN + (umac->nb_ext_addr * MAC_ADDR_LEN));
    00628                 }
    00629             }
    00630             #endif //(RW_MESH_EN)
    00631
    00632             // Build IV/EIV
    00633             buf -= IV_LEN + EIV_LEN;
    00634             #if (RW_MESH_EN)
    00635             iv = HW2CPU(buf - offset);
    00636             #else
    00637             iv = HW2CPU(buf);
    00638             #endif //(RW_MESH_EN)
    00639             iv[0] = host->pn[0];
    00640             iv[1] = EIV_PRESENT | (key->key_idx << 14);
    00641             iv[2] = host->pn[1];
    00642             iv[3] = host->pn[2];
    00643         } break;
    00644         #if RW_WAPI_EN
    00645         case MAC_CIPHER_WPI_SMS4:
    00646             buf -= WPI_IV_LEN;
    00647             iv = HW2CPU(buf);
    00648             iv[0] = key->key_idx;
    00649             iv[1] = host->pn[0];
    00650             iv[2] = host->pn[1];
    00651             iv[3] = host->pn[2];
    00652             iv[4] = host->pn[3];
    00653             iv[5] = 0x5c36;
    00654             iv[6] = 0x5c36;
    00655             iv[7] = 0x5c36;
    00656             iv[8] = 0x5c36;
    00657             break;
    00658         #endif
    00659         default:
    00660             ASSERT_ERR(0);
    00661             break;
    00662     }
    00663
    00664     // Update the policy table with the right key index
    00665     if (umac_pol)
    00666     {
    00667         pol = &umac->buf_control->policy_tbl;
    00668     }
    00669     else
    00670     {
    00671         struct txl_buffer_control *bufctrl = txl_buffer_control_get(txdesc);
    00672         pol = &bufctrl->policy_tbl;
    00673     }
    00674     mac_control_info1 = pol->maccntrlinfo1 & KEYSRAM_INDEX_RA_MASK;
    00675     pol->maccntrlinfo1 = mac_control_info1 | key->hw_key_idx;
    00676
    00677     return (buf);
    00678 }
    00679
    00690 static uint32_t txu_cntrl_llc_hdr_append(struct txdesc *txdesc, uint32_t buf)
    00691 {
    00692     struct hostdesc *host = &txdesc->host;
    00693     struct llc_snap *llc_snap_ptr;
    00694
    00695     // Check if the Ethernet frame is of Type II or SNAP
    00696     if (co_ntohs(host->ethertype) < LLC_FRAMELENGTH_MAXVALUE)
    00697         return buf;
    00698
    00699     // Compute address of LLC snap
    00700     buf -= sizeof_b(struct llc_snap);
    00701     llc_snap_ptr = HW2CPU(buf);
    00702
    00703     /*
    00704      ***********************************************************************
    00705      *              TYPE II: Build up the 802_2 Header (LLC)               *
    00706      ***********************************************************************
    00707      * Received from the adapter (Before the LLC translation):
    00708      *    xxxxxxxxxxx   |    Eth Hdr    | Data
    00709      *   [data_offset]        (14)
    00710      *
    00711      * After the LLC translation:
    00712      *    xxxxxxxxxxxxxxx   | 802.2 Hdr | Data
    00713      *     [data_offset]         (8)
    00714      ***********************************************************************
    00715      */
    00716     // Fill the LLC SNAP header the LLC+OUI to the packet
    00717     llc_snap_ptr->dsap_ssap = (LLC_DSAP | LLC_SSAP << 8);
    00718     llc_snap_ptr->control_oui0 = LLC_CTRL;
    00719     llc_snap_ptr->oui1_2 = 0;
    00720     llc_snap_ptr->proto_id = host->ethertype;
    00721
    00722     return buf;
    00723 }
    00724
    00725 #if NX_AMSDU_TX
    00726
    00736 static uint32_t  txu_cntrl_amsdu_hdr_append(struct txdesc *txdesc, uint32_t buf)
    00737 {
    00738     struct hostdesc *host = &txdesc->host;
    00739     struct umacdesc *umac = &txdesc->umac;
    00740     struct amsdu_hdr *amsdu_hdr;
    00741     uint16_t length;
    00742
    00743     if (!(host->flags & TXU_CNTRL_AMSDU))
    00744         return buf;
    00745
    00746     buf -= sizeof_b(struct amsdu_hdr);
    00747     amsdu_hdr = HW2CPU(buf);
    00748
    00749     MAC_ADDR_CPY(&amsdu_hdr->da, &host->eth_dest_addr);
    00750     MAC_ADDR_CPY(&amsdu_hdr->sa, &host->eth_src_addr);
    00751     length = host->packet_len[0] + umac->hdr_len_802_2;
    00752     amsdu_hdr->len= co_htons(length);
    00753
    00754     return buf;
    00755 }
    00756 #endif
    00757
    00767 static void txu_cntrl_check_rate(struct txdesc *txdesc)
    00768 {
    00769     // Check if rate must be changed
    00770     struct hostdesc *host = &txdesc->host;
    00771
    00772     // Check RC status
    00773     rc_check(txdesc);
    00774
    00775     // Update Buffer control
    00776     txdesc->umac.buf_control = me_update_buffer_control(&sta_info_tab[host->staid]);
    00777
    00778     #if NX_AMPDU_TX
    00779     // Update the PHY flags accordingly
    00780     txdesc->umac.phy_flags = txdesc->umac.buf_control->policy_tbl.ratecntrlinfo[RC_CONTROL_GET(txdesc->umac.rc_control, SW_RETRY_STEP)];
    00781     #endif
    00782 }
    00783
    00794 static void txu_cntrl_discard(struct txdesc *txdesc, uint8_t access_category, uint32_t status)
    00795 {
    00796     // Increment the packet counter to keep it in track with the confirmation
    00797     txl_cntrl_inc_pck_cnt();
    00798
    00799     // Send the confirmation to the host
    00800     GLOBAL_INT_DISABLE();
    00801     txl_cfm_push(txdesc, status, access_category);
    00802     GLOBAL_INT_RESTORE();
    00803 }
    00804
    00805
    00806 #if NX_FULLY_HOSTED
    00807
    00820 static void txu_cntrl_sec_tail_append(struct txdesc *txdesc)
    00821 {
    00822     struct hostdesc *host = &txdesc->host;
    00823     struct umacdesc *umac = &txdesc->umac;
    00824     struct sta_info_tag *sta = &sta_info_tab[host->staid];
    00825     struct key_info_tag *key = *sta->sta_sec_info.cur_key;
    00826     struct mic_calc mic;
    00827     struct tx_hd *thd = &txdesc->lmac.hw_desc->thd;
    00828     struct tx_pbd *pbd;
    00829     struct tx_pbd *pbd_tail;
    00830     uint32_t offset;
    00831     uint32_t data_addr;
    00832     uint32_t data_len;
    00833
    00834     // Check if we have a valid key for this STA
    00835     if (!key)
    00836         return;
    00837
    00838     pbd_tail = &txdesc->lmac.buffer->pbd_tail;
    00839
    00840     // Check which type of security is used with this STA
    00841     if (key->cipher == MAC_CIPHER_TKIP)
    00842     {
    00843         // Initialize MIC computation
    00844         me_mic_init(&mic, key->u.mic.tx_key, &host->eth_dest_addr, &host->eth_src_addr, host->tid);
    00845
    00846         // The MIC computation shall include the 802.2 Header, therefore set it as the
    00847         // default negative offset for the data pointer
    00848         thd = &txdesc->lmac.hw_desc->thd;
    00849         offset = umac->hdr_len_802_2;
    00850
    00851         // Compute the MIC on the TX buffer descriptor(s)
    00852         pbd = HW2CPU(thd->first_pbd_ptr);
    00853         // Go through the chain of payload descriptors
    00854         while (1)
    00855         {
    00856             data_addr = pbd->datastartptr - offset;
    00857             data_len = pbd->dataendptr + 1 - data_addr;
    00858             me_mic_calc(&mic, data_addr, data_len);
    00859             if (pbd->next)
    00860             {
    00861                 pbd = HW2CPU(pbd->next);
    00862             }
    00863             else
    00864             {
    00865                 pbd->next = CPU2HW(pbd_tail);
    00866                 break;
    00867             }
    00868             offset = 0;
    00869         }
    00870
    00871         // End the MIC computation
    00872         me_mic_end(&mic);
    00873
    00874         // Copy the MIC into the buffer
    00875         memcpy(&txdesc->lmac.buffer->sec_tail[0], &mic.mic_key_least, MIC_LEN);
    00876     }
    00877     else
    00878     {
    00879         // Chain the security tail at the end of the payload descriptor list
    00880         pbd = HW2CPU(thd->first_pbd_ptr);
    00881         while (pbd->next)
    00882             pbd = HW2CPU(pbd->next);
    00883         pbd->next = CPU2HW(pbd_tail);
    00884     }
    00885
    00886     // Fill-in the tail buffer descriptor
    00887     pbd_tail->upatterntx = TX_PAYLOAD_DESC_PATTERN;
    00888     pbd_tail->datastartptr = CPU2HW(&txdesc->lmac.buffer->sec_tail[0]);
    00889     pbd_tail->dataendptr = pbd_tail->datastartptr + umac->tail_len - 1;
    00890     pbd_tail->next = 0;
    00891     pbd_tail->bufctrlinfo = 0;
    00892 }
    00893
    00913 static uint32_t txu_cntrl_mgmt_sec_pbd_add(struct txdesc *txdesc, int machdr_len)
    00914 {
    00915     struct tx_hd *thd = &txdesc->lmac.hw_desc->thd;
    00916     struct tx_pbd *pbd = (struct tx_pbd *)HW2CPU(thd->first_pbd_ptr);
    00917     uint32_t payload_start, payload_end, sec_hdr_end;
    00918
    00919     // Sanity check, frame should be made of one single PBD
    00920     ASSERT_ERR(pbd && (pbd->next == 0) &&
    00921                (pbd == &txdesc->lmac.buffer->pbd[0]));
    00922
    00923     payload_start = pbd->datastartptr + machdr_len;
    00924     payload_end = pbd->dataendptr;
    00925
    00926     // Only keep MAC header in first pbd
    00927     pbd->dataendptr = payload_start - 1;
    00928     pbd->next = CPU2HW(&txdesc->lmac.buffer->pbd[1]);
    00929
    00930     // pbd[1] for security header
    00931     pbd = &txdesc->lmac.buffer->pbd[1];
    00932     pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
    00933     pbd->datastartptr = CPU2HW(&txdesc->lmac.buffer->headers[0]);
    00934     pbd->dataendptr = pbd->datastartptr + txdesc->umac.head_len - 1;
    00935     pbd->bufctrlinfo = 0;
    00936     pbd->next = CPU2HW(&txdesc->lmac.buffer->pbd[2]);
    00937
    00938     sec_hdr_end = pbd->dataendptr + 1;
    00939
    00940     // pbd[2] for mgmt frame paylaod (i.e. after MAC header)
    00941     pbd = &txdesc->lmac.buffer->pbd[2];
    00942     pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
    00943     pbd->datastartptr = payload_start;
    00944     pbd->dataendptr = payload_end;
    00945     pbd->bufctrlinfo = 0;
    00946     pbd->next = CPU2HW(&txdesc->lmac.buffer->pbd_tail);
    00947
    00949     pbd = &txdesc->lmac.buffer->pbd_tail;
    00950     pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
    00951     pbd->datastartptr = CPU2HW(&txdesc->lmac.buffer->sec_tail[0]);
    00952     pbd->dataendptr = pbd->datastartptr + txdesc->umac.tail_len - 1;
    00953     pbd->next = 0;
    00954     pbd->bufctrlinfo = 0;
    00955
    00956     return sec_hdr_end;
    00957 }
    00958
    00959 #endif //NX_FULLY_HOSTED
    00960
    00961 /*
    00962  * PUBLIC FUNCTION DEFINITIONS
    00963  ****************************************************************************************
    00964  */
    00965
    00966 void txu_cntrl_frame_build(struct txdesc *txdesc, uint32_t buf)
    00967 {
    00968     #if (RW_MESH_EN)
    00969     if (!(txdesc->host.flags & TXU_CNTRL_MESH_FWD))
    00970     #endif //(RW_MESH_EN)
    00971     {
    00972         // Check if we need to build the LLC/SNAP
    00973         buf = txu_cntrl_llc_hdr_append(txdesc, buf);
    00974     }
    00975
    00976     #if NX_AMSDU_TX
    00977     buf = txu_cntrl_amsdu_hdr_append(txdesc, buf);
    00978     #endif
    00979
    00980     // Build the SEC header and trailers
    00981     buf = txu_cntrl_sec_hdr_append(txdesc, buf, true);
    00982
    00983     // Build the MAC header
    00984     buf = txu_cntrl_mac_hdr_append(txdesc, buf);
    00985
    00986     #if NX_FULLY_HOSTED
    00987     // Append the security tail to the packet
    00988     txu_cntrl_sec_tail_append(txdesc);
    00989
    00990     // Adjust buffer THD - Shall contain the MAC Header
    00991     txdesc->lmac.hw_desc->thd.datastartptr = buf;
    00992     txdesc->lmac.hw_desc->thd.dataendptr = buf + txdesc->umac.machead_len - 1;
    00993     // Adjust buffer TBD, that should point just after the MAC Header
    00994     txl_buffer_get(txdesc)->pbd[0].datastartptr = txdesc->lmac.hw_desc->thd.dataendptr + 1;
    00995     #endif
    00996 }
    00997
    00998 bool txu_cntrl_push(struct txdesc *txdesc, uint8_t access_category)
    00999 {
    01000     // Get the VIF Entry on which packet has to be sent
    01001     struct vif_info_tag *vif;
    01002     bool queue_stop = false;
    01003     uint32_t discard_status = DESC_DONE_TX_BIT;
    01004
    01005     do
    01006     {
    01007         vif = &vif_info_tab[txdesc->host.vif_idx];
    01008
    01009         if (!vif)
    01010         {
    01011             break;
    01012         }
    01013
    01014         // Check if packet can be sent now (current channel could not be the good one)
    01015         if (!txl_cntrl_tx_check(vif))
    01016         {
    01017             // Add the DESC_DONE_SW_TX_BIT in order to force the driver to retransmit the
    01018             // packet
    01019             discard_status |= DESC_DONE_SW_TX_BIT;
    01020             break;
    01021         }
    01022
    01023         // Check if the frame is a management frame
    01024         if ((txdesc->host.flags & TXU_CNTRL_MGMT))
    01025         {
    01026             // Prepare the UMAC part of the TX descriptor
    01027             txu_cntrl_umacdesc_mgmt_prep(txdesc, vif);
    01028         }
    01029         else
    01030         {
    01031             // Perform logical port filtering
    01032             if (!txu_cntrl_logic_port_filter(txdesc->host.staid, co_ntohs(txdesc->host.ethertype),
    01033                                              &txdesc->host.flags))
    01034             {
    01035                 break;
    01036             }
    01037
    01038             // For profiling
    01039             PROF_TX_AC_BG_SET(access_category);
    01040
    01041             #if (RW_MESH_EN)
    01042             // If Mesh Point VIF, check if destination can be reached
    01043             if (vif->type == VIF_MESH_POINT)
    01044             {
    01045                 if (txdesc->host.staid < NX_REMOTE_STA_MAX)
    01046                 {
    01047                     // Check if frame can be sent to the peer mesh STA
    01048                     if (!mesh_ps_tx_data_handle(vif, txdesc->host.staid))
    01049                     {
    01050                         break;
    01051                     }
    01052                 }
    01053
    01054                 if (!mesh_hwmp_path_check(vif, &txdesc->host.eth_dest_addr, &txdesc->umac))
    01055                 {
    01056                     break;
    01057                 }
    01058             }
    01059             #endif //(RW_MESH_EN)
    01060
    01061             // Prepare the UMAC part of the TX descriptor
    01062             txu_cntrl_umacdesc_prep(txdesc);
    01063
    01064             #if (NX_AMPDU_TX)
    01065             // Check if the packet can be aggregated
    01066             bam_check_ba_agg(txdesc);
    01067             #endif
    01068
    01069             // Check RC stats
    01070             txu_cntrl_check_rate(txdesc);
    01071
    01072             #if NX_FULLY_HOSTED
    01073             if (!(txdesc->host.flags & TXU_CNTRL_RETRY))
    01074                 // Build headers
    01075                 txu_cntrl_frame_build(txdesc, txl_buffer_get(txdesc)->pbd[0].datastartptr);
    01076             #endif
    01077
    01078         }
    01079
    01080         // Push the descriptor to LMAC
    01081         queue_stop = txl_cntrl_push(txdesc, access_category);
    01082
    01083         // Handling is done for this frame
    01084         return (queue_stop);
    01085     } while(0);
    01086
    01087     // Packet discarded
    01088     txu_cntrl_discard(txdesc, access_category, discard_status);
    01089
    01090     return false;
    01091 }
    01092
    01093 #if !NX_FULLY_HOSTED
    01094 void txu_cntrl_tkip_mic_append(struct txdesc *txdesc, uint8_t ac)
    01095 {
    01096     struct hostdesc *host = &txdesc->host;
    01097     struct umacdesc *umac = &txdesc->umac;
    01098     struct sta_info_tag *sta = &sta_info_tab[host->staid];
    01099     struct key_info_tag *key = *sta->sta_sec_info.cur_key;
    01100     struct txl_buffer_tag *buffer = txl_buffer_get(txdesc);
    01101     uint32_t buf = CPU2HW(buffer->payload) + umac->head_len - umac->hdr_len_802_2;
    01102
    01103     // Check if we have a valid key for this STA
    01104     if (!key)
    01105         return;
    01106
    01107     // Check which type of security is used with this STA
    01108     // Check which encryption type has to be used
    01109     switch(key->cipher)
    01110     {
    01111         case MAC_CIPHER_TKIP:
    01112             // Compute MIC
    01113             txl_buffer_mic_compute(txdesc, key->u.mic.tx_key, buf,
    01114                                    umac->hdr_len_802_2 + umac->payl_len, ac);
    01115             break;
    01116         default:
    01117             return;
    01118             break;
    01119     }
    01120 }
    01121 #endif
    01122
    01123 void txu_cntrl_cfm(struct txdesc *txdesc)
    01124 {
    01125     int8_t credits = 1;
    01126     struct hostdesc *host = &txdesc->host;
    01127     struct tx_cfm_tag *cfm = txl_cfm_tag_get(txdesc);
    01128     // Indicate if transmission is successful
    01129     bool success = ((cfm->status & FRAME_SUCCESSFUL_TX_BIT) != 0);
    01130     // Indicate if retransmission is required by FW
    01131     bool sw_retry = ((cfm->status & (DESC_DONE_SW_TX_BIT | DESC_DONE_TX_BIT)) ==
    01132                                     (DESC_DONE_SW_TX_BIT | DESC_DONE_TX_BIT));
    01133
    01134     // Reset the status field
    01135     cfm->status = 0;
    01136
    01137     #if !NX_FULLY_HOSTED
    01138     // For debug add sn in all confirmation
    01139     cfm->sn = host->sn;
    01140     #endif
    01141
    01142     // Specific handling for management frames transmitted by the host
    01143     if (host->flags & TXU_CNTRL_MGMT)
    01144     {
    01145         // Check if we need to stop the monitoring or not
    01146         if ((host->flags & TXU_CNTRL_MGMT_PM_MON) && !success)
    01147         {
    01148             // Check if we need to stop the monitoring or not
    01149             rxu_cntrl_get_pm();
    01150         }
    01151
    01152         // Check if we need to send a EOSP QoS NULL frame
    01153         if (host->flags & TXU_CNTRL_EOSP)
    01154         {
    01155             uint16_t qos = MAC_QOSCTRL_EOSP | (0x07 << MAC_QOSCTRL_UP_OFT);
    01156
    01157             // Sanity check - buffered UAPSD frame shall belong to a known STA
    01158             ASSERT_ERR(host->staid != INVALID_STA_IDX);
    01159
    01160             // Send the NULL frame
    01161             TRACE_AP(PS, "{VIF-%d} Send Qos NULL frame as EOSP to STA-%d as last"
    01162                      " frame was MGMT (sn=%d)", host->vif_idx, host->staid, host->sn);
    01163             txl_frame_send_qosnull_frame(host->staid, qos, NULL, NULL);
    01164             sta_info_tab[host->staid].ps_service_period = NO_SERVICE_PERIOD;
    01165         }
    01166     }
    01167     else if (txdesc->host.flags & TXU_CNTRL_EOSP)
    01168     {
    01169         sta_info_tab[host->staid].ps_service_period = NO_SERVICE_PERIOD;
    01170         TRACE_AP(PS, "{VIF-%d} EOSP to STA-%d was data frame sn=%d",
    01171                  host->vif_idx, host->staid, host->sn);
    01172     }
    01173
    01174     if (sw_retry)
    01175     {
    01176         cfm->status |= TX_STATUS_SW_RETRY_REQUIRED;
    01177     }
    01178     #if (NX_AMPDU_TX)
    01179     // Check if packet is a QoS one
    01180     else if (host->tid != 0xFF)
    01181     {
    01182         // Check if there is a BA agreement for this packet
    01183         credits = bam_tx_cfm(txdesc, success);
    01184         if (is_mpdu_agg(txdesc) && !is_mpdu_last(txdesc)) {
    01185             cfm->ampdu_size = 0;
    01186         }
    01187     }
    01188
    01189     if (success)
    01190         cfm->status |= TX_STATUS_ACKNOWLEDGED;
    01191
    01192     if (!is_mpdu_agg(txdesc)) {
    01193         cfm->ampdu_size = 1;
    01194     }
    01195     #else
    01196     cfm->ampdu_size = 1;
    01197     #endif //(NX_AMPDU_TX)
    01198
    01199     // Update the confirmation descriptor
    01200     cfm->status |= TX_STATUS_DONE;
    01201     cfm->credits = credits;
    01202     #if NX_AMSDU_TX
    01203     cfm->amsdu_size = me_tx_cfm_amsdu(txdesc);
    01204     #endif
    01205 }
    01206
    01207 void txu_cntrl_protect_mgmt_frame(struct txdesc *txdesc, struct mac_hdr *mac_hdr,
    01208                                   uint16_t hdr_len)
    01209 {
    01210     uint32_t sec_end;
    01211
    01212     if (txdesc->umac.head_len == 0)
    01213     {
    01214         int tail_len, head_len;
    01215         head_len = txu_cntrl_sechdr_len_compute(txdesc, &tail_len);
    01216         txdesc->umac.head_len = head_len;
    01217         txdesc->umac.tail_len = tail_len;
    01218
    01219         sec_end = CPU2HW(mac_hdr) + hdr_len + head_len;
    01220     }
    01221     else
    01222     {
    01223         #if NX_FULLY_HOSTED
    01224         sec_end = txu_cntrl_mgmt_sec_pbd_add(txdesc, hdr_len);
    01225         #else
    01226         sec_end = CPU2HW(mac_hdr) + hdr_len + txdesc->umac.head_len;
    01227         #endif
    01228     }
    01229
    01230     mac_hdr->fctl |= MAC_FCTRL_PROTECTEDFRAME;
    01231     txu_cntrl_sec_hdr_append(txdesc, sec_end, false);
    01232 }
    01233
    01234 #if NX_FULLY_HOSTED
    01235 uint32_t txu_cntrl_mgmt_mic_pbd_append(struct txdesc *txdesc)
    01236 {
    01237     struct tx_pbd *pbd_mmic = &txdesc->lmac.buffer->pbd_tail;
    01238     pbd_mmic = &txdesc->lmac.buffer->pbd_tail;
    01239     pbd_mmic->upatterntx = TX_PAYLOAD_DESC_PATTERN;
    01240     pbd_mmic->datastartptr = CPU2HW(&txdesc->lmac.buffer->headers[0]);
    01241     pbd_mmic->dataendptr = pbd_mmic->datastartptr + MAC_MGMT_MIC_LEN;
    01242     pbd_mmic->next = 0;
    01243     pbd_mmic->bufctrlinfo = 0;
    01244
    01245     // Sanity check, there should be only one PBD
    01246     ASSERT_ERR(txdesc->lmac.buffer->pbd[0].next == 0);
    01247     txdesc->lmac.buffer->pbd[0].next = CPU2HW(pbd_mmic);
    01248
    01249     return pbd_mmic->datastartptr;
    01250 }
    01251 #endif