dcb: Generalize dcb_get_attribute()
The function dcb_get_attribute() assumes that the caller knows the exact size of the looked-for payload. It also assumes that the response comes wrapped in an DCB_ATTR_IEEE nest. The former assumption does not hold for the IEEE APP table, which has variable size. The latter one does not hold for DCBX, which is not IEEE-nested, and also for any CEE attributes, which would come CEE-nested. Factor out the payload extractor from the current dcb_get_attribute() code, and put into a helper. Then rewrite dcb_get_attribute() compatibly in terms of the new function. Introduce dcb_get_attribute_va() as a thin wrapper for IEEE-nested access, and dcb_get_attribute_bare() for access to attributes that are not nested. Signed-off-by: Petr Machata <me@pmachata.org> Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
parent
69290c32dc
commit
e59876ff55
79
dcb/dcb.c
79
dcb/dcb.c
|
|
@ -59,25 +59,19 @@ static void dcb_free(struct dcb *dcb)
|
||||||
struct dcb_get_attribute {
|
struct dcb_get_attribute {
|
||||||
struct dcb *dcb;
|
struct dcb *dcb;
|
||||||
int attr;
|
int attr;
|
||||||
void *data;
|
void *payload;
|
||||||
size_t data_len;
|
__u16 payload_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dcb_get_attribute_attr_ieee_cb(const struct nlattr *attr, void *data)
|
static int dcb_get_attribute_attr_ieee_cb(const struct nlattr *attr, void *data)
|
||||||
{
|
{
|
||||||
struct dcb_get_attribute *ga = data;
|
struct dcb_get_attribute *ga = data;
|
||||||
uint16_t len;
|
|
||||||
|
|
||||||
if (mnl_attr_get_type(attr) != ga->attr)
|
if (mnl_attr_get_type(attr) != ga->attr)
|
||||||
return MNL_CB_OK;
|
return MNL_CB_OK;
|
||||||
|
|
||||||
len = mnl_attr_get_payload_len(attr);
|
ga->payload = mnl_attr_get_payload(attr);
|
||||||
if (len != ga->data_len) {
|
ga->payload_len = mnl_attr_get_payload_len(attr);
|
||||||
fprintf(stderr, "Wrong len %d, expected %zd\n", len, ga->data_len);
|
|
||||||
return MNL_CB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ga->data, mnl_attr_get_payload(attr), ga->data_len);
|
|
||||||
return MNL_CB_STOP;
|
return MNL_CB_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,6 +88,16 @@ static int dcb_get_attribute_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
return mnl_attr_parse(nlh, sizeof(struct dcbmsg), dcb_get_attribute_attr_cb, data);
|
return mnl_attr_parse(nlh, sizeof(struct dcbmsg), dcb_get_attribute_attr_cb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dcb_get_attribute_bare_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
/* Bare attributes (e.g. DCB_ATTR_DCBX) are not wrapped inside an IEEE
|
||||||
|
* container, so this does not have to go through unpacking in
|
||||||
|
* dcb_get_attribute_attr_cb().
|
||||||
|
*/
|
||||||
|
return mnl_attr_parse(nlh, sizeof(struct dcbmsg),
|
||||||
|
dcb_get_attribute_attr_ieee_cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
struct dcb_set_attribute_response {
|
struct dcb_set_attribute_response {
|
||||||
int response_attr;
|
int response_attr;
|
||||||
};
|
};
|
||||||
|
|
@ -155,25 +159,70 @@ static struct nlmsghdr *dcb_prepare(struct dcb *dcb, const char *dev,
|
||||||
return nlh;
|
return nlh;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dcb_get_attribute(struct dcb *dcb, const char *dev, int attr, void *data, size_t data_len)
|
static int __dcb_get_attribute(struct dcb *dcb, int command,
|
||||||
|
const char *dev, int attr,
|
||||||
|
void **payload_p, __u16 *payload_len_p,
|
||||||
|
int (*get_attribute_cb)(const struct nlmsghdr *nlh,
|
||||||
|
void *data))
|
||||||
{
|
{
|
||||||
struct dcb_get_attribute ga;
|
struct dcb_get_attribute ga;
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
nlh = dcb_prepare(dcb, dev, RTM_GETDCB, DCB_CMD_IEEE_GET);
|
nlh = dcb_prepare(dcb, dev, RTM_GETDCB, command);
|
||||||
|
|
||||||
ga = (struct dcb_get_attribute) {
|
ga = (struct dcb_get_attribute) {
|
||||||
.dcb = dcb,
|
.dcb = dcb,
|
||||||
.attr = attr,
|
.attr = attr,
|
||||||
.data = data,
|
.payload = NULL,
|
||||||
.data_len = data_len,
|
|
||||||
};
|
};
|
||||||
ret = dcb_talk(dcb, nlh, dcb_get_attribute_cb, &ga);
|
ret = dcb_talk(dcb, nlh, get_attribute_cb, &ga);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
perror("Attribute read");
|
perror("Attribute read");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
if (ga.payload == NULL) {
|
||||||
|
perror("Attribute not found");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*payload_p = ga.payload;
|
||||||
|
*payload_len_p = ga.payload_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dcb_get_attribute_va(struct dcb *dcb, const char *dev, int attr,
|
||||||
|
void **payload_p, __u16 *payload_len_p)
|
||||||
|
{
|
||||||
|
return __dcb_get_attribute(dcb, DCB_CMD_IEEE_GET, dev, attr,
|
||||||
|
payload_p, payload_len_p,
|
||||||
|
dcb_get_attribute_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dcb_get_attribute_bare(struct dcb *dcb, int cmd, const char *dev, int attr,
|
||||||
|
void **payload_p, __u16 *payload_len_p)
|
||||||
|
{
|
||||||
|
return __dcb_get_attribute(dcb, cmd, dev, attr,
|
||||||
|
payload_p, payload_len_p,
|
||||||
|
dcb_get_attribute_bare_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dcb_get_attribute(struct dcb *dcb, const char *dev, int attr, void *data, size_t data_len)
|
||||||
|
{
|
||||||
|
__u16 payload_len;
|
||||||
|
void *payload;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = dcb_get_attribute_va(dcb, dev, attr, &payload, &payload_len);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (payload_len != data_len) {
|
||||||
|
fprintf(stderr, "Wrong len %d, expected %zd\n", payload_len, data_len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(data, payload, data_len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,13 @@ int dcb_get_attribute(struct dcb *dcb, const char *dev, int attr,
|
||||||
void *data, size_t data_len);
|
void *data, size_t data_len);
|
||||||
int dcb_set_attribute(struct dcb *dcb, const char *dev, int attr,
|
int dcb_set_attribute(struct dcb *dcb, const char *dev, int attr,
|
||||||
const void *data, size_t data_len);
|
const void *data, size_t data_len);
|
||||||
|
int dcb_get_attribute_va(struct dcb *dcb, const char *dev, int attr,
|
||||||
|
void **payload_p, __u16 *payload_len_p);
|
||||||
int dcb_set_attribute_va(struct dcb *dcb, int command, const char *dev,
|
int dcb_set_attribute_va(struct dcb *dcb, int command, const char *dev,
|
||||||
int (*cb)(struct dcb *dcb, struct nlmsghdr *nlh, void *data),
|
int (*cb)(struct dcb *dcb, struct nlmsghdr *nlh, void *data),
|
||||||
void *data);
|
void *data);
|
||||||
|
int dcb_get_attribute_bare(struct dcb *dcb, int cmd, const char *dev, int attr,
|
||||||
|
void **payload_p, __u16 *payload_len_p);
|
||||||
int dcb_set_attribute_bare(struct dcb *dcb, int command, const char *dev,
|
int dcb_set_attribute_bare(struct dcb *dcb, int command, const char *dev,
|
||||||
int attr, const void *data, size_t data_len,
|
int attr, const void *data, size_t data_len,
|
||||||
int response_attr);
|
int response_attr);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue