|
Packit Bot |
867fae |
// SPDX-License-Identifier: GPL-2.0+
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
#include <inttypes.h>
|
|
Packit Bot |
867fae |
#include <stdio.h>
|
|
Packit Bot |
867fae |
#include <linux/dcbnl.h>
|
|
Packit Bot |
867fae |
#include <libmnl/libmnl.h>
|
|
Packit Bot |
867fae |
#include <getopt.h>
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
#include "dcb.h"
|
|
Packit Bot |
867fae |
#include "mnl_utils.h"
|
|
Packit Bot |
867fae |
#include "namespace.h"
|
|
Packit Bot |
867fae |
#include "utils.h"
|
|
Packit Bot |
867fae |
#include "version.h"
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_init(struct dcb *dcb)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
dcb->buf = malloc(MNL_SOCKET_BUFFER_SIZE);
|
|
Packit Bot |
867fae |
if (dcb->buf == NULL) {
|
|
Packit Bot |
867fae |
perror("Netlink buffer allocation");
|
|
Packit Bot |
867fae |
return -1;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
dcb->nl = mnlu_socket_open(NETLINK_ROUTE);
|
|
Packit Bot |
867fae |
if (dcb->nl == NULL) {
|
|
Packit Bot |
867fae |
perror("Open netlink socket");
|
|
Packit Bot |
867fae |
goto err_socket_open;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
new_json_obj_plain(dcb->json_output);
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
err_socket_open:
|
|
Packit Bot |
867fae |
free(dcb->buf);
|
|
Packit Bot |
867fae |
return -1;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static void dcb_fini(struct dcb *dcb)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
delete_json_obj_plain();
|
|
Packit Bot |
867fae |
mnl_socket_close(dcb->nl);
|
|
Packit Bot |
867fae |
free(dcb->buf);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static struct dcb *dcb_alloc(void)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb *dcb;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
dcb = calloc(1, sizeof(*dcb));
|
|
Packit Bot |
867fae |
if (!dcb)
|
|
Packit Bot |
867fae |
return NULL;
|
|
Packit Bot |
867fae |
return dcb;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static void dcb_free(struct dcb *dcb)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
free(dcb);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
struct dcb_get_attribute {
|
|
Packit Bot |
867fae |
struct dcb *dcb;
|
|
Packit Bot |
867fae |
int attr;
|
|
Packit Bot |
867fae |
void *payload;
|
|
Packit Bot |
867fae |
__u16 payload_len;
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_get_attribute_attr_ieee_cb(const struct nlattr *attr, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_get_attribute *ga = data;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (mnl_attr_get_type(attr) != ga->attr)
|
|
Packit Bot |
867fae |
return MNL_CB_OK;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
ga->payload = mnl_attr_get_payload(attr);
|
|
Packit Bot |
867fae |
ga->payload_len = mnl_attr_get_payload_len(attr);
|
|
Packit Bot |
867fae |
return MNL_CB_STOP;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_get_attribute_attr_cb(const struct nlattr *attr, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
if (mnl_attr_get_type(attr) != DCB_ATTR_IEEE)
|
|
Packit Bot |
867fae |
return MNL_CB_OK;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return mnl_attr_parse_nested(attr, dcb_get_attribute_attr_ieee_cb, data);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_get_attribute_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
return mnl_attr_parse(nlh, sizeof(struct dcbmsg), dcb_get_attribute_attr_cb, data);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_get_attribute_bare_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
/* Bare attributes (e.g. DCB_ATTR_DCBX) are not wrapped inside an IEEE
|
|
Packit Bot |
867fae |
* container, so this does not have to go through unpacking in
|
|
Packit Bot |
867fae |
* dcb_get_attribute_attr_cb().
|
|
Packit Bot |
867fae |
*/
|
|
Packit Bot |
867fae |
return mnl_attr_parse(nlh, sizeof(struct dcbmsg),
|
|
Packit Bot |
867fae |
dcb_get_attribute_attr_ieee_cb, data);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
struct dcb_set_attribute_response {
|
|
Packit Bot |
867fae |
int response_attr;
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_set_attribute_attr_cb(const struct nlattr *attr, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_set_attribute_response *resp = data;
|
|
Packit Bot |
867fae |
uint16_t len;
|
|
Packit Bot |
867fae |
uint8_t err;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (mnl_attr_get_type(attr) != resp->response_attr)
|
|
Packit Bot |
867fae |
return MNL_CB_OK;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
len = mnl_attr_get_payload_len(attr);
|
|
Packit Bot |
867fae |
if (len != 1) {
|
|
Packit Bot |
867fae |
fprintf(stderr, "Response attribute expected to have size 1, not %d\n", len);
|
|
Packit Bot |
867fae |
return MNL_CB_ERROR;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
err = mnl_attr_get_u8(attr);
|
|
Packit Bot |
867fae |
if (err) {
|
|
Packit Bot |
867fae |
fprintf(stderr, "Error when attempting to set attribute: %s\n",
|
|
Packit Bot |
867fae |
strerror(err));
|
|
Packit Bot |
867fae |
return MNL_CB_ERROR;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return MNL_CB_STOP;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_set_attribute_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
return mnl_attr_parse(nlh, sizeof(struct dcbmsg), dcb_set_attribute_attr_cb, data);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_talk(struct dcb *dcb, struct nlmsghdr *nlh, mnl_cb_t cb, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
int ret;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
ret = mnl_socket_sendto(dcb->nl, nlh, nlh->nlmsg_len);
|
|
Packit Bot |
867fae |
if (ret < 0) {
|
|
Packit Bot |
867fae |
perror("mnl_socket_sendto");
|
|
Packit Bot |
867fae |
return -1;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return mnlu_socket_recv_run(dcb->nl, nlh->nlmsg_seq, dcb->buf, MNL_SOCKET_BUFFER_SIZE,
|
|
Packit Bot |
867fae |
cb, data);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static struct nlmsghdr *dcb_prepare(struct dcb *dcb, const char *dev,
|
|
Packit Bot |
867fae |
uint32_t nlmsg_type, uint8_t dcb_cmd)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcbmsg dcbm = {
|
|
Packit Bot |
867fae |
.cmd = dcb_cmd,
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
struct nlmsghdr *nlh;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
nlh = mnlu_msg_prepare(dcb->buf, nlmsg_type, NLM_F_REQUEST, &dcbm, sizeof(dcbm));
|
|
Packit Bot |
867fae |
mnl_attr_put_strz(nlh, DCB_ATTR_IFNAME, dev);
|
|
Packit Bot |
867fae |
return nlh;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int __dcb_get_attribute(struct dcb *dcb, int command,
|
|
Packit Bot |
867fae |
const char *dev, int attr,
|
|
Packit Bot |
867fae |
void **payload_p, __u16 *payload_len_p,
|
|
Packit Bot |
867fae |
int (*get_attribute_cb)(const struct nlmsghdr *nlh,
|
|
Packit Bot |
867fae |
void *data))
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_get_attribute ga;
|
|
Packit Bot |
867fae |
struct nlmsghdr *nlh;
|
|
Packit Bot |
867fae |
int ret;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
nlh = dcb_prepare(dcb, dev, RTM_GETDCB, command);
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
ga = (struct dcb_get_attribute) {
|
|
Packit Bot |
867fae |
.dcb = dcb,
|
|
Packit Bot |
867fae |
.attr = attr,
|
|
Packit Bot |
867fae |
.payload = NULL,
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
ret = dcb_talk(dcb, nlh, get_attribute_cb, &ga);
|
|
Packit Bot |
867fae |
if (ret) {
|
|
Packit Bot |
867fae |
perror("Attribute read");
|
|
Packit Bot |
867fae |
return ret;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
if (ga.payload == NULL) {
|
|
Packit Bot |
867fae |
perror("Attribute not found");
|
|
Packit Bot |
867fae |
return -ENOENT;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
*payload_p = ga.payload;
|
|
Packit Bot |
867fae |
*payload_len_p = ga.payload_len;
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int dcb_get_attribute_va(struct dcb *dcb, const char *dev, int attr,
|
|
Packit Bot |
867fae |
void **payload_p, __u16 *payload_len_p)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
return __dcb_get_attribute(dcb, DCB_CMD_IEEE_GET, dev, attr,
|
|
Packit Bot |
867fae |
payload_p, payload_len_p,
|
|
Packit Bot |
867fae |
dcb_get_attribute_cb);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int dcb_get_attribute_bare(struct dcb *dcb, int cmd, const char *dev, int attr,
|
|
Packit Bot |
867fae |
void **payload_p, __u16 *payload_len_p)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
return __dcb_get_attribute(dcb, cmd, dev, attr,
|
|
Packit Bot |
867fae |
payload_p, payload_len_p,
|
|
Packit Bot |
867fae |
dcb_get_attribute_bare_cb);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int dcb_get_attribute(struct dcb *dcb, const char *dev, int attr, void *data, size_t data_len)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
__u16 payload_len;
|
|
Packit Bot |
867fae |
void *payload;
|
|
Packit Bot |
867fae |
int ret;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
ret = dcb_get_attribute_va(dcb, dev, attr, &payload, &payload_len);
|
|
Packit Bot |
867fae |
if (ret)
|
|
Packit Bot |
867fae |
return ret;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (payload_len != data_len) {
|
|
Packit Bot |
867fae |
fprintf(stderr, "Wrong len %d, expected %zd\n", payload_len, data_len);
|
|
Packit Bot |
867fae |
return -EINVAL;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
memcpy(data, payload, data_len);
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int __dcb_set_attribute(struct dcb *dcb, int command, const char *dev,
|
|
Packit Bot |
867fae |
int (*cb)(struct dcb *, struct nlmsghdr *, void *),
|
|
Packit Bot |
867fae |
void *data, int response_attr)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_set_attribute_response resp = {
|
|
Packit Bot |
867fae |
.response_attr = response_attr,
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
struct nlmsghdr *nlh;
|
|
Packit Bot |
867fae |
int ret;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
nlh = dcb_prepare(dcb, dev, RTM_SETDCB, command);
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
ret = cb(dcb, nlh, data);
|
|
Packit Bot |
867fae |
if (ret)
|
|
Packit Bot |
867fae |
return ret;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
ret = dcb_talk(dcb, nlh, dcb_set_attribute_cb, &resp);
|
|
Packit Bot |
867fae |
if (ret) {
|
|
Packit Bot |
867fae |
perror("Attribute write");
|
|
Packit Bot |
867fae |
return ret;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
struct dcb_set_attribute_ieee_cb {
|
|
Packit Bot |
867fae |
int (*cb)(struct dcb *dcb, struct nlmsghdr *nlh, void *data);
|
|
Packit Bot |
867fae |
void *data;
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_set_attribute_ieee_cb(struct dcb *dcb, struct nlmsghdr *nlh, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_set_attribute_ieee_cb *ieee_data = data;
|
|
Packit Bot |
867fae |
struct nlattr *nest;
|
|
Packit Bot |
867fae |
int ret;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
nest = mnl_attr_nest_start(nlh, DCB_ATTR_IEEE);
|
|
Packit Bot |
867fae |
ret = ieee_data->cb(dcb, nlh, ieee_data->data);
|
|
Packit Bot |
867fae |
if (ret)
|
|
Packit Bot |
867fae |
return ret;
|
|
Packit Bot |
867fae |
mnl_attr_nest_end(nlh, nest);
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int dcb_set_attribute_va(struct dcb *dcb, int command, const char *dev,
|
|
Packit Bot |
867fae |
int (*cb)(struct dcb *dcb, struct nlmsghdr *nlh, void *data),
|
|
Packit Bot |
867fae |
void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_set_attribute_ieee_cb ieee_data = {
|
|
Packit Bot |
867fae |
.cb = cb,
|
|
Packit Bot |
867fae |
.data = data,
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return __dcb_set_attribute(dcb, command, dev,
|
|
Packit Bot |
867fae |
&dcb_set_attribute_ieee_cb, &ieee_data,
|
|
Packit Bot |
867fae |
DCB_ATTR_IEEE);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
struct dcb_set_attribute {
|
|
Packit Bot |
867fae |
int attr;
|
|
Packit Bot |
867fae |
const void *data;
|
|
Packit Bot |
867fae |
size_t data_len;
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_set_attribute_put(struct dcb *dcb, struct nlmsghdr *nlh, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_set_attribute *dsa = data;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
mnl_attr_put(nlh, dsa->attr, dsa->data_len, dsa->data);
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int dcb_set_attribute(struct dcb *dcb, const char *dev, int attr, const void *data, size_t data_len)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_set_attribute dsa = {
|
|
Packit Bot |
867fae |
.attr = attr,
|
|
Packit Bot |
867fae |
.data = data,
|
|
Packit Bot |
867fae |
.data_len = data_len,
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return dcb_set_attribute_va(dcb, DCB_CMD_IEEE_SET, dev,
|
|
Packit Bot |
867fae |
&dcb_set_attribute_put, &dsa;;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int dcb_set_attribute_bare(struct dcb *dcb, int command, const char *dev,
|
|
Packit Bot |
867fae |
int attr, const void *data, size_t data_len,
|
|
Packit Bot |
867fae |
int response_attr)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb_set_attribute dsa = {
|
|
Packit Bot |
867fae |
.attr = attr,
|
|
Packit Bot |
867fae |
.data = data,
|
|
Packit Bot |
867fae |
.data_len = data_len,
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return __dcb_set_attribute(dcb, command, dev,
|
|
Packit Bot |
867fae |
&dcb_set_attribute_put, &dsa, response_attr);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
void dcb_print_array_u8(const __u8 *array, size_t size)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
SPRINT_BUF(b);
|
|
Packit Bot |
867fae |
size_t i;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
for (i = 0; i < size; i++) {
|
|
Packit Bot |
867fae |
snprintf(b, sizeof(b), "%zd:%%d ", i);
|
|
Packit Bot |
867fae |
print_uint(PRINT_ANY, NULL, b, array[i]);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
void dcb_print_array_u64(const __u64 *array, size_t size)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
SPRINT_BUF(b);
|
|
Packit Bot |
867fae |
size_t i;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
for (i = 0; i < size; i++) {
|
|
Packit Bot |
867fae |
snprintf(b, sizeof(b), "%zd:%%" PRIu64 " ", i);
|
|
Packit Bot |
867fae |
print_u64(PRINT_ANY, NULL, b, array[i]);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
void dcb_print_array_on_off(const __u8 *array, size_t size)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
SPRINT_BUF(b);
|
|
Packit Bot |
867fae |
size_t i;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
for (i = 0; i < size; i++) {
|
|
Packit Bot |
867fae |
snprintf(b, sizeof(b), "%zd:%%s ", i);
|
|
Packit Bot |
867fae |
print_on_off(PRINT_ANY, NULL, b, array[i]);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
void dcb_print_array_kw(const __u8 *array, size_t array_size,
|
|
Packit Bot |
867fae |
const char *const kw[], size_t kw_size)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
SPRINT_BUF(b);
|
|
Packit Bot |
867fae |
size_t i;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
for (i = 0; i < array_size; i++) {
|
|
Packit Bot |
867fae |
__u8 emt = array[i];
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
snprintf(b, sizeof(b), "%zd:%%s ", i);
|
|
Packit Bot |
867fae |
if (emt < kw_size && kw[emt])
|
|
Packit Bot |
867fae |
print_string(PRINT_ANY, NULL, b, kw[emt]);
|
|
Packit Bot |
867fae |
else
|
|
Packit Bot |
867fae |
print_string(PRINT_ANY, NULL, b, "???");
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
void dcb_print_named_array(const char *json_name, const char *fp_name,
|
|
Packit Bot |
867fae |
const __u8 *array, size_t size,
|
|
Packit Bot |
867fae |
void (*print_array)(const __u8 *, size_t))
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
open_json_array(PRINT_JSON, json_name);
|
|
Packit Bot |
867fae |
print_string(PRINT_FP, NULL, "%s ", fp_name);
|
|
Packit Bot |
867fae |
print_array(array, size);
|
|
Packit Bot |
867fae |
close_json_array(PRINT_JSON, json_name);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int dcb_parse_mapping(const char *what_key, __u32 key, __u32 max_key,
|
|
Packit Bot |
867fae |
const char *what_value, __u64 value, __u64 max_value,
|
|
Packit Bot |
867fae |
void (*set_array)(__u32 index, __u64 value, void *data),
|
|
Packit Bot |
867fae |
void *set_array_data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
bool is_all = key == (__u32) -1;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (!is_all && key > max_key) {
|
|
Packit Bot |
867fae |
fprintf(stderr, "In %s:%s mapping, %s is expected to be 0..%d\n",
|
|
Packit Bot |
867fae |
what_key, what_value, what_key, max_key);
|
|
Packit Bot |
867fae |
return -EINVAL;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (value > max_value) {
|
|
Packit Bot |
867fae |
fprintf(stderr, "In %s:%s mapping, %s is expected to be 0..%llu\n",
|
|
Packit Bot |
867fae |
what_key, what_value, what_value, max_value);
|
|
Packit Bot |
867fae |
return -EINVAL;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (is_all) {
|
|
Packit Bot |
867fae |
for (key = 0; key <= max_key; key++)
|
|
Packit Bot |
867fae |
set_array(key, value, set_array_data);
|
|
Packit Bot |
867fae |
} else {
|
|
Packit Bot |
867fae |
set_array(key, value, set_array_data);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
void dcb_set_u8(__u32 key, __u64 value, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
__u8 *array = data;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
array[key] = value;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
void dcb_set_u32(__u32 key, __u64 value, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
__u32 *array = data;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
array[key] = value;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
void dcb_set_u64(__u32 key, __u64 value, void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
__u64 *array = data;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
array[key] = value;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int dcb_cmd_parse_dev(struct dcb *dcb, int argc, char **argv,
|
|
Packit Bot |
867fae |
int (*and_then)(struct dcb *dcb, const char *dev,
|
|
Packit Bot |
867fae |
int argc, char **argv),
|
|
Packit Bot |
867fae |
void (*help)(void))
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
const char *dev;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (!argc || matches(*argv, "help") == 0) {
|
|
Packit Bot |
867fae |
help();
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
} else if (matches(*argv, "dev") == 0) {
|
|
Packit Bot |
867fae |
NEXT_ARG();
|
|
Packit Bot |
867fae |
dev = *argv;
|
|
Packit Bot |
867fae |
if (check_ifname(dev)) {
|
|
Packit Bot |
867fae |
invarg("not a valid ifname", *argv);
|
|
Packit Bot |
867fae |
return -EINVAL;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
NEXT_ARG_FWD();
|
|
Packit Bot |
867fae |
return and_then(dcb, dev, argc, argv);
|
|
Packit Bot |
867fae |
} else {
|
|
Packit Bot |
867fae |
fprintf(stderr, "Expected `dev DEV', not `%s'", *argv);
|
|
Packit Bot |
867fae |
help();
|
|
Packit Bot |
867fae |
return -EINVAL;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static void dcb_help(void)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
fprintf(stderr,
|
|
Packit Bot |
867fae |
"Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n"
|
|
Packit Bot |
867fae |
" dcb [ -f | --force ] { -b | --batch } filename [ -n | --netns ] netnsname\n"
|
|
Packit Bot |
867fae |
"where OBJECT := { app | buffer | dcbx | ets | maxrate | pfc }\n"
|
|
Packit Bot |
867fae |
" OPTIONS := [ -V | --Version | -i | --iec | -j | --json\n"
|
|
Packit Bot |
867fae |
" | -N | --Numeric | -p | --pretty\n"
|
|
Packit Bot |
867fae |
" | -s | --statistics | -v | --verbose]\n");
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_cmd(struct dcb *dcb, int argc, char **argv)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
if (!argc || matches(*argv, "help") == 0) {
|
|
Packit Bot |
867fae |
dcb_help();
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
} else if (matches(*argv, "app") == 0) {
|
|
Packit Bot |
867fae |
return dcb_cmd_app(dcb, argc - 1, argv + 1);
|
|
Packit Bot |
867fae |
} else if (matches(*argv, "buffer") == 0) {
|
|
Packit Bot |
867fae |
return dcb_cmd_buffer(dcb, argc - 1, argv + 1);
|
|
Packit Bot |
867fae |
} else if (matches(*argv, "dcbx") == 0) {
|
|
Packit Bot |
867fae |
return dcb_cmd_dcbx(dcb, argc - 1, argv + 1);
|
|
Packit Bot |
867fae |
} else if (matches(*argv, "ets") == 0) {
|
|
Packit Bot |
867fae |
return dcb_cmd_ets(dcb, argc - 1, argv + 1);
|
|
Packit Bot |
867fae |
} else if (matches(*argv, "maxrate") == 0) {
|
|
Packit Bot |
867fae |
return dcb_cmd_maxrate(dcb, argc - 1, argv + 1);
|
|
Packit Bot |
867fae |
} else if (matches(*argv, "pfc") == 0) {
|
|
Packit Bot |
867fae |
return dcb_cmd_pfc(dcb, argc - 1, argv + 1);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
fprintf(stderr, "Object \"%s\" is unknown\n", *argv);
|
|
Packit Bot |
867fae |
return -ENOENT;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_batch_cmd(int argc, char *argv[], void *data)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
struct dcb *dcb = data;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return dcb_cmd(dcb, argc, argv);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
static int dcb_batch(struct dcb *dcb, const char *name, bool force)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
return do_batch(name, force, dcb_batch_cmd, dcb);
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
int main(int argc, char **argv)
|
|
Packit Bot |
867fae |
{
|
|
Packit Bot |
867fae |
static const struct option long_options[] = {
|
|
Packit Bot |
867fae |
{ "Version", no_argument, NULL, 'V' },
|
|
Packit Bot |
867fae |
{ "force", no_argument, NULL, 'f' },
|
|
Packit Bot |
867fae |
{ "batch", required_argument, NULL, 'b' },
|
|
Packit Bot |
867fae |
{ "iec", no_argument, NULL, 'i' },
|
|
Packit Bot |
867fae |
{ "json", no_argument, NULL, 'j' },
|
|
Packit Bot |
867fae |
{ "Numeric", no_argument, NULL, 'N' },
|
|
Packit Bot |
867fae |
{ "pretty", no_argument, NULL, 'p' },
|
|
Packit Bot |
867fae |
{ "statistics", no_argument, NULL, 's' },
|
|
Packit Bot |
867fae |
{ "netns", required_argument, NULL, 'n' },
|
|
Packit Bot |
867fae |
{ "help", no_argument, NULL, 'h' },
|
|
Packit Bot |
867fae |
{ NULL, 0, NULL, 0 }
|
|
Packit Bot |
867fae |
};
|
|
Packit Bot |
867fae |
const char *batch_file = NULL;
|
|
Packit Bot |
867fae |
bool force = false;
|
|
Packit Bot |
867fae |
struct dcb *dcb;
|
|
Packit Bot |
867fae |
int opt;
|
|
Packit Bot |
867fae |
int err;
|
|
Packit Bot |
867fae |
int ret;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
dcb = dcb_alloc();
|
|
Packit Bot |
867fae |
if (!dcb) {
|
|
Packit Bot |
867fae |
fprintf(stderr, "Failed to allocate memory for dcb\n");
|
|
Packit Bot |
867fae |
return EXIT_FAILURE;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
while ((opt = getopt_long(argc, argv, "b:fhijn:psvNV",
|
|
Packit Bot |
867fae |
long_options, NULL)) >= 0) {
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
switch (opt) {
|
|
Packit Bot |
867fae |
case 'V':
|
|
Packit Bot |
867fae |
printf("dcb utility, iproute2-%s\n", version);
|
|
Packit Bot |
867fae |
ret = EXIT_SUCCESS;
|
|
Packit Bot |
867fae |
goto dcb_free;
|
|
Packit Bot |
867fae |
case 'f':
|
|
Packit Bot |
867fae |
force = true;
|
|
Packit Bot |
867fae |
break;
|
|
Packit Bot |
867fae |
case 'b':
|
|
Packit Bot |
867fae |
batch_file = optarg;
|
|
Packit Bot |
867fae |
break;
|
|
Packit Bot |
867fae |
case 'j':
|
|
Packit Bot |
867fae |
dcb->json_output = true;
|
|
Packit Bot |
867fae |
break;
|
|
Packit Bot |
867fae |
case 'N':
|
|
Packit Bot |
867fae |
dcb->numeric = true;
|
|
Packit Bot |
867fae |
break;
|
|
Packit Bot |
867fae |
case 'p':
|
|
Packit Bot |
867fae |
pretty = true;
|
|
Packit Bot |
867fae |
break;
|
|
Packit Bot |
867fae |
case 's':
|
|
Packit Bot |
867fae |
dcb->stats = true;
|
|
Packit Bot |
867fae |
break;
|
|
Packit Bot |
867fae |
case 'n':
|
|
Packit Bot |
867fae |
if (netns_switch(optarg)) {
|
|
Packit Bot |
867fae |
ret = EXIT_FAILURE;
|
|
Packit Bot |
867fae |
goto dcb_free;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
break;
|
|
Packit Bot |
867fae |
case 'i':
|
|
Packit Bot |
867fae |
dcb->use_iec = true;
|
|
Packit Bot |
867fae |
break;
|
|
Packit Bot |
867fae |
case 'h':
|
|
Packit Bot |
867fae |
dcb_help();
|
|
Packit Bot |
867fae |
return 0;
|
|
Packit Bot |
867fae |
default:
|
|
Packit Bot |
867fae |
fprintf(stderr, "Unknown option.\n");
|
|
Packit Bot |
867fae |
dcb_help();
|
|
Packit Bot |
867fae |
ret = EXIT_FAILURE;
|
|
Packit Bot |
867fae |
goto dcb_free;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
argc -= optind;
|
|
Packit Bot |
867fae |
argv += optind;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
err = dcb_init(dcb);
|
|
Packit Bot |
867fae |
if (err) {
|
|
Packit Bot |
867fae |
ret = EXIT_FAILURE;
|
|
Packit Bot |
867fae |
goto dcb_free;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (batch_file)
|
|
Packit Bot |
867fae |
err = dcb_batch(dcb, batch_file, force);
|
|
Packit Bot |
867fae |
else
|
|
Packit Bot |
867fae |
err = dcb_cmd(dcb, argc, argv);
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
if (err) {
|
|
Packit Bot |
867fae |
ret = EXIT_FAILURE;
|
|
Packit Bot |
867fae |
goto dcb_fini;
|
|
Packit Bot |
867fae |
}
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
ret = EXIT_SUCCESS;
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
dcb_fini:
|
|
Packit Bot |
867fae |
dcb_fini(dcb);
|
|
Packit Bot |
867fae |
dcb_free:
|
|
Packit Bot |
867fae |
dcb_free(dcb);
|
|
Packit Bot |
867fae |
|
|
Packit Bot |
867fae |
return ret;
|
|
Packit Bot |
867fae |
}
|