diff --git a/src/cmdu.h b/src/cmdu.h index 5730f35d65ad02de799491da183fc48ff0655fc3..4a112e0bb41138caccea97282494d88f6d009ecc 100644 --- a/src/cmdu.h +++ b/src/cmdu.h @@ -23,7 +23,7 @@ #include "bufutil.h" #include "hlist.h" -/** struct cmdu_header - IEEE1905 CMDU header */ +/** struct cmdu_header - IEEE-1905 CMDU header */ struct cmdu_header { uint8_t version; uint8_t rsvd; /**< reserved */ @@ -41,7 +41,7 @@ struct cmdu_header { #define CMDU_DEFAULT_TIMEOUT 1000 - +/** struct cmdu_linear - represents a CMDU frame with header and TLVs */ struct cmdu_linear { struct cmdu_header hdr; uint8_t data[]; @@ -57,17 +57,19 @@ struct cmdu_frag { uint16_t len; struct list_head list; }; + /** * @struct cmdu_buff - * @brief control structure for a CMDU buffer + * @brief Control structure for a CMDU buffer * - * This control structure abstracts out a CMDU frame. In addition to holding - * pointer to the actual CMDU frame, it holds meta information about the CMDU, - * viz. for a receive CMDU which interface it arrived on, sender's macaddress + * This structure abstracts out a CMDU frame. In addition to holding pointer + * to an actual CMDU frame, it holds meta information about the CMDU, + * such as, for a Rx CMDU which interface it arrived on, sender's macaddress * etc. * - * APIs are provided for working with cmdu_buff. Function for iterating through - * TLVs in a CMDU, adding TLV, getting size of CMDU frame etc. + * APIs are provided for working with a cmdu_buff. There are functions to + * parse a cmdu_buff and get the list of TLVs within it, ititerate through TLVs + * in a CMDU, adding a TLV, peeking a TLV, getting size of a CMDU frame etc. * * On the transmit and receive path, it is possible to achieve zero-memcpy for * CMDU manipulation including inserting/extracting the ethernet frame header. @@ -108,7 +110,7 @@ struct tlv_policy { /** * @struct tlv - * @brief defines a IEEE1905 TLV + * @brief defines an IEEE-1905 TLV */ struct tlv { uint8_t type; @@ -119,28 +121,70 @@ struct tlv { /** * Allocates a TLV * @param[in] datalen length of tlv data in bytes - * @param[out] band band struct wifi_band type * * @return newly allocated tlv on success, or NULL if failed. */ struct tlv *tlv_alloc(uint16_t datalen); + +/** Free an allocated TLV */ +void tlv_free_linear(struct tlv *t); + +/** Zeros out a TLV */ void tlv_zero(struct tlv *t); + +/* following functions for internal use only */ int tlv_ok(struct tlv *t, int rem); struct tlv *tlv_next(struct tlv *t, int *rem); + +/** Get length of TLV data */ uint16_t tlv_length(struct tlv *t); -uint16_t tlv_total_length(struct tlv *t); -void tlv_free_linear(struct tlv *t); +/** Get total length of a TLV including the header */ +uint16_t tlv_total_length(struct tlv *t); +/** Allocates cmdu_buff to hold 'size' length cmdu payload */ struct cmdu_buff *cmdu_alloc(int size); + +/** + * Allocates cmdu_buff to hold full-size ethernet frame of 1500 bytes + * + * @return newly allocated cmdu_buff on success, or NULL if failed. + * + * This function is useful to allocate CMDUs for transmit when size of the + * payload i.e. TLV data is not known a-priori. + */ struct cmdu_buff *cmdu_alloc_default(void); + +/** + * Convenient function to allocate cmdu_buff that can hold a full-size CMDU + * @param[in] type CMDU type + * @param[in|out] mid CMDU mid if nonzero, or valid mid returned + * + * @return newly allocated cmdu_buff on success, or NULL if failed. + * + * If mid passed is 0, then the next valid mid gets assigned to the newly + * allocated cmdu. + */ struct cmdu_buff *cmdu_alloc_simple(uint16_t type, uint16_t *mid); + +/** + * Prepare cmdu_buff from a received CMDU whose fields are known + * @param[in] type CMDU type + * @param[in|out] mid CMDU mid if nonzero, or valid mid returned + * @param[in] ifname interface name through which the CMDU is received + * @param[in] origin macaddress of the source that sent the CMDU + * @param[in] tlvs flattened TLV data bytes + * @param[in] tlvslen length of the TLV data bytes + * + * @return newly allocated cmdu_buff on success, or NULL if failed. + */ struct cmdu_buff *cmdu_alloc_custom(uint16_t type, uint16_t *mid, char *ifname, uint8_t *origin, uint8_t *tlvs, uint32_t tlvslen); +/** Free CMDU allocated through cmdu_alloc*() functions */ void cmdu_free(struct cmdu_buff *c); static inline void cmdu_set_type(struct cmdu_buff *c, uint16_t type) @@ -183,42 +227,84 @@ static inline uint8_t *cmdu_get_origin(struct cmdu_buff *c) return c ? c->origin : NULL; } +/** Full size of a CMDU frame including the CMDU header */ int cmdu_size(struct cmdu_buff *c); + +/** Get a valid CMDU 'mid' that can be used next */ uint16_t cmdu_get_next_mid(void); + +/** (Re)initialize the mid generation. + * + * Users of libmidgen.so do not need to explicitely call this function to + * initialize the mids. It is done implicitely whenever libmidgen.so is loaded. + */ uint16_t cmdu_init_mid(void); + +/** Helper function to get expected response CMDU for a request CMDU */ uint16_t cmdu_expect_response(uint16_t req_type); + +/** Helper function to check if a CMDU is of relay multicast type */ int cmdu_should_relay(uint16_t type); + +/** Function to check if a CMDU type is valid */ int is_cmdu_type_valid(uint16_t type); + +/** Function to check if a CMDU is of response type */ int is_cmdu_type_response(uint16_t type); + +/** Function to check if a CMDU type must include atleast one TLV */ int is_cmdu_tlv_required(uint16_t type); -int cmdu_validate(struct cmdu_buff *c, int max_tlvtype, - struct tlv_policy *policy); +/** Parse a CMDU to get list of the TLVs present in it + * + * @param[in] c cmdu_buff for parsing + * @param[in|out] tv array of TLVs to hold the returned TLVs + * @param[in] policy policy for TLV parsing + * @param[in] policy_len length of the policy + * + * @return 0 on success, else non-zero. + * + * The TLVs are returned in the passed 'tv' array. + */ int cmdu_parse_tlvs(struct cmdu_buff *c, struct tlv *tv[][16], struct tlv_policy *policy, int policy_len); - +/** Copy append flattended TLVs data buffer into a CMDU */ int cmdu_copy_tlvs_linear(struct cmdu_buff *c, uint8_t *tlvs, uint32_t tlvslen); + +/** Copy append un-flattened TLVs into a CMDU */ int cmdu_copy_tlvs(struct cmdu_buff *c, struct tlv *tv[], int tv_arrsize); + +/** Create a clone or duplicate of a CMDU */ struct cmdu_buff *cmdu_clone(struct cmdu_buff *frm); +/** Function to reserve space at the tail of a CMDU buffer */ struct tlv *cmdu_reserve_tlv(struct cmdu_buff *c, uint16_t tlv_datalen); + +/** Function puts a TLV within the CMDU buffer at the reserved area */ int cmdu_put_tlv(struct cmdu_buff *c, struct tlv *t); + +/** Copy data at the tail of a CMDU */ int cmdu_put(struct cmdu_buff *c, uint8_t *bytes, int len); + +/** Append End-Of-Message TLV to a CMDU */ int cmdu_put_eom(struct cmdu_buff *c); struct tlv *cmdu_extract_tlv(struct cmdu_buff *c, uint8_t tlv_type); struct tlv *cmdu_peek_tlv(struct cmdu_buff *c, uint8_t tlv_type); + +#if 0 int cmdu_reserve(struct cmdu_buff *c, size_t s); int cmdu_expand(struct cmdu_buff *c, size_t newsize); -int cmdu_send(struct cmdu_buff *c); +#endif struct cmdu_buff *cmdu_fragment(uint8_t *data, int datalen); +/** Helper function to stringify a CMDU type */ const char *cmdu_type2str(uint16_t type); - +/** Iterate through TLVs within a CMDU */ #define cmdu_for_each_tlv(pos, tlvs, rem) \ for (pos = (struct tlv *) tlvs; \ tlv_ok(pos, rem); \ @@ -226,7 +312,7 @@ const char *cmdu_type2str(uint16_t type); - +/** struct cmdu_queue - queue to hold CMDU buffers */ struct cmdu_queue { struct list_head q; pthread_mutex_t lock;