Declaration of all structures and functions used by the BAM module. More...
|
Data Structures | |
| struct | bam_addba_req |
| ADDBA Request frame Action field format (see IEEE 802.11-2012, section 8.5.5.2). More... | |
| struct | bam_addba_rsp |
| ADDBA Response frame Action field format (see IEEE 802.11-2012, section 8.5.5.3). More... | |
| struct | bam_delba |
| DELBA frame Action field format (see IEEE 802.11-2012, section 8.5.5.4). More... | |
| struct | bam_baw |
| Per RA/TID Data for AMPDU TX. More... | |
| struct | bam_env_tag |
| Declaration of BAM environment. More... | |
Modules | |
| TASK_BAM | |
UMAC ME BAM module state machine. | |
Defines | |
| #define | BAM_IDX_MAX (NX_MAX_BA_TX + NX_REORD) |
| Maximum index of the task instance. | |
| #define | BAM_FIRST_RX_IDX 0 |
| First BAM index for RX BA agreements. | |
| #define | BAM_NB_RX_IDX NX_REORD |
| Number of available RX BA agreements. | |
| #define | BAM_FIRST_TX_IDX BAM_NB_RX_IDX |
| First BAM index for TX BA agreements. | |
| #define | BAM_NB_TX_IDX NX_MAX_BA_TX |
| Number of available TX BA agreements. | |
| #define | BAM_INVALID_TASK_IDX (BAM_IDX_MAX + 1) |
| Invalid index of the task instances - 1 instance for manager. | |
| #define | BAM_BA_AGG_TX_CNT_THRES 2 |
| TX packet count for a STA/TID above which we establish a BlockAck agreement. | |
| #define | BAM_RESPONSE_TO_DURATION 500 |
| Maximal time before considering that BA_ADD_REQ won't receive any response. | |
| #define | BAM_INACTIVITY_TO_DURATION 2000 |
| Maximal time between two consequent packet before considering a BA AGG can be deleted (in number of TU). | |
| #define | BAM_ADDBA_REQ_INTERVAL 1000000 |
| Minimal time between sending two consequent ADDBA Req if error detected on the first one (in us) - 1s. | |
| #define | BAM_MAX_TX_WIN_SIZE 64 |
| Maximum size of the transmit window. | |
| #define | BAM_DELBA_MAX_TRY 3 |
| Maximum number of tentatives to send DELBA. | |
| #define | BAM_BA_PARAM_GET(ba_param, field) |
| Get field from Block Ack Parameter field. | |
| #define | BAM_DELBA_PARAM_GET(delba_param, field) |
| Get field from DELBA Parameter field. | |
Typedefs | |
| typedef unsigned int(* | bam_baw_index_func_ptr )(struct bam_baw *, unsigned int) |
| Pointer to BaW index computation function. | |
Enumerations | |
| enum | bam_ba_type { BA_RESPONDER = 0, BA_ORIGINATOR, BA_DEV_NONE } |
Block Ack device type. More... | |
| enum | bam_ba_policy { BAM_BA_POL_IMMEDIATE = 1, BAM_BA_POL_DELAYED } |
Block Ack Policy Values. More... | |
| enum | bam_pkt_policy { BAM_PKT_POL_SINGLETON = 0, BAM_PKT_POL_AMPDU } |
Packet policy values. | |
| enum | bam_baw_state { BAW_FREE, BAW_PENDING, BAW_CONFIRMED } |
Enum listing the possible states of a BAW element. More... | |
Functions | |
| static uint16_t | bam_time_get (void) |
| Read and returns the current BAM time (used for lifetime expiry computation). | |
| static bool | bam_time_cmp (uint16_t time1, uint16_t time2) |
| Compare BAM timer absolute expiration time. | |
| static bool | bam_time_past (uint32_t time) |
| Check if a BAM time is in the past or not. | |
| static unsigned int | bam_baw_index_compute (struct bam_baw *baw, unsigned int offset) |
| Compute the index of a BaW element from its offset. | |
| static unsigned int | bam_baw_index_compute_opt (struct bam_baw *baw, unsigned int offset) |
| Compute the index of a BaW element from its offset. | |
| static int8_t | bam_move_baw (struct bam_baw *baw) |
| Move the BaW to the next unconfirmed packet. | |
| static void | bam_set_baw_state (struct bam_baw *baw, uint16_t sn, uint8_t state) |
| Set the state of a sequence number in the given BaW. | |
| static int8_t | bam_check_tx_baw (struct txdesc *txdesc, uint8_t bam_idx, bool success) |
| Check and update the state of the BaW after transmission of a frame This function verifies if the frame should be retried or not. | |
| static uint8_t | bam_create_ba_agg (uint8_t sta_idx, uint8_t tid, uint16_t ssn) |
| Initiate the creation of a TX BlockAck agreement. | |
| void | bam_init (void) |
| Initialize the BAM context. | |
| void | bam_param_sta_info_tab_reset (uint16_t bam_idx) |
| Reset the BA parameters in the station info table. | |
| uint16_t | bam_alloc_new_task (bool tx) |
| Allocate the BAM task. | |
| void | bam_delete_ba_agg (uint8_t bam_idx) |
| Delete a provided BlockAck agreement. | |
| void | bam_delete_all_ba_agg (uint8_t sta_idx) |
| Delete all Block Ack agreements linked to the specified staid. | |
| void | bam_start_inactivity_timer (uint16_t bam_task_idx) |
| start the BAM_INACTIVITY_TIMEOUT_IND timer | |
| void | bam_send_mm_ba_add_req (uint16_t sta_idx, uint16_t bam_idx) |
| Send MM_BAADD_REQ to LMAC. | |
| void | bam_send_mm_ba_del_req (uint16_t sta_idx, uint16_t bam_idx) |
| Send Send MM_BADEL_REQ to LMAC. | |
| void | bam_send_air_action_frame (uint8_t sta_idx, struct bam_env_tag *bam_env, uint8_t action, uint8_t dialog_token, uint16_t param, uint16_t status_code, void(*cfm_func)(void *, uint32_t)) |
| Send BA action frame to peer. | |
| void | bam_check_ba_agg (struct txdesc *txdesc) |
| Check if a BlockAck agreement is currently active for the RA/TID for which the packet is sent. | |
| int8_t | bam_tx_cfm (struct txdesc *txdesc, bool success) |
| Handles status of a transmission under BA. | |
| void | bam_baw_init (struct bam_env_tag *bam_env) |
| Initialize the transmission window structure. | |
| int8_t | bam_flush_baw (struct bam_baw *baw) |
| Flush the transmission window. | |
| void | bam_rx_active (uint8_t sta_idx, uint8_t tid) |
| Reset the last activity time of a BlockAck agreement. | |
| void | bam_send_del_ba_agg (uint8_t sta_idx, uint8_t tid) |
| Send DELBA action frame to delete a BA agreement active only on the peer. | |
| __INLINE uint16_t | bam_build_baparamset (struct bam_env_tag *bam_env) |
| Used to build the BA parameter field. | |
Variables | |
| static struct bam_baw | bam_baws [5] |
| BaW array. | |
| struct bam_env_tag | bam_env [BAM_IDX_MAX] |
| BAM module environment definition. | |
| struct bam_env_tag | bam_env [BAM_IDX_MAX] |
| BAM module environment declaration. | |
ADDBA Request Offsets - From Action Category | |
|
| |
| #define | BAM_ADDBAREQ_BA_PARAM_OFFSET (3) |
| ADDBA Request Offset. | |
| #define | BAM_ADDBAREQ_BA_TIMEOUT_OFFSET (5) |
| ADDBA Request Offset. | |
| #define | BAM_ADDBAREQ_BA_SSC_OFFSET (7) |
| ADDBA Request Offset. | |
ADDBA Response Offsets - From Action Category | |
|
| |
| #define | BAM_ADDBARSP_STATUS_OFFSET (3) |
| ADDBA Response Offset. | |
| #define | BAM_ADDBARSP_BA_PARAM_OFFSET (5) |
| ADDBA Response Offset. | |
| #define | BAM_ADDBARSP_BA_TIMEOUT_OFFSET (7) |
| ADDBA Response Offset. | |
DELBA Offsets - From Action Category | |
|
| |
| #define | BAM_DELBA_PARAM_OFFSET (2) |
| DELBA Offset. | |
| #define | BAM_DELBA_REASON_OFFSET (4) |
| DELBA Offset. | |
Action Frames Lengths | |
|
| |
| #define | BAM_ADDBAREQ_LENGTH (9) |
| BlockAck action frame length. | |
| #define | BAM_ADDBARSP_LENGTH (9) |
| BlockAck action frame length. | |
| #define | BAM_DELBA_LENGTH (6) |
| BlockAck action frame length. | |
Block Ack Parameter Set Offsets and Masks | |
|
| |
| #define | BAM_BA_PARAM_AMSDU_SUP_OFFSET (0) |
| BlockAck parameter set definition. | |
| #define | BAM_BA_PARAM_AMSDU_SUP_MASK (0x0001) |
| BlockAck parameter set definition. | |
| #define | BAM_BA_PARAM_BA_POL_OFFSET (1) |
| BlockAck parameter set definition. | |
| #define | BAM_BA_PARAM_BA_POL_MASK (0x0002) |
| BlockAck parameter set definition. | |
| #define | BAM_BA_PARAM_TID_OFFSET (2) |
| BlockAck parameter set definition. | |
| #define | BAM_BA_PARAM_TID_MASK (0x003C) |
| BlockAck parameter set definition. | |
| #define | BAM_BA_PARAM_BUFF_SIZE_OFFSET (6) |
| BlockAck parameter set definition. | |
| #define | BAM_BA_PARAM_BUFF_SIZE_MASK (0xFFC0) |
| BlockAck parameter set definition. | |
DELBA Parameters Offsets and Masks | |
|
| |
| #define | BAM_DELBA_PARAM_INITIATOR_OFFSET (11) |
| DELBA parameter definition. | |
| #define | BAM_DELBA_PARAM_INITIATOR_MASK (0x0800) |
| DELBA parameter definition. | |
| #define | BAM_DELBA_PARAM_TID_OFFSET (12) |
| DELBA parameter definition. | |
| #define | BAM_DELBA_PARAM_TID_MASK (0xF000) |
| DELBA parameter definition. | |
BA/BAR Control Offsets and Masks | |
|
| |
| #define | BAM_BA_CTRL_POLICY_OFFSET (0) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_POLICY_MASK (0x0001) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_MULTI_TID_OFFSET (1) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_MULTI_TID_MASK (0x0002) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_COMP_BITMAP_OFFSET (2) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_COMP_BITMAP_OFFSET (2) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_COMP_BITMAP_MASK (0x0004) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_COMP_BITMAP_MASK (0x0004) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_TID_INFO_OFFSET (11) |
| BA/BAR control definition. | |
| #define | BAM_BA_CTRL_TID_INFO_MASK (0xF000) |
| BA/BAR control definition. | |
Basic SSC Offsets and Masks | |
|
| |
| #define | BAM_BASIC_SSC_FN_OFFSET (0) |
| Basic SSC definition. | |
| #define | BAM_BASIC_SSC_FN_MASK (0x000F) |
| Basic SSC definition. | |
| #define | BAM_BASIC_SSC_SSN_OFFSET (4) |
| Basic SSC definition. | |
| #define | BAM_BASIC_SSC_SSN_MASK (0xFFF0) |
| Basic SSC definition. | |
Declaration of all structures and functions used by the BAM module.
| #define BAM_BA_PARAM_GET | ( | ba_param, | |||
| field | ) |
((ba_param & BAM_BA_PARAM_ ## field ## _MASK) \
>> BAM_BA_PARAM_ ## field ## _OFFSET)
Get field from Block Ack Parameter field.
Definition at line 189 of file bam.h.
Referenced by rxu_mgt_ind_handler().
| #define BAM_DELBA_PARAM_GET | ( | delba_param, | |||
| field | ) |
((delba_param & BAM_DELBA_PARAM_ ## field ## _MASK) \
>> BAM_DELBA_PARAM_ ## field ## _OFFSET)
Get field from DELBA Parameter field.
Definition at line 194 of file bam.h.
Referenced by rxu_mgt_ind_handler().
| enum bam_ba_policy |
| enum bam_ba_type |
| enum bam_baw_state |
| uint16_t bam_alloc_new_task | ( | bool | tx | ) |
Allocate the BAM task.
| [in] | tx | Flag indicating whether the allocation shall be for a TX (true) or RX (false) BA agreement |
Referenced by bam_create_ba_agg(), and rxu_mgt_ind_handler().
| static unsigned int bam_baw_index_compute | ( | struct bam_baw * | baw, | |
| unsigned int | offset | |||
| ) | [static] |
Compute the index of a BaW element from its offset.
This function uses a modulo to do the computation.
| [in] | baw | Pointer to the BaW structure. |
| [in] | offset | Offset of the element in the BaW structure. |
Definition at line 120 of file bam.c.
References bam_baw::buf_size, and bam_baw::fsn_idx.
| static unsigned int bam_baw_index_compute_opt | ( | struct bam_baw * | baw, | |
| unsigned int | offset | |||
| ) | [static] |
Compute the index of a BaW element from its offset.
This function uses a mask. It is used only when the BaW size is a power of 2.
| [in] | baw | Pointer to the BaW structure. |
| [in] | offset | Offset of the element in the BaW structure. |
Definition at line 136 of file bam.c.
References bam_baw::fsn_idx, and bam_baw::mask.
| void bam_baw_init | ( | struct bam_env_tag * | bam_env | ) |
Initialize the transmission window structure.
This function is called upon the creation of a TX block ack agreement.
| [in] | bam_env | Pointer to the BAM structure allocated for the new agreement |
Referenced by mm_ba_add_cfm_handler().
| __INLINE uint16_t bam_build_baparamset | ( | struct bam_env_tag * | bam_env | ) |
Used to build the BA parameter field.
| [in] | bam_env | Pointer to the BAM environment variable |
Definition at line 356 of file bam.h.
References bam_env_tag::ba_policy, bam_env_tag::buffer_size, MAC_BA_PARAMSET_AMSDU_MASK, MAC_BA_PARAMSET_BUFFER_OFT, MAC_BA_PARAMSET_POLICY_OFT, MAC_BA_PARAMSET_TID_OFT, and bam_env_tag::tid.
Referenced by mm_ba_add_cfm_handler().
| void bam_check_ba_agg | ( | struct txdesc * | txdesc | ) |
Check if a BlockAck agreement is currently active for the RA/TID for which the packet is sent.
This function is called each time a new packet is pushed to the TX path. If a BlockAck agreement is active, then the TX descriptor is updated accordingly to allow the LMAC to aggregate the packet in a A-MPDU. If no agreement is in place, the function initiates the creation of such an agreement for the future transmissions.
| [in] | txdesc | TX descriptor describing the packet to transmit |
| static int8_t bam_check_tx_baw | ( | struct txdesc * | txdesc, | |
| uint8_t | bam_idx, | |||
| bool | success | |||
| ) | [static] |
Check and update the state of the BaW after transmission of a frame This function verifies if the frame should be retried or not.
It then updates the state of the BaW to BAW_CONFIRMED if the frame is successful or not to be retried, and finally move the BaW.
| [in] | txdesc | Pointer to the TX descriptor attached to the frame. |
| [in] | bam_idx | Index of the BAM task |
| [in] | success | true if frame was successfully transmitted, false otherwise |
Definition at line 204 of file bam.c.
References AMPDU_BIT, bam_env, bam_move_baw(), bam_set_baw_state(), bam_time_past(), bam_env_tag::baw, BAW_CONFIRMED, umacdesc::flags, txdesc::host, is_mpdu_split(), NX_AMSDU_TX, hostdesc::pn, tx_cfm_tag::pn, hostdesc::sn, tx_cfm_tag::sn, tx_cfm_tag::status, tx_cfm_tag::timestamp, hostdesc::timestamp, TX_STATUS_RETRY_REQUIRED, txl_cfm_tag_get(), and txdesc::umac.
| static uint8_t bam_create_ba_agg | ( | uint8_t | sta_idx, | |
| uint8_t | tid, | |||
| uint16_t | ssn | |||
| ) | [static] |
Initiate the creation of a TX BlockAck agreement.
| [in] | sta_idx | Station for which the BlockAck agreement is created |
| [in] | tid | TID of the BA agreement |
| [in] | ssn | Sequence number of the first packet sent after the BA agreement establishment |
Definition at line 258 of file bam.c.
References sta_info_tag::ba_info, BA_ORIGINATOR, bam_env_tag::ba_policy, bam_env_tag::ba_timeout, BAM_ADD_BA_RSP_TIMEOUT_IND, bam_alloc_new_task(), bam_env, sta_mgmt_ba_info::bam_idx_tx, BAM_INACTIVITY_TO_DURATION, BAM_INVALID_TASK_IDX, BAM_RESPONSE_TO_DURATION, bam_send_air_action_frame(), BAM_WAIT_RSP, bam_env_tag::buffer_size, CO_FULL, CO_OK, co_rand_byte(), bam_env_tag::dev_type, bam_env_tag::dialog_token, KE_BUILD_ID, ke_state_set(), ke_time(), ke_timer_set(), MAC_BA_ACTION_ADDBA_REQ, MAC_BA_ACTION_DELBA, MAC_RS_TIMEOUT, mac_tid2ac, nx_txdesc_cnt, bam_env_tag::pkt_cnt, bam_env_tag::ssn, bam_env_tag::sta_idx, sta_info_tab, sta_mgmt_set_add_ba_time(), TASK_BAM, bam_env_tag::tid, TRACE_LMAC, and TU_DURATION.
| void bam_delete_all_ba_agg | ( | uint8_t | sta_idx | ) |
Delete all Block Ack agreements linked to the specified staid.
| [in] | sta_idx | The STA index the BA agreements of which have to be deleted |
Referenced by me_sta_del_req_handler(), and sm_delete_resources().
| void bam_delete_ba_agg | ( | uint8_t | bam_idx | ) |
Delete a provided BlockAck agreement.
| [in] | bam_idx | The BAM task index to be delete |
Referenced by mm_ba_del_cfm_handler(), and rxu_mgt_ind_handler().
| int8_t bam_flush_baw | ( | struct bam_baw * | baw | ) |
Flush the transmission window.
This function then returns the number of credits that should be added/removed for the associated RA/TID queue.
| [in] | baw | Pointer to the transmission window to be flushed |
Referenced by mm_ba_del_cfm_handler().
| static int8_t bam_move_baw | ( | struct bam_baw * | baw | ) | [static] |
Move the BaW to the next unconfirmed packet.
This function goes through the BaW and checks the status of the elements. For each confirmed element the number of credits (i.e the number of positions becoming free in the BaW) that can be allocated to the associated TX queue is increased.
| [in] | baw | Pointer to the BaW structure. |
Definition at line 153 of file bam.c.
References BAW_CONFIRMED, BAW_FREE, bam_baw::fsn, bam_baw::fsn_idx, bam_baw::idx_compute, and bam_baw::states.
Referenced by bam_check_tx_baw().
| void bam_param_sta_info_tab_reset | ( | uint16_t | bam_idx | ) |
Reset the BA parameters in the station info table.
| [in] | bam_idx | Indicates BAM task index |
Referenced by bam_add_ba_rsp_timeout_ind_handler(), mm_ba_add_cfm_handler(), and rxu_mgt_ind_handler().
| void bam_rx_active | ( | uint8_t | sta_idx, | |
| uint8_t | tid | |||
| ) |
Reset the last activity time of a BlockAck agreement.
This function is called upon any frame reception having this sta_idx, tid pair. It is used as part of the BA agreement aging mechanism.
| [in] | sta_idx | Index of the STA we just received a packet from |
| [in] | tid | TID of the received packet |
Referenced by rxu_cntrl_reord_check().
| void bam_send_air_action_frame | ( | uint8_t | sta_idx, | |
| struct bam_env_tag * | bam_env, | |||
| uint8_t | action, | |||
| uint8_t | dialog_token, | |||
| uint16_t | param, | |||
| uint16_t | status_code, | |||
| void(*)(void *, uint32_t) | cfm_func | |||
| ) |
Send BA action frame to peer.
| [in] | sta_idx | indicates station index |
| [in] | bam_env | Pointer to the BAM environment, may be NULL in case of ADDBA RSP transmission |
| [in] | action | Action to perform |
| [in] | dialog_token | Dialog token to be used |
| [in] | param | Param to be put (used only for ADDBA RSP) |
| [in] | status_code | Status of the response/Reason for deletion (used for ADDBA RSP /DELBA only) |
| [in] | cfm_func | Function to call when transmission is done. (may be NULL) |
Referenced by bam_create_ba_agg(), bam_delba_status(), bam_inactivity_timeout_ind_handler(), mm_ba_add_cfm_handler(), and rxu_mgt_ind_handler().
| void bam_send_del_ba_agg | ( | uint8_t | sta_idx, | |
| uint8_t | tid | |||
| ) |
Send DELBA action frame to delete a BA agreement active only on the peer.
This function is called upon the reception of a MPDU part of a A-MPDU, in case no BA agreement is active for the STA/TID pair.
| [in] | sta_idx | Index of the STA we just received a packet from |
| [in] | tid | TID of the received packet |
| void bam_send_mm_ba_add_req | ( | uint16_t | sta_idx, | |
| uint16_t | bam_idx | |||
| ) |
Send MM_BAADD_REQ to LMAC.
| [in] | sta_idx | indicates station index |
| [in] | bam_idx | indicates BAM task index |
Referenced by rxu_mgt_ind_handler().
| void bam_send_mm_ba_del_req | ( | uint16_t | sta_idx, | |
| uint16_t | bam_idx | |||
| ) |
Send Send MM_BADEL_REQ to LMAC.
| [in] | sta_idx | indicates station index |
| [in] | bam_idx | indicates BAM task index |
Referenced by bam_delba_status(), and rxu_mgt_ind_handler().
| static void bam_set_baw_state | ( | struct bam_baw * | baw, | |
| uint16_t | sn, | |||
| uint8_t | state | |||
| ) | [static] |
Set the state of a sequence number in the given BaW.
| [in] | baw | Pointer to the BaW structure. |
| [in] | sn | Sequence Number to be modified |
| [in] | state | New state |
Definition at line 176 of file bam.c.
References ASSERT_ERR, bam_baw::fsn, bam_baw::idx_compute, and bam_baw::states.
Referenced by bam_check_tx_baw().
| void bam_start_inactivity_timer | ( | uint16_t | bam_task_idx | ) |
start the BAM_INACTIVITY_TIMEOUT_IND timer
| [in] | bam_task_idx | indicates BAM task index |
Referenced by bam_inactivity_timeout_ind_handler(), and mm_ba_add_cfm_handler().
| static bool bam_time_cmp | ( | uint16_t | time1, | |
| uint16_t | time2 | |||
| ) | [static] |
Compare BAM timer absolute expiration time.
| [in] | time1 | First time to compare. |
| [in] | time2 | Second time to compare. |
Definition at line 82 of file bam.c.
Referenced by bam_time_past().
| static uint16_t bam_time_get | ( | void | ) | [static] |
Read and returns the current BAM time (used for lifetime expiry computation).
Definition at line 66 of file bam.c.
References hal_machw_time().
Referenced by bam_time_past().
| static bool bam_time_past | ( | uint32_t | time | ) | [static] |
Check if a BAM time is in the past or not.
| [in] | time | Time to compare. |
Definition at line 103 of file bam.c.
References bam_time_cmp(), and bam_time_get().
Referenced by bam_check_tx_baw().
| int8_t bam_tx_cfm | ( | struct txdesc * | txdesc, | |
| bool | success | |||
| ) |
Handles status of a transmission under BA.
Move the transmission window accordingly and returns the number of credits allocated to the host for the next transmissions.
| [in] | txdesc | Pointer to the packet descriptor |
| [in] | success | Flag indicating if the transmission was successful (true) or not (false) |
| struct bam_env_tag bam_env[BAM_IDX_MAX] |
BAM module environment definition.
BAM module environment declaration.
Definition at line 46 of file bam.c.
Referenced by bam_check_tx_baw(), bam_create_ba_agg(), bam_delba_status(), bam_inactivity_timeout_ind_handler(), me_tx_cfm_amsdu(), mm_ba_add_cfm_handler(), mm_ba_del_cfm_handler(), rxu_mgt_ind_handler(), and sta_mgmt_set_tx_ssn().
1.6.1