0001
0002
0003
0004 #include <linux/kernel.h>
0005 #include <linux/errno.h>
0006 #include <linux/types.h>
0007 #include <linux/slab.h>
0008
0009 #include "vnic_vic.h"
0010
0011 struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, const u8 *oui,
0012 const u8 type)
0013 {
0014 struct vic_provinfo *vp;
0015
0016 if (!oui)
0017 return NULL;
0018
0019 vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags);
0020 if (!vp)
0021 return NULL;
0022
0023 memcpy(vp->oui, oui, sizeof(vp->oui));
0024 vp->type = type;
0025 vp->length = htonl(sizeof(vp->num_tlvs));
0026
0027 return vp;
0028 }
0029
0030 void vic_provinfo_free(struct vic_provinfo *vp)
0031 {
0032 kfree(vp);
0033 }
0034
0035 int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length,
0036 const void *value)
0037 {
0038 struct vic_provinfo_tlv *tlv;
0039
0040 if (!vp || !value)
0041 return -EINVAL;
0042
0043 if (ntohl(vp->length) + offsetof(struct vic_provinfo_tlv, value) +
0044 length > VIC_PROVINFO_MAX_TLV_DATA)
0045 return -ENOMEM;
0046
0047 tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv +
0048 ntohl(vp->length) - sizeof(vp->num_tlvs));
0049
0050 tlv->type = htons(type);
0051 tlv->length = htons(length);
0052 memcpy(tlv->value, value, length);
0053
0054 vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1);
0055 vp->length = htonl(ntohl(vp->length) +
0056 offsetof(struct vic_provinfo_tlv, value) + length);
0057
0058 return 0;
0059 }
0060
0061 size_t vic_provinfo_size(struct vic_provinfo *vp)
0062 {
0063 return vp ? ntohl(vp->length) + sizeof(*vp) - sizeof(vp->num_tlvs) : 0;
0064 }