/* verify pointers are not NULL */ if (!string || !msg) return FM10K_ERR_PARAM;
attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
/* copy string into local variable and then write to msg */ do { /* write data to message */ if (len && !(len % 4)) {
attr[len / 4] = attr_data;
attr_data = 0;
}
/* record character to offset location */
attr_data |= (u32)(*string) << (8 * (len % 4));
len++;
/* test for NULL and then increment */
} while (*(string++));
/* write last piece of data to message */
attr[(len + 3) / 4] = attr_data;
/* record attribute header, update message length */
len <<= FM10K_TLV_LEN_SHIFT;
attr[0] = len | attr_id;
/* add header length to length */
len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
*msg += FM10K_TLV_LEN_ALIGN(len);
/* verify pointers are not NULL */ if (!msg || !mac_addr) return FM10K_ERR_PARAM;
attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
/* record attribute header, update message length */
attr[0] = len | attr_id;
/* copy value into local variable and then write to msg */
attr[1] = le32_to_cpu(*(const __le32 *)&mac_addr[0]);
attr[2] = le16_to_cpu(*(const __le16 *)&mac_addr[4]);
attr[2] |= (u32)vlan << 16;
/* add header length to length */
len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
*msg += FM10K_TLV_LEN_ALIGN(len);
/* verify pointer is not NULL */ if (!msg) return FM10K_ERR_PARAM;
/* locate the nested header and retrieve its length */
attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
len = (attr[0] >> FM10K_TLV_LEN_SHIFT) << FM10K_TLV_LEN_SHIFT;
/* only include nest if data was added to it */ if (len) {
len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
*msg += len;
}
/* verify this is an attribute and not a message */ if (*attr & (FM10K_TLV_FLAGS_MSG << FM10K_TLV_FLAGS_SHIFT)) return FM10K_ERR_PARAM;
/* search through the list of attributes to find a matching ID */ while (tlv_attr->id < attr_id)
tlv_attr++;
/* if didn't find a match then we should exit */ if (tlv_attr->id != attr_id) return FM10K_NOT_IMPLEMENTED;
/* move to start of attribute data */
attr++;
switch (tlv_attr->type) { case FM10K_TLV_NULL_STRING: if (!len ||
(attr[(len - 1) / 4] & (0xFF << (8 * ((len - 1) % 4))))) return FM10K_ERR_PARAM; if (len > tlv_attr->len) return FM10K_ERR_PARAM; break; case FM10K_TLV_MAC_ADDR: if (len != ETH_ALEN) return FM10K_ERR_PARAM; break; case FM10K_TLV_BOOL: if (len) return FM10K_ERR_PARAM; break; case FM10K_TLV_UNSIGNED: case FM10K_TLV_SIGNED: if (len != tlv_attr->len) return FM10K_ERR_PARAM; break; case FM10K_TLV_LE_STRUCT: /* struct must be 4 byte aligned */ if ((len % 4) || len != tlv_attr->len) return FM10K_ERR_PARAM; break; case FM10K_TLV_NESTED: /* nested attributes must be 4 byte aligned */ if (len % 4) return FM10K_ERR_PARAM; break; default: /* attribute id is mapped to bad value */ return FM10K_ERR_PARAM;
}
/* The message below is meant to be used as a test message to demonstrate *howtousetheTLVinterfaceandtotestthetypes.Normallythiscode *becompiledoutbystrippingthecodewrappedinFM10K_TLV_TEST_MSG
*/ conststruct fm10k_tlv_attr fm10k_tlv_msg_test_attr[] = {
FM10K_TLV_ATTR_NULL_STRING(FM10K_TEST_MSG_STRING, 80),
FM10K_TLV_ATTR_MAC_ADDR(FM10K_TEST_MSG_MAC_ADDR),
FM10K_TLV_ATTR_U8(FM10K_TEST_MSG_U8),
FM10K_TLV_ATTR_U16(FM10K_TEST_MSG_U16),
FM10K_TLV_ATTR_U32(FM10K_TEST_MSG_U32),
FM10K_TLV_ATTR_U64(FM10K_TEST_MSG_U64),
FM10K_TLV_ATTR_S8(FM10K_TEST_MSG_S8),
FM10K_TLV_ATTR_S16(FM10K_TEST_MSG_S16),
FM10K_TLV_ATTR_S32(FM10K_TEST_MSG_S32),
FM10K_TLV_ATTR_S64(FM10K_TEST_MSG_S64),
FM10K_TLV_ATTR_LE_STRUCT(FM10K_TEST_MSG_LE_STRUCT, 8),
FM10K_TLV_ATTR_NESTED(FM10K_TEST_MSG_NESTED),
FM10K_TLV_ATTR_S32(FM10K_TEST_MSG_RESULT),
FM10K_TLV_ATTR_LAST
};
/** *fm10k_tlv_msg_test_generate_data-Stuffmessagewithdata *@msg:Pointertomessage *@attr_flags:Listofflagsindicatingwhatattributestoadd * *Thisfunctionismeanttoloadamessagebufferwithattributedata
**/ staticvoid fm10k_tlv_msg_test_generate_data(u32 *msg, u32 attr_flags)
{ if (attr_flags & BIT(FM10K_TEST_MSG_STRING))
fm10k_tlv_attr_put_null_string(msg, FM10K_TEST_MSG_STRING,
test_str); if (attr_flags & BIT(FM10K_TEST_MSG_MAC_ADDR))
fm10k_tlv_attr_put_mac_vlan(msg, FM10K_TEST_MSG_MAC_ADDR,
test_mac, test_vlan); if (attr_flags & BIT(FM10K_TEST_MSG_U8))
fm10k_tlv_attr_put_u8(msg, FM10K_TEST_MSG_U8, test_u8); if (attr_flags & BIT(FM10K_TEST_MSG_U16))
fm10k_tlv_attr_put_u16(msg, FM10K_TEST_MSG_U16, test_u16); if (attr_flags & BIT(FM10K_TEST_MSG_U32))
fm10k_tlv_attr_put_u32(msg, FM10K_TEST_MSG_U32, test_u32); if (attr_flags & BIT(FM10K_TEST_MSG_U64))
fm10k_tlv_attr_put_u64(msg, FM10K_TEST_MSG_U64, test_u64); if (attr_flags & BIT(FM10K_TEST_MSG_S8))
fm10k_tlv_attr_put_s8(msg, FM10K_TEST_MSG_S8, test_s8); if (attr_flags & BIT(FM10K_TEST_MSG_S16))
fm10k_tlv_attr_put_s16(msg, FM10K_TEST_MSG_S16, test_s16); if (attr_flags & BIT(FM10K_TEST_MSG_S32))
fm10k_tlv_attr_put_s32(msg, FM10K_TEST_MSG_S32, test_s32); if (attr_flags & BIT(FM10K_TEST_MSG_S64))
fm10k_tlv_attr_put_s64(msg, FM10K_TEST_MSG_S64, test_s64); if (attr_flags & BIT(FM10K_TEST_MSG_LE_STRUCT))
fm10k_tlv_attr_put_le_struct(msg, FM10K_TEST_MSG_LE_STRUCT,
test_le, 8);
}
/* retrieve results of a previous test */ if (!!results[FM10K_TEST_MSG_RESULT]) return fm10k_tlv_attr_get_s32(results[FM10K_TEST_MSG_RESULT],
&mbx->test_result);
parse_nested: if (!!results[FM10K_TEST_MSG_STRING]) {
err = fm10k_tlv_attr_get_null_string(
results[FM10K_TEST_MSG_STRING],
result_str); if (!err && memcmp(test_str, result_str, sizeof(test_str)))
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_MAC_ADDR]) {
err = fm10k_tlv_attr_get_mac_vlan(
results[FM10K_TEST_MSG_MAC_ADDR],
result_mac, &result_vlan); if (!err && !ether_addr_equal(test_mac, result_mac))
err = FM10K_ERR_INVALID_VALUE; if (!err && test_vlan != result_vlan)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_U8]) {
err = fm10k_tlv_attr_get_u8(results[FM10K_TEST_MSG_U8],
&result_u8); if (!err && test_u8 != result_u8)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_U16]) {
err = fm10k_tlv_attr_get_u16(results[FM10K_TEST_MSG_U16],
&result_u16); if (!err && test_u16 != result_u16)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_U32]) {
err = fm10k_tlv_attr_get_u32(results[FM10K_TEST_MSG_U32],
&result_u32); if (!err && test_u32 != result_u32)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_U64]) {
err = fm10k_tlv_attr_get_u64(results[FM10K_TEST_MSG_U64],
&result_u64); if (!err && test_u64 != result_u64)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_S8]) {
err = fm10k_tlv_attr_get_s8(results[FM10K_TEST_MSG_S8],
&result_s8); if (!err && test_s8 != result_s8)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_S16]) {
err = fm10k_tlv_attr_get_s16(results[FM10K_TEST_MSG_S16],
&result_s16); if (!err && test_s16 != result_s16)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_S32]) {
err = fm10k_tlv_attr_get_s32(results[FM10K_TEST_MSG_S32],
&result_s32); if (!err && test_s32 != result_s32)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_S64]) {
err = fm10k_tlv_attr_get_s64(results[FM10K_TEST_MSG_S64],
&result_s64); if (!err && test_s64 != result_s64)
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
} if (!!results[FM10K_TEST_MSG_LE_STRUCT]) {
err = fm10k_tlv_attr_get_le_struct(
results[FM10K_TEST_MSG_LE_STRUCT],
result_le, sizeof(result_le)); if (!err && memcmp(test_le, result_le, sizeof(test_le)))
err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result;
}
if (!!results[FM10K_TEST_MSG_NESTED]) { /* clear any pointers */
memset(nest_results, 0, sizeof(nest_results));
/* parse the nested attributes into the nest results list */
err = fm10k_tlv_attr_parse(results[FM10K_TEST_MSG_NESTED],
nest_results,
fm10k_tlv_msg_test_attr); if (err) goto report_result;
/* loop back through to the start */
results = nest_results; goto parse_nested;
}
report_result: /* generate reply with test result */
fm10k_tlv_msg_init(reply, FM10K_TLV_MSG_ID_TEST);
fm10k_tlv_attr_put_s32(reply, FM10K_TEST_MSG_RESULT, err);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.