/** *fbnic_tlv_attr_put_string-Addstringtomessage *@msg:Messageheaderweareaddingflagattributeto *@attr_id:IDofflagattributeweareaddingtomessage *@string:Bytepointertonullterminatedstringtobestored * *Return:-ENOSPCifthereisnoroomfortheattribute.Otherwise0. * *Addsheaderandcopiesdatapointedtobystringintothemessage.Will *copytheaddressrawsoitwillbeinbyteorder.
**/ int fbnic_tlv_attr_put_string(struct fbnic_tlv_msg *msg, u16 attr_id, constchar *string)
{ int attr_max_len = PAGE_SIZE - sizeof(*msg); int str_len = 1;
/* The max length will be message minus existing message and new *attributeheader.SincethemessageismeasuredinDWORDswehave *tomultiplythesizeby4. * *Thestringlengthdoesn'tincludethe\0sowehavetoaddoneto *thefinalvalue,sostartwiththatasourinitialvalue. * *Wewillverifyifthestringwillfitinfbnic_tlv_attr_put_value()
*/
attr_max_len -= le16_to_cpu(msg->hdr.len) * sizeof(u32);
str_len += strnlen(string, attr_max_len);
/* Copy the value and adjust for byte ordering */
memcpy(&le64_value, &attr->value[0],
le16_to_cpu(attr->hdr.len) - sizeof(*attr));
value = le64_to_cpu(le64_value);
/* Sign extend the return value by using a pair of shifts */ return (value << shift) >> shift;
}
/* Make sure we have space for at least the nest header plus one more */
attr_max_len -= le16_to_cpu(msg->hdr.len) * sizeof(u32); if (attr_max_len < sizeof(*attr) * 2) return NULL;
/* Record attribute type and size */
hdr.type = attr_id;
/* Add current message length to account for consumption within the *pageandleaveitasamultipleofDWORDs,wewillshiftto *byteswhenwecloseitout.
*/
hdr.len = cpu_to_le16(1);
if (attr_id >= FBNIC_TLV_RESULTS_MAX) return -EINVAL;
while (tlv_index->id != attr_id) { if (tlv_index->id == FBNIC_TLV_ATTR_ID_UNKNOWN) { if (attr->hdr.cannot_ignore) return -ENOENT; return le16_to_cpu(attr->hdr.len);
}
tlv_index++;
}
if (offset_in_page(attr) + len > PAGE_SIZE - sizeof(*attr)) return -E2BIG;
switch (tlv_index->type) { case FBNIC_TLV_STRING: if (!len || len > tlv_index->len) return -EINVAL; if (((char *)value)[len - 1]) return -EINVAL; break; case FBNIC_TLV_FLAG: if (len) return -EINVAL; break; case FBNIC_TLV_UNSIGNED: case FBNIC_TLV_SIGNED: if (tlv_index->len > sizeof(__le64)) return -EINVAL;
fallthrough; case FBNIC_TLV_BINARY: if (!len || len > tlv_index->len) return -EINVAL; break; case FBNIC_TLV_NESTED: case FBNIC_TLV_ARRAY: if (len % 4) return -EINVAL; break; default: return -EINVAL;
}
return0;
}
/** *fbnic_tlv_attr_parse_array-Parsearrayofattributesintoresultsarray *@attr:Startofattributesinthemessage *@len:Lengthofattributesinthemessage *@results:Arrayofpointerstostoretheresultsofparsing *@tlv_index:ListofTLVattributestobeparsedfrommessage *@tlv_attr_id:SpecificIDthatisrepeatedinarray *@array_len:Numberofresultstostoreinresultsarray * *Return:zeroonsuccess,ornegativevalueonerror. * *Willtakealistofattributesandaparserdefinitionandwillcapture *theresultsintheresultsarraytohavethedataextractedlater.
**/ int fbnic_tlv_attr_parse_array(struct fbnic_tlv_msg *attr, int len, struct fbnic_tlv_msg **results, conststruct fbnic_tlv_index *tlv_index,
u16 tlv_attr_id, size_t array_len)
{ int i = 0;
/* Nothing to parse if header was only thing there */ if (!len) return0;
/* Work through list of attributes, parsing them as necessary */ while (len > 0) { int err = fbnic_tlv_attr_validate(attr, tlv_index);
u16 attr_id = attr->hdr.type;
u16 attr_len;
/* Stop parsing on full error */ if (err < 0) return err;
/* Ignore results for unsupported values */ if (!err) { /* Do not overwrite existing entries */ if (results[attr_id]) return -EADDRINUSE;
results[attr_id] = attr;
}
attr_len = FBNIC_TLV_MSG_SIZE(le16_to_cpu(attr->hdr.len));
len -= attr_len;
attr += attr_len;
}
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.