qcacmn: Add APIs to defragment elem/subelem fragment sequence

Add APIs to defragment a sequence of 802.11 element/subelement
fragments. Add an inline mode to carry out the defragmentation within
the source buffer in order to reduce buffer requirements and to
eliminate memory copies/moves for the lead element/sublement.
Conversely, add a non-inline mode to copy the defragmented payload to
a separate buffer.

Add common helper functionality shared between these APIs.

CRs-Fixed: 3124132
Change-Id: Ia68584e918ddcf626b748f2b0c3a5da6492b40b6
This commit is contained in:
Krishna Rao
2022-01-27 23:33:57 +05:30
committed by Gerrit - the friendly Code Review server
parent 94df448341
commit 3f38db23d4
2 changed files with 377 additions and 0 deletions

View File

@@ -414,6 +414,78 @@ QDF_STATUS wlan_get_elem_fragseq_info(uint8_t *elembuff,
qdf_size_t *fragseq_totallen,
qdf_size_t *fragseq_payloadlen);
/**
* wlan_defrag_elem_fragseq() - Defragment sequence of element fragments
*
* @inline_defrag: Whether to use inline defragmentation, wherein the
* defragmentation is carried out inline within the source buffer and no
* memmoves/memcopy would be required for the lead element.
* @fragbuff: Source buffer containing the element fragment sequence starting
* with the Element ID of the lead element. The buffer should not contain any
* material other than elements. If inline defragmentation is enabled, the
* corresponding defragmented payload will be generated inline into this buffer
* and the defragmented payload will start after the location of the lead
* element's element ID, element length, and (if the lead element's element ID
* is WLAN_ELEMID_EXTN_ELEM), the element ID extension. This defragmented
* payload will not contain the headers of any of the other fragments in the
* fragment sequence.
* @fragbuff_maxsize: Maximum size of fragbuff. This should be greater than or
* equal to the total size of the element fragment sequence, inclusive of the
* header and payload of the leading element and the headers and payloads of all
* subsequent fragments applicable to that element.
* @defragbuff: The destination buffer into which the defragmented payload
* should be copied. This is inapplicable and ignored if inline_defrag is true.
* The defragmented payload will be copied to the start of the destination
* buffer without including the headers of the lead element and the subsequent
* fragment elements, and (if the lead element's element ID is
* WLAN_ELEMID_EXTN_ELEM), without including the element ID extension.
* @defragbuff_maxsize: Maximum size of defragbuff. This is inapplicable and
* ignored if inline_defrag is true. The size should be large enough to contain
* the entire defragmented payload, otherwise an error will be returned.
* @defragpayload_len: Pointer to the location where the length of the
* defragmented payload should be updated. Irrespective of whether inline_defrag
* is true or false, this will not include the sizes of the headers of the lead
* element and subsequent fragments, and (if the lead element's element ID is
* WLAN_ELEMID_EXTN_ELEM), it will not include the size of the lead element's
* element ID extension. Please note standards related limitation given in
* function description below.
*
* Defragment a sequence of element fragments. If the source buffer does not
* contain an element fragment sequence (in the beginning), an error is
* returned. An inline mode is available to carry out the defragmentation within
* the source buffer in order to reduce buffer requirements and to eliminate
* memory copies/moves for the lead element. In the inline mode, the buffer
* content (if any) after the fragments is moved as well. The contents of the
* defragmented payload are intended for end consumption by control path
* protocol processing code within the driver in a manner uniform with other
* protocol data in byte buffers, and not for onward forwarding to other
* subsystems or for intrusive specialized processing different from other
* protocol data. Hence zero copy methods such as network buffer fragment
* processing, etc. are not used in this use case. Additionally, this API is
* intended for use cases where the nature of the payload is complex and it is
* infeasible for the caller to skip the (un-defragmented) fragment boundaries
* on its own in a scalable and maintainable manner. Separately, please note a
* limitation arising from the standard wherein if the caller passes a truncated
* maximum buffer size such that the buffer ends prematurely just at the end of
* a fragment element with length 255, the function will have to conclude that
* the last successfully parsed fragment element is the final one in the
* fragment sequence, and return results accordingly. If another fragment
* actually exists beyond the given buffer, this function cannot detect the
* condition since there is no provision in the standard to indicate a total
* fragment sequence size in one place in the beginning or anywhere else. Hence
* the caller should take care to provide the complete buffer with the max size
* set accordingly.
*
* Return: QDF_STATUS_SUCCESS in the case of success, QDF_STATUS value giving
* the reason for error in the case of failure
*/
QDF_STATUS wlan_defrag_elem_fragseq(bool inline_defrag,
uint8_t *fragbuff,
qdf_size_t fragbuff_maxsize,
uint8_t *defragbuff,
qdf_size_t defragbuff_maxsize,
qdf_size_t *defragpayload_len);
/**
* wlan_get_subelem_fragseq_info() - Get information about subelement fragment
* sequence
@@ -481,6 +553,78 @@ QDF_STATUS wlan_get_subelem_fragseq_info(uint8_t subelemfragid,
qdf_size_t *fragseq_totallen,
qdf_size_t *fragseq_payloadlen);
/**
* wlan_defrag_subelem_fragseq() - Defragment sequence of subelement fragments
*
* @inline_defrag: Whether to use inline defragmentation, wherein the
* defragmentation is carried out inline within the source buffer and no
* memmoves/memcopy would be required for the lead subelement.
* @subelemid: Fragment ID applicable for the subelement (this can potentially
* vary across protocol areas)
* @fragbuff: Source buffer containing the subelement fragment sequence starting
* with the subelement ID of the lead subelement. The containing element is
* required to have already been defragmented (if applicable). If inline
* defragmentation is enabled, the corresponding defragmented payload will be
* generated inline into this buffer and the defragmented payload will start
* after the location of the lead subelement's subelement ID and subelement
* length. This defragmented payload will not contain the headers of any of the
* other fragments in the fragment sequence.
* @fragbuff_maxsize: Maximum size of fragbuff. This should be greater than or
* equal to the total size of the subelement fragment sequence, inclusive of the
* header and payload of the leading subelement and the headers and payloads of
* all subsequent fragments applicable to that subelement.
* @defragbuff: The destination buffer into which the defragmented payload
* should be copied. This is inapplicable and ignored if inline_defrag is true.
* The defragmented payload will be copied to the start of the destination
* buffer without including the headers of the lead subelement and the
* subsequent fragment subelements.
* @defragbuff_maxsize: Maximum size of defragbuff. This is inapplicable and
* ignored if inline_defrag is true. The size should be large enough to contain
* the entire defragmented payload, otherwise an error will be returned.
* @defragpayload_len: Pointer to the location where the length of the
* defragmented payload should be updated. Irrespective of whether inline_defrag
* is true or false, this will not include the sizes of the headers of the lead
* subelement and subsequent fragments. Please note standards related limitation
* given in function description below.
*
* Defragment a sequence of subelement fragments. If the source buffer does not
* contain a subelement fragment sequence (in the beginning), the function
* returns an error. The containing element is required to have already been
* defragmented. An inline mode is available to carry out the defragmentation
* within the source buffer in order to reduce buffer requirements and to
* eliminate memory copies/moves for the lead subelement. In the inline mode,
* the buffer content (if any) after the fragments is moved as well. The
* contents of the defragmented payload are intended for end consumption by
* control path protocol processing code within the driver in a manner uniform
* with other protocol data in byte buffers, and not for onward forwarding to
* other subsystems or for intrusive specialized processing different from other
* protocol data. Hence zero copy methods such as network buffer fragment
* processing, etc. are not used in this use case. Additionally, this API is
* intended for use cases where the nature of the payload is complex and it is
* infeasible for the caller to skip the (un-defragmented) fragment boundaries
* on its own in a scalable and maintainable manner. Separately, please note a
* limitation arising from the standard wherein if the caller passes a truncated
* maximum buffer size such that the buffer ends prematurely just at the end of
* a fragment subelement with length 255, the function will have to conclude
* that the last successfully parsed fragment subelement is the final one in the
* fragment sequence, and return results accordingly. If another fragment
* actually exists beyond the given buffer, this function cannot detect the
* condition since there is no provision in the standard to indicate a total
* fragment sequence size in one place in the beginning or anywhere else. Hence
* the caller should take care to provide the complete buffer with the max size
* set accordingly.
*
* Return: QDF_STATUS_SUCCESS in the case of success, QDF_STATUS value giving
* the reason for error in the case of failure
*/
QDF_STATUS wlan_defrag_subelem_fragseq(bool inline_defrag,
uint8_t subelemfragid,
uint8_t *fragbuff,
qdf_size_t fragbuff_maxsize,
uint8_t *defragbuff,
qdf_size_t defragbuff_maxsize,
qdf_size_t *defragpayload_len);
/**
* wlan_is_emulation_platform() - check if platform is emulation based
* @phy_version - psoc nif phy_version