mirror of
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git
synced 2026-01-26 14:13:24 +00:00
Merge git://git.kernel.org/pub/scm/network/iproute2/iproute2-next
This commit is contained in:
commit
5e72cc73eb
@ -33,7 +33,7 @@ static void usage(void)
|
||||
fprintf(stderr,
|
||||
"Usage: bridge vni { add | del } vni VNI\n"
|
||||
" [ { group | remote } IP_ADDRESS ]\n"
|
||||
" [ dev DEV ]\n"
|
||||
" [ dev DEV ]\n"
|
||||
" bridge vni { show }\n"
|
||||
"\n"
|
||||
"Where: VNI := 0-16777215\n"
|
||||
|
||||
@ -8,7 +8,8 @@ DCBOBJ = dcb.o \
|
||||
dcb_ets.o \
|
||||
dcb_maxrate.o \
|
||||
dcb_pfc.o \
|
||||
dcb_apptrust.o
|
||||
dcb_apptrust.o \
|
||||
dcb_rewr.o
|
||||
TARGETS += dcb
|
||||
LDLIBS += -lm
|
||||
|
||||
|
||||
@ -470,7 +470,7 @@ static void dcb_help(void)
|
||||
fprintf(stderr,
|
||||
"Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n"
|
||||
" dcb [ -f | --force ] { -b | --batch } filename [ -n | --netns ] netnsname\n"
|
||||
"where OBJECT := { app | apptrust | buffer | dcbx | ets | maxrate | pfc }\n"
|
||||
"where OBJECT := { app | apptrust | buffer | dcbx | ets | maxrate | pfc | rewr }\n"
|
||||
" OPTIONS := [ -V | --Version | -i | --iec | -j | --json\n"
|
||||
" | -N | --Numeric | -p | --pretty\n"
|
||||
" | -s | --statistics | -v | --verbose]\n");
|
||||
@ -485,6 +485,8 @@ static int dcb_cmd(struct dcb *dcb, int argc, char **argv)
|
||||
return dcb_cmd_app(dcb, argc - 1, argv + 1);
|
||||
} else if (strcmp(*argv, "apptrust") == 0) {
|
||||
return dcb_cmd_apptrust(dcb, argc - 1, argv + 1);
|
||||
} else if (strcmp(*argv, "rewr") == 0) {
|
||||
return dcb_cmd_rewr(dcb, argc - 1, argv + 1);
|
||||
} else if (matches(*argv, "buffer") == 0) {
|
||||
return dcb_cmd_buffer(dcb, argc - 1, argv + 1);
|
||||
} else if (matches(*argv, "dcbx") == 0) {
|
||||
|
||||
54
dcb/dcb.h
54
dcb/dcb.h
@ -54,13 +54,67 @@ void dcb_print_array_on_off(const __u8 *array, size_t size);
|
||||
void dcb_print_array_kw(const __u8 *array, size_t array_size,
|
||||
const char *const kw[], size_t kw_size);
|
||||
|
||||
/* dcp_rewr.c */
|
||||
|
||||
int dcb_cmd_rewr(struct dcb *dcb, int argc, char **argv);
|
||||
|
||||
/* dcb_app.c */
|
||||
|
||||
struct dcb_app_table {
|
||||
struct dcb_app *apps;
|
||||
size_t n_apps;
|
||||
int attr;
|
||||
};
|
||||
|
||||
struct dcb_app_parse_mapping {
|
||||
__u8 selector;
|
||||
struct dcb_app_table *tab;
|
||||
int err;
|
||||
};
|
||||
|
||||
#define DCB_APP_PCP_MAX 15
|
||||
#define DCB_APP_DSCP_MAX 63
|
||||
|
||||
int dcb_cmd_app(struct dcb *dcb, int argc, char **argv);
|
||||
|
||||
int dcb_app_get(struct dcb *dcb, const char *dev, struct dcb_app_table *tab);
|
||||
int dcb_app_add_del(struct dcb *dcb, const char *dev, int command,
|
||||
const struct dcb_app_table *tab,
|
||||
bool (*filter)(const struct dcb_app *));
|
||||
|
||||
bool dcb_app_is_dscp(const struct dcb_app *app);
|
||||
bool dcb_app_is_pcp(const struct dcb_app *app);
|
||||
|
||||
int dcb_app_print_pid_dscp(__u16 protocol);
|
||||
int dcb_app_print_pid_pcp(__u16 protocol);
|
||||
int dcb_app_print_pid_dec(__u16 protocol);
|
||||
void dcb_app_print_filtered(const struct dcb_app_table *tab,
|
||||
bool (*filter)(const struct dcb_app *),
|
||||
void (*print_pid_prio)(int (*print_pid)(__u16),
|
||||
const struct dcb_app *),
|
||||
int (*print_pid)(__u16 protocol),
|
||||
const char *json_name,
|
||||
const char *fp_name);
|
||||
|
||||
enum ieee_attrs_app dcb_app_attr_type_get(__u8 selector);
|
||||
bool dcb_app_attr_type_validate(enum ieee_attrs_app type);
|
||||
bool dcb_app_selector_validate(enum ieee_attrs_app type, __u8 selector);
|
||||
|
||||
int dcb_app_table_push(struct dcb_app_table *tab, struct dcb_app *app);
|
||||
int dcb_app_table_copy(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b);
|
||||
void dcb_app_table_sort(struct dcb_app_table *tab);
|
||||
void dcb_app_table_fini(struct dcb_app_table *tab);
|
||||
void dcb_app_table_remove_existing(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b);
|
||||
void dcb_app_table_remove_replaced(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b,
|
||||
bool (*key_eq)(const struct dcb_app *aa,
|
||||
const struct dcb_app *ab));
|
||||
|
||||
int dcb_app_parse_pcp(__u32 *key, const char *arg);
|
||||
int dcb_app_parse_dscp(__u32 *key, const char *arg);
|
||||
|
||||
/* dcb_apptrust.c */
|
||||
|
||||
int dcb_cmd_apptrust(struct dcb *dcb, int argc, char **argv);
|
||||
|
||||
154
dcb/dcb_app.c
154
dcb/dcb_app.c
@ -10,8 +10,6 @@
|
||||
#include "utils.h"
|
||||
#include "rt_names.h"
|
||||
|
||||
#define DCB_APP_PCP_MAX 15
|
||||
|
||||
static const char *const pcp_names[DCB_APP_PCP_MAX + 1] = {
|
||||
"0nd", "1nd", "2nd", "3nd", "4nd", "5nd", "6nd", "7nd",
|
||||
"0de", "1de", "2de", "3de", "4de", "5de", "6de", "7de"
|
||||
@ -68,11 +66,6 @@ static void dcb_app_help(void)
|
||||
dcb_app_help_add();
|
||||
}
|
||||
|
||||
struct dcb_app_table {
|
||||
struct dcb_app *apps;
|
||||
size_t n_apps;
|
||||
};
|
||||
|
||||
enum ieee_attrs_app dcb_app_attr_type_get(__u8 selector)
|
||||
{
|
||||
switch (selector) {
|
||||
@ -105,12 +98,12 @@ bool dcb_app_selector_validate(enum ieee_attrs_app type, __u8 selector)
|
||||
return dcb_app_attr_type_get(selector) == type;
|
||||
}
|
||||
|
||||
static void dcb_app_table_fini(struct dcb_app_table *tab)
|
||||
void dcb_app_table_fini(struct dcb_app_table *tab)
|
||||
{
|
||||
free(tab->apps);
|
||||
}
|
||||
|
||||
static int dcb_app_table_push(struct dcb_app_table *tab, struct dcb_app *app)
|
||||
int dcb_app_table_push(struct dcb_app_table *tab, struct dcb_app *app)
|
||||
{
|
||||
struct dcb_app *apps = realloc(tab->apps, (tab->n_apps + 1) * sizeof(*tab->apps));
|
||||
|
||||
@ -124,8 +117,8 @@ static int dcb_app_table_push(struct dcb_app_table *tab, struct dcb_app *app)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dcb_app_table_remove_existing(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b)
|
||||
void dcb_app_table_remove_existing(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b)
|
||||
{
|
||||
size_t ia, ja;
|
||||
size_t ib;
|
||||
@ -152,8 +145,16 @@ static void dcb_app_table_remove_existing(struct dcb_app_table *a,
|
||||
a->n_apps = ja;
|
||||
}
|
||||
|
||||
static void dcb_app_table_remove_replaced(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b)
|
||||
static bool dcb_app_pid_eq(const struct dcb_app *aa, const struct dcb_app *ab)
|
||||
{
|
||||
return aa->selector == ab->selector &&
|
||||
aa->protocol == ab->protocol;
|
||||
}
|
||||
|
||||
void dcb_app_table_remove_replaced(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b,
|
||||
bool (*key_eq)(const struct dcb_app *aa,
|
||||
const struct dcb_app *ab))
|
||||
{
|
||||
size_t ia, ja;
|
||||
size_t ib;
|
||||
@ -166,13 +167,13 @@ static void dcb_app_table_remove_replaced(struct dcb_app_table *a,
|
||||
for (ib = 0; ib < b->n_apps; ib++) {
|
||||
const struct dcb_app *ab = &b->apps[ib];
|
||||
|
||||
if (aa->selector == ab->selector &&
|
||||
aa->protocol == ab->protocol)
|
||||
if (key_eq(aa, ab))
|
||||
present = true;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (aa->priority == ab->priority) {
|
||||
if (aa->protocol == ab->protocol &&
|
||||
aa->priority == ab->priority) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@ -189,8 +190,8 @@ static void dcb_app_table_remove_replaced(struct dcb_app_table *a,
|
||||
a->n_apps = ja;
|
||||
}
|
||||
|
||||
static int dcb_app_table_copy(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b)
|
||||
int dcb_app_table_copy(struct dcb_app_table *a,
|
||||
const struct dcb_app_table *b)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
@ -217,17 +218,11 @@ static int dcb_app_cmp_cb(const void *a, const void *b)
|
||||
return dcb_app_cmp(a, b);
|
||||
}
|
||||
|
||||
static void dcb_app_table_sort(struct dcb_app_table *tab)
|
||||
void dcb_app_table_sort(struct dcb_app_table *tab)
|
||||
{
|
||||
qsort(tab->apps, tab->n_apps, sizeof(*tab->apps), dcb_app_cmp_cb);
|
||||
}
|
||||
|
||||
struct dcb_app_parse_mapping {
|
||||
__u8 selector;
|
||||
struct dcb_app_table *tab;
|
||||
int err;
|
||||
};
|
||||
|
||||
static void dcb_app_parse_mapping_cb(__u32 key, __u64 value, void *data)
|
||||
{
|
||||
struct dcb_app_parse_mapping *pm = data;
|
||||
@ -260,7 +255,7 @@ static int dcb_app_parse_mapping_ethtype_prio(__u32 key, char *value, void *data
|
||||
dcb_app_parse_mapping_cb, data);
|
||||
}
|
||||
|
||||
static int dcb_app_parse_pcp(__u32 *key, const char *arg)
|
||||
int dcb_app_parse_pcp(__u32 *key, const char *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -286,7 +281,7 @@ static int dcb_app_parse_mapping_pcp_prio(__u32 key, char *value, void *data)
|
||||
dcb_app_parse_mapping_cb, data);
|
||||
}
|
||||
|
||||
static int dcb_app_parse_dscp(__u32 *key, const char *arg)
|
||||
int dcb_app_parse_dscp(__u32 *key, const char *arg)
|
||||
{
|
||||
if (parse_mapping_num_all(key, arg) == 0)
|
||||
return 0;
|
||||
@ -311,7 +306,7 @@ static int dcb_app_parse_mapping_dscp_prio(__u32 key, char *value, void *data)
|
||||
if (get_u8(&prio, value, 0))
|
||||
return -EINVAL;
|
||||
|
||||
return dcb_parse_mapping("DSCP", key, 63,
|
||||
return dcb_parse_mapping("DSCP", key, DCB_APP_DSCP_MAX,
|
||||
"PRIO", prio, IEEE_8021QAZ_MAX_TCS - 1,
|
||||
dcb_app_parse_mapping_cb, data);
|
||||
}
|
||||
@ -377,12 +372,12 @@ static bool dcb_app_is_default(const struct dcb_app *app)
|
||||
app->protocol == 0;
|
||||
}
|
||||
|
||||
static bool dcb_app_is_dscp(const struct dcb_app *app)
|
||||
bool dcb_app_is_dscp(const struct dcb_app *app)
|
||||
{
|
||||
return app->selector == IEEE_8021QAZ_APP_SEL_DSCP;
|
||||
}
|
||||
|
||||
static bool dcb_app_is_pcp(const struct dcb_app *app)
|
||||
bool dcb_app_is_pcp(const struct dcb_app *app)
|
||||
{
|
||||
return app->selector == DCB_APP_SEL_PCP;
|
||||
}
|
||||
@ -402,40 +397,42 @@ static bool dcb_app_is_port(const struct dcb_app *app)
|
||||
return app->selector == IEEE_8021QAZ_APP_SEL_ANY;
|
||||
}
|
||||
|
||||
static int dcb_app_print_key_dec(__u16 protocol)
|
||||
int dcb_app_print_pid_dec(__u16 protocol)
|
||||
{
|
||||
return print_uint(PRINT_ANY, NULL, "%d:", protocol);
|
||||
return print_uint(PRINT_ANY, NULL, "%u", protocol);
|
||||
}
|
||||
|
||||
static int dcb_app_print_key_hex(__u16 protocol)
|
||||
static int dcb_app_print_pid_hex(__u16 protocol)
|
||||
{
|
||||
return print_uint(PRINT_ANY, NULL, "%x:", protocol);
|
||||
return print_uint(PRINT_ANY, NULL, "%x", protocol);
|
||||
}
|
||||
|
||||
static int dcb_app_print_key_dscp(__u16 protocol)
|
||||
int dcb_app_print_pid_dscp(__u16 protocol)
|
||||
{
|
||||
const char *name = rtnl_dsfield_get_name(protocol << 2);
|
||||
|
||||
|
||||
if (!is_json_context() && name != NULL)
|
||||
return print_string(PRINT_FP, NULL, "%s:", name);
|
||||
return print_uint(PRINT_ANY, NULL, "%d:", protocol);
|
||||
return print_string(PRINT_FP, NULL, "%s", name);
|
||||
return print_uint(PRINT_ANY, NULL, "%u", protocol);
|
||||
}
|
||||
|
||||
static int dcb_app_print_key_pcp(__u16 protocol)
|
||||
int dcb_app_print_pid_pcp(__u16 protocol)
|
||||
{
|
||||
/* Print in numerical form, if protocol value is out-of-range */
|
||||
if (protocol > DCB_APP_PCP_MAX)
|
||||
return print_uint(PRINT_ANY, NULL, "%d:", protocol);
|
||||
return print_uint(PRINT_ANY, NULL, "%u", protocol);
|
||||
|
||||
return print_string(PRINT_ANY, NULL, "%s:", pcp_names[protocol]);
|
||||
return print_string(PRINT_ANY, NULL, "%s", pcp_names[protocol]);
|
||||
}
|
||||
|
||||
static void dcb_app_print_filtered(const struct dcb_app_table *tab,
|
||||
bool (*filter)(const struct dcb_app *),
|
||||
int (*print_key)(__u16 protocol),
|
||||
const char *json_name,
|
||||
const char *fp_name)
|
||||
void dcb_app_print_filtered(const struct dcb_app_table *tab,
|
||||
bool (*filter)(const struct dcb_app *),
|
||||
void (*print_pid_prio)(int (*print_pid)(__u16),
|
||||
const struct dcb_app *),
|
||||
int (*print_pid)(__u16 protocol),
|
||||
const char *json_name,
|
||||
const char *fp_name)
|
||||
{
|
||||
bool first = true;
|
||||
size_t i;
|
||||
@ -452,8 +449,8 @@ static void dcb_app_print_filtered(const struct dcb_app_table *tab,
|
||||
}
|
||||
|
||||
open_json_array(PRINT_JSON, NULL);
|
||||
print_key(app->protocol);
|
||||
print_uint(PRINT_ANY, NULL, "%d ", app->priority);
|
||||
print_pid_prio(print_pid, app);
|
||||
print_string(PRINT_ANY, NULL, "%s", " ");
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
}
|
||||
|
||||
@ -463,9 +460,17 @@ static void dcb_app_print_filtered(const struct dcb_app_table *tab,
|
||||
}
|
||||
}
|
||||
|
||||
static void dcb_app_print_pid_prio(int (*print_pid)(__u16 protocol),
|
||||
const struct dcb_app *app)
|
||||
{
|
||||
print_pid(app->protocol);
|
||||
print_uint(PRINT_ANY, NULL, ":%u", app->priority);
|
||||
}
|
||||
|
||||
static void dcb_app_print_ethtype_prio(const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_app_print_filtered(tab, dcb_app_is_ethtype, dcb_app_print_key_hex,
|
||||
dcb_app_print_filtered(tab, dcb_app_is_ethtype,
|
||||
dcb_app_print_pid_prio, dcb_app_print_pid_hex,
|
||||
"ethtype_prio", "ethtype-prio");
|
||||
}
|
||||
|
||||
@ -473,8 +478,9 @@ static void dcb_app_print_pcp_prio(const struct dcb *dcb,
|
||||
const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_app_print_filtered(tab, dcb_app_is_pcp,
|
||||
dcb->numeric ? dcb_app_print_key_dec
|
||||
: dcb_app_print_key_pcp,
|
||||
dcb_app_print_pid_prio,
|
||||
dcb->numeric ? dcb_app_print_pid_dec :
|
||||
dcb_app_print_pid_pcp,
|
||||
"pcp_prio", "pcp-prio");
|
||||
}
|
||||
|
||||
@ -482,26 +488,30 @@ static void dcb_app_print_dscp_prio(const struct dcb *dcb,
|
||||
const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_app_print_filtered(tab, dcb_app_is_dscp,
|
||||
dcb->numeric ? dcb_app_print_key_dec
|
||||
: dcb_app_print_key_dscp,
|
||||
dcb_app_print_pid_prio,
|
||||
dcb->numeric ? dcb_app_print_pid_dec :
|
||||
dcb_app_print_pid_dscp,
|
||||
"dscp_prio", "dscp-prio");
|
||||
}
|
||||
|
||||
static void dcb_app_print_stream_port_prio(const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_app_print_filtered(tab, dcb_app_is_stream_port, dcb_app_print_key_dec,
|
||||
dcb_app_print_filtered(tab, dcb_app_is_stream_port,
|
||||
dcb_app_print_pid_prio, dcb_app_print_pid_dec,
|
||||
"stream_port_prio", "stream-port-prio");
|
||||
}
|
||||
|
||||
static void dcb_app_print_dgram_port_prio(const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_app_print_filtered(tab, dcb_app_is_dgram_port, dcb_app_print_key_dec,
|
||||
dcb_app_print_filtered(tab, dcb_app_is_dgram_port,
|
||||
dcb_app_print_pid_prio, dcb_app_print_pid_dec,
|
||||
"dgram_port_prio", "dgram-port-prio");
|
||||
}
|
||||
|
||||
static void dcb_app_print_port_prio(const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_app_print_filtered(tab, dcb_app_is_port, dcb_app_print_key_dec,
|
||||
dcb_app_print_filtered(tab, dcb_app_is_port,
|
||||
dcb_app_print_pid_prio, dcb_app_print_pid_dec,
|
||||
"port_prio", "port-prio");
|
||||
}
|
||||
|
||||
@ -518,7 +528,7 @@ static void dcb_app_print_default_prio(const struct dcb_app_table *tab)
|
||||
print_string(PRINT_FP, NULL, "default-prio ", NULL);
|
||||
first = false;
|
||||
}
|
||||
print_uint(PRINT_ANY, NULL, "%d ", tab->apps[i].priority);
|
||||
print_uint(PRINT_ANY, NULL, "%u ", tab->apps[i].priority);
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
@ -549,13 +559,13 @@ static int dcb_app_get_table_attr_cb(const struct nlattr *attr, void *data)
|
||||
|
||||
if (!dcb_app_attr_type_validate(type)) {
|
||||
fprintf(stderr,
|
||||
"Unknown attribute in DCB_ATTR_IEEE_APP_TABLE: %d\n",
|
||||
"Unknown attribute in DCB_ATTR_IEEE_APP_TABLE: %u\n",
|
||||
type);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
if (mnl_attr_get_payload_len(attr) < sizeof(struct dcb_app)) {
|
||||
fprintf(stderr,
|
||||
"%s payload expected to have size %zd, not %d\n",
|
||||
"%s payload expected to have size %zu, not %u\n",
|
||||
ieee_attrs_app_names[type], sizeof(struct dcb_app),
|
||||
mnl_attr_get_payload_len(attr));
|
||||
return MNL_CB_OK;
|
||||
@ -577,13 +587,13 @@ static int dcb_app_get_table_attr_cb(const struct nlattr *attr, void *data)
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int dcb_app_get(struct dcb *dcb, const char *dev, struct dcb_app_table *tab)
|
||||
int dcb_app_get(struct dcb *dcb, const char *dev, struct dcb_app_table *tab)
|
||||
{
|
||||
uint16_t payload_len;
|
||||
void *payload;
|
||||
int ret;
|
||||
|
||||
ret = dcb_get_attribute_va(dcb, dev, DCB_ATTR_IEEE_APP_TABLE, &payload, &payload_len);
|
||||
ret = dcb_get_attribute_va(dcb, dev, tab->attr, &payload, &payload_len);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
@ -606,7 +616,7 @@ static int dcb_app_add_del_cb(struct dcb *dcb, struct nlmsghdr *nlh, void *data)
|
||||
struct nlattr *nest;
|
||||
size_t i;
|
||||
|
||||
nest = mnl_attr_nest_start(nlh, DCB_ATTR_IEEE_APP_TABLE);
|
||||
nest = mnl_attr_nest_start(nlh, add_del->tab->attr);
|
||||
|
||||
for (i = 0; i < add_del->tab->n_apps; i++) {
|
||||
const struct dcb_app *app = &add_del->tab->apps[i];
|
||||
@ -620,9 +630,9 @@ static int dcb_app_add_del_cb(struct dcb *dcb, struct nlmsghdr *nlh, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dcb_app_add_del(struct dcb *dcb, const char *dev, int command,
|
||||
const struct dcb_app_table *tab,
|
||||
bool (*filter)(const struct dcb_app *))
|
||||
int dcb_app_add_del(struct dcb *dcb, const char *dev, int command,
|
||||
const struct dcb_app_table *tab,
|
||||
bool (*filter)(const struct dcb_app *))
|
||||
{
|
||||
struct dcb_app_add_del add_del = {
|
||||
.tab = tab,
|
||||
@ -715,7 +725,7 @@ static int dcb_cmd_app_parse_add_del(struct dcb *dcb, const char *dev,
|
||||
|
||||
static int dcb_cmd_app_add(struct dcb *dcb, const char *dev, int argc, char **argv)
|
||||
{
|
||||
struct dcb_app_table tab = {};
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_IEEE_APP_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_cmd_app_parse_add_del(dcb, dev, argc, argv, &tab);
|
||||
@ -729,7 +739,7 @@ static int dcb_cmd_app_add(struct dcb *dcb, const char *dev, int argc, char **ar
|
||||
|
||||
static int dcb_cmd_app_del(struct dcb *dcb, const char *dev, int argc, char **argv)
|
||||
{
|
||||
struct dcb_app_table tab = {};
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_IEEE_APP_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_cmd_app_parse_add_del(dcb, dev, argc, argv, &tab);
|
||||
@ -743,7 +753,7 @@ static int dcb_cmd_app_del(struct dcb *dcb, const char *dev, int argc, char **ar
|
||||
|
||||
static int dcb_cmd_app_show(struct dcb *dcb, const char *dev, int argc, char **argv)
|
||||
{
|
||||
struct dcb_app_table tab = {};
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_IEEE_APP_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_app_get(dcb, dev, &tab);
|
||||
@ -795,7 +805,7 @@ out:
|
||||
|
||||
static int dcb_cmd_app_flush(struct dcb *dcb, const char *dev, int argc, char **argv)
|
||||
{
|
||||
struct dcb_app_table tab = {};
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_IEEE_APP_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_app_get(dcb, dev, &tab);
|
||||
@ -848,9 +858,9 @@ out:
|
||||
|
||||
static int dcb_cmd_app_replace(struct dcb *dcb, const char *dev, int argc, char **argv)
|
||||
{
|
||||
struct dcb_app_table orig = {};
|
||||
struct dcb_app_table tab = {};
|
||||
struct dcb_app_table new = {};
|
||||
struct dcb_app_table orig = { .attr = DCB_ATTR_IEEE_APP_TABLE };
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_IEEE_APP_TABLE };
|
||||
struct dcb_app_table new = { .attr = DCB_ATTR_IEEE_APP_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_app_get(dcb, dev, &orig);
|
||||
@ -876,7 +886,7 @@ static int dcb_cmd_app_replace(struct dcb *dcb, const char *dev, int argc, char
|
||||
}
|
||||
|
||||
/* Remove the obsolete entries. */
|
||||
dcb_app_table_remove_replaced(&orig, &tab);
|
||||
dcb_app_table_remove_replaced(&orig, &tab, dcb_app_pid_eq);
|
||||
ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &orig, NULL);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Could not remove replaced APP entries\n");
|
||||
|
||||
363
dcb/dcb_rewr.c
Normal file
363
dcb/dcb_rewr.c
Normal file
@ -0,0 +1,363 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <errno.h>
|
||||
#include <linux/dcbnl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dcb.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void dcb_rewr_help_add(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: dcb rewr { add | del | replace } dev STRING\n"
|
||||
" [ prio-pcp PRIO:PCP ]\n"
|
||||
" [ prio-dscp PRIO:DSCP ]\n"
|
||||
"\n"
|
||||
" where PRIO := { 0 .. 7 }\n"
|
||||
" PCP := { 0(nd/de) .. 7(nd/de) }\n"
|
||||
" DSCP := { 0 .. 63 }\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void dcb_rewr_help_show_flush(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: dcb rewr { show | flush } dev STRING\n"
|
||||
" [ prio-pcp ]\n"
|
||||
" [ prio-dscp ]\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void dcb_rewr_help(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: dcb rewr help\n"
|
||||
"\n"
|
||||
);
|
||||
dcb_rewr_help_show_flush();
|
||||
dcb_rewr_help_add();
|
||||
}
|
||||
|
||||
static void dcb_rewr_parse_mapping_cb(__u32 key, __u64 value, void *data)
|
||||
{
|
||||
struct dcb_app_parse_mapping *pm = data;
|
||||
struct dcb_app app = {
|
||||
.selector = pm->selector,
|
||||
.priority = key,
|
||||
.protocol = value,
|
||||
};
|
||||
|
||||
if (pm->err)
|
||||
return;
|
||||
|
||||
pm->err = dcb_app_table_push(pm->tab, &app);
|
||||
}
|
||||
|
||||
static int dcb_rewr_parse_mapping_prio_pcp(__u32 key, char *value, void *data)
|
||||
{
|
||||
__u32 pcp;
|
||||
|
||||
if (dcb_app_parse_pcp(&pcp, value))
|
||||
return -EINVAL;
|
||||
|
||||
return dcb_parse_mapping("PRIO", key, IEEE_8021QAZ_MAX_TCS - 1,
|
||||
"PCP", pcp, DCB_APP_PCP_MAX,
|
||||
dcb_rewr_parse_mapping_cb, data);
|
||||
}
|
||||
|
||||
static int dcb_rewr_parse_mapping_prio_dscp(__u32 key, char *value, void *data)
|
||||
{
|
||||
__u32 dscp;
|
||||
|
||||
if (dcb_app_parse_dscp(&dscp, value))
|
||||
return -EINVAL;
|
||||
|
||||
return dcb_parse_mapping("PRIO", key, IEEE_8021QAZ_MAX_TCS - 1,
|
||||
"DSCP", dscp, DCB_APP_DSCP_MAX,
|
||||
dcb_rewr_parse_mapping_cb, data);
|
||||
}
|
||||
|
||||
static void dcb_rewr_print_prio_pid(int (*print_pid)(__u16 protocol),
|
||||
const struct dcb_app *app)
|
||||
{
|
||||
print_uint(PRINT_ANY, NULL, "%u:", app->priority);
|
||||
print_pid(app->protocol);
|
||||
}
|
||||
|
||||
static void dcb_rewr_print_prio_pcp(const struct dcb *dcb,
|
||||
const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_app_print_filtered(tab, dcb_app_is_pcp,
|
||||
dcb_rewr_print_prio_pid,
|
||||
dcb->numeric ? dcb_app_print_pid_dec :
|
||||
dcb_app_print_pid_pcp,
|
||||
"prio_pcp", "prio-pcp");
|
||||
}
|
||||
|
||||
static void dcb_rewr_print_prio_dscp(const struct dcb *dcb,
|
||||
const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_app_print_filtered(tab, dcb_app_is_dscp,
|
||||
dcb_rewr_print_prio_pid,
|
||||
dcb->numeric ? dcb_app_print_pid_dec :
|
||||
dcb_app_print_pid_dscp,
|
||||
"prio_dscp", "prio-dscp");
|
||||
}
|
||||
|
||||
static void dcb_rewr_print(const struct dcb *dcb,
|
||||
const struct dcb_app_table *tab)
|
||||
{
|
||||
dcb_rewr_print_prio_pcp(dcb, tab);
|
||||
dcb_rewr_print_prio_dscp(dcb, tab);
|
||||
}
|
||||
|
||||
static bool dcb_rewr_prio_eq(const struct dcb_app *aa, const struct dcb_app *ab)
|
||||
{
|
||||
return aa->selector == ab->selector &&
|
||||
aa->priority == ab->priority;
|
||||
}
|
||||
|
||||
static int dcb_cmd_rewr_parse_add_del(struct dcb *dcb, const char *dev,
|
||||
int argc, char **argv,
|
||||
struct dcb_app_table *tab)
|
||||
{
|
||||
struct dcb_app_parse_mapping pm = {
|
||||
.tab = tab,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!argc) {
|
||||
dcb_rewr_help_add();
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
if (strcmp(*argv, "help") == 0) {
|
||||
dcb_rewr_help_add();
|
||||
return 0;
|
||||
} else if (strcmp(*argv, "prio-pcp") == 0) {
|
||||
NEXT_ARG();
|
||||
pm.selector = DCB_APP_SEL_PCP;
|
||||
ret = parse_mapping(&argc, &argv, false,
|
||||
&dcb_rewr_parse_mapping_prio_pcp,
|
||||
&pm);
|
||||
} else if (strcmp(*argv, "prio-dscp") == 0) {
|
||||
NEXT_ARG();
|
||||
pm.selector = IEEE_8021QAZ_APP_SEL_DSCP;
|
||||
ret = parse_mapping(&argc, &argv, false,
|
||||
&dcb_rewr_parse_mapping_prio_dscp,
|
||||
&pm);
|
||||
} else {
|
||||
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
||||
dcb_rewr_help_add();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid mapping %s\n", *argv);
|
||||
return ret;
|
||||
}
|
||||
if (pm.err)
|
||||
return pm.err;
|
||||
} while (argc > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dcb_cmd_rewr_add(struct dcb *dcb, const char *dev, int argc,
|
||||
char **argv)
|
||||
{
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_SET, &tab, NULL);
|
||||
dcb_app_table_fini(&tab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dcb_cmd_rewr_del(struct dcb *dcb, const char *dev, int argc,
|
||||
char **argv)
|
||||
{
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab, NULL);
|
||||
dcb_app_table_fini(&tab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dcb_cmd_rewr_replace(struct dcb *dcb, const char *dev, int argc,
|
||||
char **argv)
|
||||
{
|
||||
struct dcb_app_table orig = { .attr = DCB_ATTR_DCB_REWR_TABLE };
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
|
||||
struct dcb_app_table new = { .attr = DCB_ATTR_DCB_REWR_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_app_get(dcb, dev, &orig);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
/* Attempts to add an existing entry would be rejected, so drop
|
||||
* these entries from tab.
|
||||
*/
|
||||
ret = dcb_app_table_copy(&new, &tab);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
dcb_app_table_remove_existing(&new, &orig);
|
||||
|
||||
ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_SET, &new, NULL);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Could not add new rewrite entries\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Remove the obsolete entries. */
|
||||
dcb_app_table_remove_replaced(&orig, &tab, dcb_rewr_prio_eq);
|
||||
ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &orig, NULL);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Could not remove replaced rewrite entries\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
dcb_app_table_fini(&new);
|
||||
dcb_app_table_fini(&tab);
|
||||
dcb_app_table_fini(&orig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dcb_cmd_rewr_show(struct dcb *dcb, const char *dev, int argc,
|
||||
char **argv)
|
||||
{
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_app_get(dcb, dev, &tab);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
dcb_app_table_sort(&tab);
|
||||
|
||||
open_json_object(NULL);
|
||||
|
||||
if (!argc) {
|
||||
dcb_rewr_print(dcb, &tab);
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
if (strcmp(*argv, "help") == 0) {
|
||||
dcb_rewr_help_show_flush();
|
||||
goto out;
|
||||
} else if (strcmp(*argv, "prio-pcp") == 0) {
|
||||
dcb_rewr_print_prio_pcp(dcb, &tab);
|
||||
} else if (strcmp(*argv, "prio-dscp") == 0) {
|
||||
dcb_rewr_print_prio_dscp(dcb, &tab);
|
||||
} else {
|
||||
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
||||
dcb_rewr_help_show_flush();
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
NEXT_ARG_FWD();
|
||||
} while (argc > 0);
|
||||
|
||||
out:
|
||||
close_json_object();
|
||||
dcb_app_table_fini(&tab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dcb_cmd_rewr_flush(struct dcb *dcb, const char *dev, int argc,
|
||||
char **argv)
|
||||
{
|
||||
struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
|
||||
int ret;
|
||||
|
||||
ret = dcb_app_get(dcb, dev, &tab);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (!argc) {
|
||||
ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
|
||||
NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
if (strcmp(*argv, "help") == 0) {
|
||||
dcb_rewr_help_show_flush();
|
||||
goto out;
|
||||
} else if (strcmp(*argv, "prio-pcp") == 0) {
|
||||
ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
|
||||
&dcb_app_is_pcp);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
} else if (strcmp(*argv, "prio-dscp") == 0) {
|
||||
ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
|
||||
&dcb_app_is_dscp);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
} else {
|
||||
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
||||
dcb_rewr_help_show_flush();
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
NEXT_ARG_FWD();
|
||||
} while (argc > 0);
|
||||
|
||||
out:
|
||||
dcb_app_table_fini(&tab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dcb_cmd_rewr(struct dcb *dcb, int argc, char **argv)
|
||||
{
|
||||
if (!argc || strcmp(*argv, "help") == 0) {
|
||||
dcb_rewr_help();
|
||||
return 0;
|
||||
} else if (strcmp(*argv, "show") == 0) {
|
||||
NEXT_ARG_FWD();
|
||||
return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_show,
|
||||
dcb_rewr_help_show_flush);
|
||||
} else if (strcmp(*argv, "flush") == 0) {
|
||||
NEXT_ARG_FWD();
|
||||
return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_flush,
|
||||
dcb_rewr_help_show_flush);
|
||||
} else if (strcmp(*argv, "add") == 0) {
|
||||
NEXT_ARG_FWD();
|
||||
return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_add,
|
||||
dcb_rewr_help_add);
|
||||
} else if (strcmp(*argv, "del") == 0) {
|
||||
NEXT_ARG_FWD();
|
||||
return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_del,
|
||||
dcb_rewr_help_add);
|
||||
} else if (strcmp(*argv, "replace") == 0) {
|
||||
NEXT_ARG_FWD();
|
||||
return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_replace,
|
||||
dcb_rewr_help_add);
|
||||
} else {
|
||||
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
||||
dcb_rewr_help();
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -315,7 +315,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
|
||||
|
||||
rtnl_dump_filter(&rth, print_ctrl2, stdout);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ctrl_done:
|
||||
|
||||
@ -1273,6 +1273,9 @@ enum {
|
||||
|
||||
/* Create a map that will be registered/unregesitered by the backed bpf_link */
|
||||
BPF_F_LINK = (1U << 13),
|
||||
|
||||
/* Get path from provided FD in BPF_OBJ_PIN/BPF_OBJ_GET commands */
|
||||
BPF_F_PATH_FD = (1U << 14),
|
||||
};
|
||||
|
||||
/* Flags for BPF_PROG_QUERY. */
|
||||
@ -1421,6 +1424,13 @@ union bpf_attr {
|
||||
__aligned_u64 pathname;
|
||||
__u32 bpf_fd;
|
||||
__u32 file_flags;
|
||||
/* Same as dirfd in openat() syscall; see openat(2)
|
||||
* manpage for details of path FD and pathname semantics;
|
||||
* path_fd should accompanied by BPF_F_PATH_FD flag set in
|
||||
* file_flags field, otherwise it should be set to zero;
|
||||
* if BPF_F_PATH_FD flag is not set, AT_FDCWD is assumed.
|
||||
*/
|
||||
__s32 path_fd;
|
||||
};
|
||||
|
||||
struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */
|
||||
|
||||
@ -826,6 +826,7 @@ enum {
|
||||
IFLA_VXLAN_TTL_INHERIT,
|
||||
IFLA_VXLAN_DF,
|
||||
IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */
|
||||
IFLA_VXLAN_LOCALBYPASS,
|
||||
__IFLA_VXLAN_MAX
|
||||
};
|
||||
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
|
||||
|
||||
@ -594,6 +594,10 @@ enum {
|
||||
|
||||
TCA_FLOWER_KEY_L2TPV3_SID, /* be32 */
|
||||
|
||||
TCA_FLOWER_L2_MISS, /* u8 */
|
||||
|
||||
TCA_FLOWER_KEY_CFM, /* nested */
|
||||
|
||||
__TCA_FLOWER_MAX,
|
||||
};
|
||||
|
||||
@ -702,6 +706,13 @@ enum {
|
||||
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_FLOWER_KEY_CFM_OPT_UNSPEC,
|
||||
TCA_FLOWER_KEY_CFM_MD_LEVEL,
|
||||
TCA_FLOWER_KEY_CFM_OPCODE,
|
||||
TCA_FLOWER_KEY_CFM_OPT_MAX,
|
||||
};
|
||||
|
||||
#define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0) /* Range-based match */
|
||||
|
||||
/* Match-all classifier */
|
||||
|
||||
@ -1259,6 +1259,16 @@ enum {
|
||||
TCA_TAPRIO_TC_ENTRY_MAX = (__TCA_TAPRIO_TC_ENTRY_CNT - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_TAPRIO_OFFLOAD_STATS_PAD = 1, /* u64 */
|
||||
TCA_TAPRIO_OFFLOAD_STATS_WINDOW_DROPS, /* u64 */
|
||||
TCA_TAPRIO_OFFLOAD_STATS_TX_OVERRUNS, /* u64 */
|
||||
|
||||
/* add new constants above here */
|
||||
__TCA_TAPRIO_OFFLOAD_STATS_CNT,
|
||||
TCA_TAPRIO_OFFLOAD_STATS_MAX = (__TCA_TAPRIO_OFFLOAD_STATS_CNT - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_TAPRIO_ATTR_UNSPEC,
|
||||
TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
|
||||
|
||||
@ -1443,7 +1443,7 @@ static const struct ifa_flag_data_t* lookup_flag_data_by_name(const char* flag_n
|
||||
if (strcmp(flag_name, ifa_flag_data[i].name) == 0)
|
||||
return &ifa_flag_data[i];
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void print_ifa_flags(FILE *fp, const struct ifaddrmsg *ifa,
|
||||
@ -2031,9 +2031,13 @@ static int ipaddr_flush(void)
|
||||
|
||||
static int iplink_filter_req(struct nlmsghdr *nlh, int reqlen)
|
||||
{
|
||||
__u32 filt_mask;
|
||||
int err;
|
||||
|
||||
err = addattr32(nlh, reqlen, IFLA_EXT_MASK, RTEXT_FILTER_VF);
|
||||
filt_mask = RTEXT_FILTER_VF;
|
||||
if (!show_stats)
|
||||
filt_mask |= RTEXT_FILTER_SKIP_STATS;
|
||||
err = addattr32(nlh, reqlen, IFLA_EXT_MASK, filt_mask);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@ -1166,6 +1166,9 @@ int iplink_get(char *name, __u32 filt_mask)
|
||||
!check_ifname(name) ? IFLA_IFNAME : IFLA_ALT_IFNAME,
|
||||
name, strlen(name) + 1);
|
||||
}
|
||||
|
||||
if (!show_stats)
|
||||
filt_mask |= RTEXT_FILTER_SKIP_STATS;
|
||||
addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
|
||||
|
||||
if (rtnl_talk(&rth, &req.n, &answer) < 0)
|
||||
|
||||
@ -36,6 +36,7 @@ static const struct vxlan_bool_opt {
|
||||
{ "udp_zero_csum6_rx", IFLA_VXLAN_UDP_ZERO_CSUM6_RX, false },
|
||||
{ "remcsum_tx", IFLA_VXLAN_REMCSUM_TX, false },
|
||||
{ "remcsum_rx", IFLA_VXLAN_REMCSUM_RX, false },
|
||||
{ "localbypass", IFLA_VXLAN_LOCALBYPASS, true },
|
||||
};
|
||||
|
||||
static void print_explain(FILE *f)
|
||||
@ -62,6 +63,7 @@ static void print_explain(FILE *f)
|
||||
" [ [no]udp6zerocsumtx ]\n"
|
||||
" [ [no]udp6zerocsumrx ]\n"
|
||||
" [ [no]remcsumtx ] [ [no]remcsumrx ]\n"
|
||||
" [ [no]localbypass ]\n"
|
||||
" [ [no]external ] [ gbp ] [ gpe ]\n"
|
||||
" [ [no]vnifilter ]\n"
|
||||
"\n"
|
||||
@ -327,6 +329,14 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
check_duparg(&attrs, IFLA_VXLAN_REMCSUM_RX,
|
||||
*argv, *argv);
|
||||
addattr8(n, 1024, IFLA_VXLAN_REMCSUM_RX, 0);
|
||||
} else if (strcmp(*argv, "localbypass") == 0) {
|
||||
check_duparg(&attrs, IFLA_VXLAN_LOCALBYPASS,
|
||||
*argv, *argv);
|
||||
addattr8(n, 1024, IFLA_VXLAN_LOCALBYPASS, 1);
|
||||
} else if (strcmp(*argv, "nolocalbypass") == 0) {
|
||||
check_duparg(&attrs, IFLA_VXLAN_LOCALBYPASS,
|
||||
*argv, *argv);
|
||||
addattr8(n, 1024, IFLA_VXLAN_LOCALBYPASS, 0);
|
||||
} else if (!matches(*argv, "external")) {
|
||||
check_duparg(&attrs, IFLA_VXLAN_COLLECT_METADATA,
|
||||
*argv, *argv);
|
||||
|
||||
@ -1379,10 +1379,10 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
if (strcmp(*argv, "default") == 0)
|
||||
cipher.id = MACSEC_DEFAULT_CIPHER_ID;
|
||||
else if (strcmp(*argv, "gcm-aes-128") == 0 ||
|
||||
strcmp(*argv, "GCM-AES-128") == 0)
|
||||
strcmp(*argv, "GCM-AES-128") == 0)
|
||||
cipher.id = MACSEC_CIPHER_ID_GCM_AES_128;
|
||||
else if (strcmp(*argv, "gcm-aes-256") == 0 ||
|
||||
strcmp(*argv, "GCM-AES-256") == 0)
|
||||
strcmp(*argv, "GCM-AES-256") == 0)
|
||||
cipher.id = MACSEC_CIPHER_ID_GCM_AES_256;
|
||||
else if (strcmp(*argv, "gcm-aes-xpn-128") == 0 ||
|
||||
strcmp(*argv, "GCM-AES-XPN-128") == 0)
|
||||
|
||||
@ -58,6 +58,7 @@ static const struct {
|
||||
{ "subflow", MPTCP_PM_ADDR_FLAG_SUBFLOW },
|
||||
{ "backup", MPTCP_PM_ADDR_FLAG_BACKUP },
|
||||
{ "fullmesh", MPTCP_PM_ADDR_FLAG_FULLMESH },
|
||||
{ "implicit", MPTCP_PM_ADDR_FLAG_IMPLICIT },
|
||||
{ "nobackup", MPTCP_PM_ADDR_FLAG_NONE },
|
||||
{ "nofullmesh", MPTCP_PM_ADDR_FLAG_NONE }
|
||||
};
|
||||
|
||||
@ -60,7 +60,7 @@ int print_prefix(struct nlmsghdr *n, void *arg)
|
||||
|
||||
if (tb[PREFIX_ADDRESS]) {
|
||||
fprintf(fp, "prefix %s/%u",
|
||||
rt_addr_n2a_rta(family, tb[PREFIX_ADDRESS]),
|
||||
rt_addr_n2a_rta(family, tb[PREFIX_ADDRESS]),
|
||||
prefix->prefix_len);
|
||||
}
|
||||
fprintf(fp, "dev %s ", ll_index_to_name(prefix->prefix_ifindex));
|
||||
|
||||
@ -252,7 +252,7 @@ static int prog_load(int idx)
|
||||
};
|
||||
|
||||
return bpf_program_load(BPF_PROG_TYPE_CGROUP_SOCK, prog, sizeof(prog),
|
||||
"GPL", bpf_log_buf, sizeof(bpf_log_buf));
|
||||
"GPL", bpf_log_buf, sizeof(bpf_log_buf));
|
||||
}
|
||||
|
||||
static int vrf_configure_cgroup(const char *path, int ifindex)
|
||||
|
||||
2
lib/fs.c
2
lib/fs.c
@ -41,7 +41,7 @@ static int name_to_handle_at(int dirfd, const char *pathname,
|
||||
struct file_handle *handle, int *mount_id, int flags)
|
||||
{
|
||||
return syscall(__NR_name_to_handle_at, dirfd, pathname, handle,
|
||||
mount_id, flags);
|
||||
mount_id, flags);
|
||||
}
|
||||
|
||||
static int open_by_handle_at(int mount_fd, struct file_handle *handle, int flags)
|
||||
|
||||
@ -78,6 +78,7 @@ __PF(8021AD,802.1ad)
|
||||
__PF(MPLS_UC,mpls_uc)
|
||||
__PF(MPLS_MC,mpls_mc)
|
||||
__PF(TEB,teb)
|
||||
__PF(CFM,cfm)
|
||||
|
||||
{ 0x8100, "802.1Q" },
|
||||
{ 0x88cc, "LLDP" },
|
||||
|
||||
@ -108,10 +108,10 @@ __PF(VOID, void)
|
||||
#undef __PF
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; !numeric && i < ARRAY_SIZE(arphrd_names); i++) {
|
||||
if (arphrd_names[i].type == type)
|
||||
for (i = 0; !numeric && i < ARRAY_SIZE(arphrd_names); i++) {
|
||||
if (arphrd_names[i].type == type)
|
||||
return arphrd_names[i].name;
|
||||
}
|
||||
snprintf(buf, len, "[%d]", type);
|
||||
return buf;
|
||||
snprintf(buf, len, "[%d]", type);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
.TH DCB-ETS 8 "6 December 2020" "iproute2" "Linux"
|
||||
.TH DCB-APP 8 "6 December 2020" "iproute2" "Linux"
|
||||
.SH NAME
|
||||
dcb-app \- show / manipulate application priority table of
|
||||
the DCB (Data Center Bridging) subsystem
|
||||
@ -26,7 +26,7 @@ the DCB (Data Center Bridging) subsystem
|
||||
.RB "[ " pcp-prio " ]"
|
||||
|
||||
.ti -8
|
||||
.B dcb ets " { " add " | " del " | " replace " } " dev
|
||||
.B dcb app " { " add " | " del " | " replace " } " dev
|
||||
.RI DEV
|
||||
.RB "[ " default-prio " " \fIPRIO-LIST\fB " ]"
|
||||
.RB "[ " ethtype-prio " " \fIET-MAP\fB " ]"
|
||||
@ -106,7 +106,7 @@ individual APP 3-tuples through
|
||||
.B add
|
||||
and
|
||||
.B del
|
||||
commands. On the other other hand, the command
|
||||
commands. On the other hand, the command
|
||||
.B replace
|
||||
does what one would typically want in this situation--first adds the new
|
||||
configuration, and then removes the obsolete one, so that only one
|
||||
@ -184,7 +184,7 @@ for details. Keys are DSCP points, values are priorities assigned to
|
||||
traffic with matching DSCP. DSCP points can be written either directly as
|
||||
numeric values, or using symbolic names specified in
|
||||
.B /etc/iproute2/rt_dsfield
|
||||
(however note that that file specifies full 8-bit dsfield values, whereas
|
||||
(however note that the file specifies full 8-bit dsfield values, whereas
|
||||
.B dcb app
|
||||
will only use the higher six bits).
|
||||
.B dcb app show
|
||||
@ -230,7 +230,7 @@ priority 4:
|
||||
.P
|
||||
# dcb app replace dev eth0 dscp-prio 24:4
|
||||
.br
|
||||
# dcb app show dev eth0 dscp-prio
|
||||
# dcb app -N show dev eth0 dscp-prio
|
||||
.br
|
||||
dscp-prio 0:0 24:4 48:6
|
||||
|
||||
|
||||
206
man/man8/dcb-rewr.8
Normal file
206
man/man8/dcb-rewr.8
Normal file
@ -0,0 +1,206 @@
|
||||
.TH DCB-REWR 8 "15 may 2023" "iproute2" "Linux"
|
||||
.SH NAME
|
||||
dcb-rewr \- show / manipulate the rewrite table of
|
||||
the DCB (Data Center Bridging) subsystem
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
.ad l
|
||||
.in +8
|
||||
|
||||
.ti -8
|
||||
.B dcb
|
||||
.RI "[ " OPTIONS " ] "
|
||||
.B rewr
|
||||
.RI "{ " COMMAND " | " help " }"
|
||||
.sp
|
||||
|
||||
.ti -8
|
||||
.B dcb rewr " { " show " | " flush " } " dev
|
||||
.RI DEV
|
||||
.RB "[ " prio-dscp " ]"
|
||||
.RB "[ " prio-pcp " ]"
|
||||
|
||||
.ti -8
|
||||
.B dcb rewr " { " add " | " del " | " replace " } " dev
|
||||
.RI DEV
|
||||
.RB "[ " prio-dscp " " \fIDSCP-MAP\fB " ]"
|
||||
.RB "[ " prio-pcp " " \fIPCP-MAP\fB " ]"
|
||||
|
||||
.ti -8
|
||||
.IR DSCP-MAP " := [ " DSCP-MAP " ] " DSCP-MAPPING
|
||||
|
||||
.ti -8
|
||||
.IR DSCP-MAPPING " := " \fIPRIO \fB:\fR "{ " DSCP " | " \fBall\fR " }"
|
||||
|
||||
.ti -8
|
||||
.IR PCP-MAP " := [ " PCP-MAP " ] " PCP-MAPPING
|
||||
|
||||
.ti -8
|
||||
.IR PCP-MAPPING " := " \fIPRIO \fB:\fR PCP\fR
|
||||
|
||||
.ti -8
|
||||
.IR DSCP " := { " \fB0\fR " .. " \fB63\fR " }"
|
||||
|
||||
.ti -8
|
||||
.IR PCP " := { " \fB0(nd/de)\fR " .. " \fB7(nd/de)\fR " }"
|
||||
|
||||
.ti -8
|
||||
.IR PRIO " := { " \fB0\fR " .. " \fB7\fR " }"
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
.B dcb rewr
|
||||
is used to configure the rewrite table, in the DCB (Data Center Bridging)
|
||||
subsystem. The rewrite table is used to rewrite certain values in the packet
|
||||
headers, based on packet priority.
|
||||
|
||||
DCB rewrite entries are, like DCB APP entries, 3-tuples of selector, protocol
|
||||
ID, and priority. Selector is an enumeration that picks one of the
|
||||
prioritization namespaces. Currently, only the DSCP and PCP selector namespaces
|
||||
are supported by dcb rewr.
|
||||
|
||||
The rewrite table is a list of DCB rewrite rules, that applies to packets
|
||||
with matching priority. Notably, it is valid to have conflicting rewrite
|
||||
assignment for the same selector and priority. For example, the set of two
|
||||
rewrite entries (DSCP, 10, 1) and (DSCP, 11, 1), where packets with priority 1
|
||||
should have its DSCP value rewritten to both 10 and 11, form a well-defined
|
||||
rewrite table.
|
||||
.B dcb rewr
|
||||
tool allows low-level management of the rewrite table by adding and deleting
|
||||
individual rewrite 3-tuples through
|
||||
.B add
|
||||
and
|
||||
.B del
|
||||
commands. On the other hand, the command
|
||||
.B replace
|
||||
does what one would typically want in this situation--first adds the new
|
||||
configuration, and then removes the obsolete one, so that only one
|
||||
rewrite rule is in effect for a given selector and priority.
|
||||
|
||||
.SH COMMANDS
|
||||
|
||||
.TP
|
||||
.B show
|
||||
Display all entries with a given selector. When no selector is given, shows all
|
||||
rewrite table entries categorized per selector.
|
||||
|
||||
.TP
|
||||
.B flush
|
||||
Remove all entries with a given selector. When no selector is given, removes all
|
||||
rewrite table entries.
|
||||
|
||||
.TP
|
||||
.B add
|
||||
.TQ
|
||||
.B del
|
||||
Add and, respectively, remove individual rewrite 3-tuples to and from the DCB
|
||||
rewrite table.
|
||||
|
||||
.TP
|
||||
.B replace
|
||||
Take the list of entries mentioned as parameter, and add those that are not
|
||||
present in the rewrite table yet. Then remove those entries, whose selector and
|
||||
priority have been mentioned as parameter, but not with the exact same
|
||||
protocol ID. This has the effect of, for the given selector and priority,
|
||||
causing that the table only contains the protocol ID (or ID's) given as
|
||||
parameter.
|
||||
|
||||
.SH PARAMETERS
|
||||
|
||||
The following table shows parameters in a way that they would be used with
|
||||
\fBadd\fR, \fBdel\fR and \fBreplace\fR commands. For \fBshow\fR and
|
||||
\fBflush\fR, the parameter name is to be used as a simple keyword without
|
||||
further arguments.
|
||||
|
||||
.TP
|
||||
.B prio-dscp \fIDSCP-MAP
|
||||
\fIDSCP-MAP\fR uses the array parameter syntax, see
|
||||
.BR dcb (8)
|
||||
for details. Keys are priorities, values are DSCP points for traffic
|
||||
with matching priority. DSCP points can be written either directly as numeric
|
||||
values, or using symbolic names specified in
|
||||
.B /etc/iproute2/rt_dsfield
|
||||
(however note that the file specifies full 8-bit dsfield values, whereas
|
||||
.B dcb rewr
|
||||
will only use the higher six bits).
|
||||
.B dcb rewr show
|
||||
will similarly format DSCP values as symbolic names if possible. The
|
||||
command line option
|
||||
.B -N
|
||||
turns the show translation off.
|
||||
|
||||
.TP
|
||||
.B prio-pcp \fIPCP-MAP
|
||||
\fIPCP-MAP\fR uses the array parameter syntax, see
|
||||
.BR dcb (8)
|
||||
for details. Keys are priorities. Values are PCP/DEI for traffic with
|
||||
matching priority. PCP/DEI values are written as a combination of numeric- and
|
||||
symbolic values, to accommodate for both. PCP always in numeric form e.g 0 ..
|
||||
7 and DEI in symbolic form e.g 'de' (drop-eligible), indicating that the DEI
|
||||
bit is 1 or 'nd' (not-drop-eligible), indicating that the DEI bit is 0. In
|
||||
combination 1:2de translates to a mapping of priority 1 to PCP=2 and DEI=1.
|
||||
|
||||
.SH EXAMPLE & USAGE
|
||||
|
||||
Add a rule to rewrite DSCP to 0, 24 and 48 for traffic with priority 0, 3 and
|
||||
6, respectively:
|
||||
.P
|
||||
# dcb rewr add dev eth0 prio-dscp 0:0 3:24 6:48
|
||||
|
||||
Add a rule to rewrite DSCP to 25 for traffic with priority 3:
|
||||
.P
|
||||
# dcb rewr add dev eth0 prio-dscp 3:25
|
||||
.br
|
||||
# dcb rewr show dev eth0 prio-dscp
|
||||
.br
|
||||
prio-dscp 0:0 3:CS3 3:25 6:CS6
|
||||
.br
|
||||
# dcb -N rewr show dev eth0 prio-dscp
|
||||
.br
|
||||
prio-dscp 0:0 3:24 3:25 6:48
|
||||
|
||||
Reconfigure the table so that only one rule exists for rewriting traffic with
|
||||
priority 3.
|
||||
|
||||
.P
|
||||
# dcb rewr replace dev eth0 prio-dscp 3:26
|
||||
.br
|
||||
# dcb rewr -N show dev eth0 prio-dscp
|
||||
.br
|
||||
prio-dscp 0:0 3:26 6:48
|
||||
|
||||
Flush all DSCP rules:
|
||||
|
||||
.P
|
||||
# dcb rewr flush dev eth0 prio-dscp
|
||||
.br
|
||||
# dcb rewr show dev eth0 prio-dscp
|
||||
.br
|
||||
(nothing)
|
||||
|
||||
Add a rule to rewrite PCP to 1 and DEI to 0 for traffic with priority 1 and a
|
||||
rule to rewrite PCP to 2 and DEI to 1 for traffic with priority 2:
|
||||
|
||||
.P
|
||||
# dcb rewr add dev eth0 prio-pcp 1:1nd 2:2de
|
||||
.br
|
||||
# dcb rewr show dev eth0 prio-pcp
|
||||
.br
|
||||
prio-pcp 1:1nd 2:2de
|
||||
|
||||
.SH EXIT STATUS
|
||||
Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR dcb (8)
|
||||
.BR dcb-app (8)
|
||||
.BR dcb-apptrust (8)
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Report any bugs to the Network Developers mailing list
|
||||
.B <netdev@vger.kernel.org>
|
||||
where the development and maintenance is primarily done. You do not have to be
|
||||
subscribed to the list to send a message there.
|
||||
|
||||
.SH AUTHOR
|
||||
Daniel Machon <daniel.machon@microchip.com>
|
||||
@ -140,10 +140,12 @@ Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR dcb-app (8),
|
||||
.BR dcb-apptrust (8),
|
||||
.BR dcb-buffer (8),
|
||||
.BR dcb-ets (8),
|
||||
.BR dcb-maxrate (8),
|
||||
.BR dcb-pfc (8)
|
||||
.BR dcb-pfc (8),
|
||||
.BR dcb-rewr (8)
|
||||
.br
|
||||
|
||||
.SH REPORTING BUGS
|
||||
|
||||
@ -634,6 +634,8 @@ the following additional arguments are supported:
|
||||
] [
|
||||
.RB [ no ] udp6zerocsumrx
|
||||
] [
|
||||
.RB [ no ] localbypass
|
||||
] [
|
||||
.BI ageing " SECONDS "
|
||||
] [
|
||||
.BI maxaddress " NUMBER "
|
||||
@ -742,6 +744,14 @@ are entered into the VXLAN device forwarding database.
|
||||
.RB [ no ] udp6zerocsumrx
|
||||
- allow incoming UDP packets over IPv6 with zero checksum field.
|
||||
|
||||
.sp
|
||||
.RB [ no ] localbypass
|
||||
- if FDB destination is local, with nolocalbypass set, forward encapsulated
|
||||
packets to the userspace network stack. If there is a userspace process
|
||||
listening for these packets, it will have a chance to process them. If
|
||||
localbypass is active (default), bypass the kernel network stack and
|
||||
inject the packets into the target VXLAN device, assuming one exists.
|
||||
|
||||
.sp
|
||||
.BI ageing " SECONDS"
|
||||
- specifies the lifetime in seconds of FDB entries learnt by the kernel.
|
||||
|
||||
@ -176,6 +176,15 @@ endpoint. When the peer does announce addresses, each received ADD_ADDR
|
||||
sub-option will trigger creation of an additional subflow to generate a
|
||||
full mesh topology.
|
||||
|
||||
.TP
|
||||
.BR implicit
|
||||
In some scenarios, an MPTCP
|
||||
.BR subflow
|
||||
can use a local address mapped by a implicit endpoint created by the
|
||||
in-kernel path manager. Once set, the implicit flag cannot be removed, but
|
||||
other flags can be added to the endpoint. Implicit endpoints cannot be
|
||||
created from user-space.
|
||||
|
||||
.sp
|
||||
.PP
|
||||
The
|
||||
|
||||
@ -100,7 +100,11 @@ flower \- flow based traffic control filter
|
||||
}
|
||||
.IR OPTIONS " | "
|
||||
.BR ip_flags
|
||||
.IR IP_FLAGS " }"
|
||||
.IR IP_FLAGS " | "
|
||||
.B l2_miss
|
||||
.IR L2_MISS " | "
|
||||
.BR cfm
|
||||
.IR CFM_OPTIONS " }"
|
||||
|
||||
.ti -8
|
||||
.IR LSE_LIST " := [ " LSE_LIST " ] " LSE
|
||||
@ -118,6 +122,13 @@ flower \- flow based traffic control filter
|
||||
.B ttl
|
||||
.IR TTL " }"
|
||||
|
||||
.ti -8
|
||||
.IR CFM " := "
|
||||
.B cfm mdl
|
||||
.IR LEVEL " | "
|
||||
.B op
|
||||
.IR OPCODE "
|
||||
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B flower
|
||||
@ -493,6 +504,30 @@ respectively. firstfrag and nofirstfrag can be used to further distinguish
|
||||
fragmented packet. firstfrag can be used to indicate the first fragmented
|
||||
packet. nofirstfrag can be used to indicates subsequent fragmented packets
|
||||
or non-fragmented packets.
|
||||
.TP
|
||||
|
||||
.BI l2_miss " L2_MISS"
|
||||
Match on layer 2 miss in the bridge driver's FDB / MDB. \fIL2_MISS\fR may be 0
|
||||
or 1. When 1, match on packets that encountered a layer 2 miss. When 0, match
|
||||
on packets that were forwarded using an FDB / MDB entry. Note that broadcast
|
||||
packets do not encounter a miss since a lookup is not performed for them.
|
||||
.TP
|
||||
|
||||
.BI cfm " CFM_OPTIONS"
|
||||
Match on Connectivity Fault Management (CFM) fields.
|
||||
.I CFM_OPTIONS
|
||||
is a list of options that describe the properties of the CFM information
|
||||
fields to match.
|
||||
.RS
|
||||
.TP
|
||||
.BI mdl " LEVEL "
|
||||
Match on the Maintenance Domain (MD) level field.
|
||||
\fILEVEL\fR is an unsigned 3 bit value in decimal format.
|
||||
.TP
|
||||
.BI op " OPCODE "
|
||||
Match on the CFM opcode field. \fIOPCODE\fR is an unsigned 8 bit value in
|
||||
decimal format.
|
||||
|
||||
.SH NOTES
|
||||
As stated above where applicable, matches of a certain layer implicitly depend
|
||||
on the matches of the next lower layer. Precisely, layer one and two matches
|
||||
|
||||
12
rdma/dev.c
12
rdma/dev.c
@ -189,6 +189,17 @@ static void dev_print_node_type(struct rd *rd, struct nlattr **tb)
|
||||
node_str);
|
||||
}
|
||||
|
||||
static void dev_print_dev_proto(struct rd *rd, struct nlattr **tb)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_PROTOCOL])
|
||||
return;
|
||||
|
||||
str = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_PROTOCOL]);
|
||||
print_color_string(PRINT_ANY, COLOR_NONE, "protocol", "protocol %s ", str);
|
||||
}
|
||||
|
||||
static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
@ -206,6 +217,7 @@ static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
print_color_string(PRINT_ANY, COLOR_NONE, "ifname", "%s: ", name);
|
||||
|
||||
dev_print_node_type(rd, tb);
|
||||
dev_print_dev_proto(rd, tb);
|
||||
dev_print_fw(rd, tb);
|
||||
dev_print_node_guid(rd, tb);
|
||||
dev_print_sys_image_guid(rd, tb);
|
||||
|
||||
118
tc/f_flower.c
118
tc/f_flower.c
@ -57,7 +57,7 @@ static void explain(void)
|
||||
" cvlan_prio PRIORITY |\n"
|
||||
" cvlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
|
||||
" pppoe_sid PSID |\n"
|
||||
" ppp_proto [ ipv4 | ipv6 | mpls_uc | mpls_mc | PPP_PROTO ]"
|
||||
" ppp_proto [ ipv4 | ipv6 | mpls_uc | mpls_mc | PPP_PROTO ] |\n"
|
||||
" dst_mac MASKED-LLADDR |\n"
|
||||
" src_mac MASKED-LLADDR |\n"
|
||||
" ip_proto [tcp | udp | sctp | icmp | icmpv6 | l2tp | IP-PROTO ] |\n"
|
||||
@ -88,19 +88,22 @@ static void explain(void)
|
||||
" enc_ttl MASKED-IP_TTL |\n"
|
||||
" geneve_opts MASKED-OPTIONS |\n"
|
||||
" vxlan_opts MASKED-OPTIONS |\n"
|
||||
" erspan_opts MASKED-OPTIONS |\n"
|
||||
" erspan_opts MASKED-OPTIONS |\n"
|
||||
" gtp_opts MASKED-OPTIONS |\n"
|
||||
" ip_flags IP-FLAGS |\n"
|
||||
" l2_miss L2_MISS |\n"
|
||||
" enc_dst_port [ port_number ] |\n"
|
||||
" ct_state MASKED_CT_STATE |\n"
|
||||
" ct_label MASKED_CT_LABEL |\n"
|
||||
" ct_mark MASKED_CT_MARK |\n"
|
||||
" ct_zone MASKED_CT_ZONE }\n"
|
||||
" ct_zone MASKED_CT_ZONE |\n"
|
||||
" cfm CFM }\n"
|
||||
" LSE-LIST := [ LSE-LIST ] LSE\n"
|
||||
" LSE := lse depth DEPTH { label LABEL | tc TC | bos BOS | ttl TTL }\n"
|
||||
" FILTERID := X:Y:Z\n"
|
||||
" MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
|
||||
" MASKED_CT_STATE := combination of {+|-} and flags trk,est,new,rel,rpl,inv\n"
|
||||
" CFM := { mdl LEVEL | op OPCODE }\n"
|
||||
" ACTION-SPEC := ... look at individual actions\n"
|
||||
"\n"
|
||||
"NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n"
|
||||
@ -1446,6 +1449,57 @@ static int flower_parse_mpls(int *argc_p, char ***argv_p, struct nlmsghdr *nlh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flower_parse_cfm(int *argc_p, char ***argv_p, __be16 eth_type,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
struct rtattr *cfm_attr;
|
||||
char **argv = *argv_p;
|
||||
int argc = *argc_p;
|
||||
int ret;
|
||||
|
||||
if (eth_type != htons(ETH_P_CFM)) {
|
||||
fprintf(stderr,
|
||||
"Can't set attribute if ethertype isn't CFM\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfm_attr = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_CFM | NLA_F_NESTED);
|
||||
|
||||
while (argc > 0) {
|
||||
if (!strcmp(*argv, "mdl")) {
|
||||
__u8 val;
|
||||
|
||||
NEXT_ARG();
|
||||
ret = get_u8(&val, *argv, 10);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Illegal \"cfm md level\"\n");
|
||||
return -1;
|
||||
}
|
||||
addattr8(n, MAX_MSG, TCA_FLOWER_KEY_CFM_MD_LEVEL, val);
|
||||
} else if (!strcmp(*argv, "op")) {
|
||||
__u8 val;
|
||||
|
||||
NEXT_ARG();
|
||||
ret = get_u8(&val, *argv, 10);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Illegal \"cfm opcode\"\n");
|
||||
return -1;
|
||||
}
|
||||
addattr8(n, MAX_MSG, TCA_FLOWER_KEY_CFM_OPCODE, val);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
addattr_nest_end(n, cfm_attr);
|
||||
|
||||
*argc_p = argc;
|
||||
*argv_p = argv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flower_parse_opt(struct filter_util *qu, char *handle,
|
||||
int argc, char **argv, struct nlmsghdr *n)
|
||||
{
|
||||
@ -1520,6 +1574,15 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
||||
fprintf(stderr, "Illegal \"ip_flags\"\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(*argv, "l2_miss") == 0) {
|
||||
__u8 l2_miss;
|
||||
|
||||
NEXT_ARG();
|
||||
if (get_u8(&l2_miss, *argv, 10)) {
|
||||
fprintf(stderr, "Illegal \"l2_miss\"\n");
|
||||
return -1;
|
||||
}
|
||||
addattr8(n, MAX_MSG, TCA_FLOWER_L2_MISS, l2_miss);
|
||||
} else if (matches(*argv, "verbose") == 0) {
|
||||
flags |= TCA_CLS_FLAGS_VERBOSE;
|
||||
} else if (matches(*argv, "skip_hw") == 0) {
|
||||
@ -2055,6 +2118,12 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
} else if (!strcmp(*argv, "cfm")) {
|
||||
NEXT_ARG();
|
||||
ret = flower_parse_cfm(&argc, &argv, eth_type, n);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
continue;
|
||||
} else {
|
||||
if (strcmp(*argv, "help") != 0)
|
||||
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
||||
@ -2744,6 +2813,39 @@ static void flower_print_arp_op(const char *name,
|
||||
flower_print_arp_op_to_name);
|
||||
}
|
||||
|
||||
static void flower_print_cfm(struct rtattr *attr)
|
||||
{
|
||||
struct rtattr *tb[TCA_FLOWER_KEY_CFM_OPT_MAX + 1];
|
||||
struct rtattr *v;
|
||||
SPRINT_BUF(out);
|
||||
size_t sz = 0;
|
||||
|
||||
if (!attr || !(attr->rta_type & NLA_F_NESTED))
|
||||
return;
|
||||
|
||||
parse_rtattr(tb, TCA_FLOWER_KEY_CFM_OPT_MAX, RTA_DATA(attr),
|
||||
RTA_PAYLOAD(attr));
|
||||
|
||||
print_nl();
|
||||
print_string(PRINT_FP, NULL, " cfm", NULL);
|
||||
open_json_object("cfm");
|
||||
|
||||
v = tb[TCA_FLOWER_KEY_CFM_MD_LEVEL];
|
||||
if (v) {
|
||||
sz += sprintf(out, " mdl %u", rta_getattr_u8(v));
|
||||
print_hhu(PRINT_JSON, "mdl", NULL, rta_getattr_u8(v));
|
||||
}
|
||||
|
||||
v = tb[TCA_FLOWER_KEY_CFM_OPCODE];
|
||||
if (v) {
|
||||
sprintf(out + sz, " op %u", rta_getattr_u8(v));
|
||||
print_hhu(PRINT_JSON, "op", NULL, rta_getattr_u8(v));
|
||||
}
|
||||
|
||||
close_json_object();
|
||||
print_string(PRINT_FP, "cfm", "%s", out);
|
||||
}
|
||||
|
||||
static int flower_print_opt(struct filter_util *qu, FILE *f,
|
||||
struct rtattr *opt, __u32 handle)
|
||||
{
|
||||
@ -2983,6 +3085,14 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
|
||||
tb[TCA_FLOWER_KEY_FLAGS],
|
||||
tb[TCA_FLOWER_KEY_FLAGS_MASK]);
|
||||
|
||||
if (tb[TCA_FLOWER_L2_MISS]) {
|
||||
struct rtattr *attr = tb[TCA_FLOWER_L2_MISS];
|
||||
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "l2_miss", " l2_miss %u",
|
||||
rta_getattr_u8(attr));
|
||||
}
|
||||
|
||||
flower_print_ct_state(tb[TCA_FLOWER_KEY_CT_STATE],
|
||||
tb[TCA_FLOWER_KEY_CT_STATE_MASK]);
|
||||
flower_print_ct_zone(tb[TCA_FLOWER_KEY_CT_ZONE],
|
||||
@ -2992,6 +3102,8 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
|
||||
flower_print_ct_label(tb[TCA_FLOWER_KEY_CT_LABELS],
|
||||
tb[TCA_FLOWER_KEY_CT_LABELS_MASK]);
|
||||
|
||||
flower_print_cfm(tb[TCA_FLOWER_KEY_CFM]);
|
||||
|
||||
close_json_object();
|
||||
|
||||
if (tb[TCA_FLOWER_FLAGS]) {
|
||||
|
||||
@ -409,8 +409,8 @@ static int parse_ipt(struct action_util *a, int *argc_p,
|
||||
optind = 0;
|
||||
free_opts(opts);
|
||||
/* Clear flags if target will be used again */
|
||||
m->tflags = 0;
|
||||
m->used = 0;
|
||||
m->tflags = 0;
|
||||
m->used = 0;
|
||||
/* Free allocated memory */
|
||||
free(m->t);
|
||||
|
||||
|
||||
@ -334,8 +334,8 @@ static int parse_ipt(struct action_util *a, int *argc_p,
|
||||
optind = 0;
|
||||
free_opts(opts);
|
||||
/* Clear flags if target will be used again */
|
||||
m->tflags = 0;
|
||||
m->used = 0;
|
||||
m->tflags = 0;
|
||||
m->used = 0;
|
||||
/* Free allocated memory */
|
||||
free(m->t);
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ static void explain(void)
|
||||
fprintf(stderr,
|
||||
"Usage: ... fq [ limit PACKETS ] [ flow_limit PACKETS ]\n"
|
||||
" [ quantum BYTES ] [ initial_quantum BYTES ]\n"
|
||||
" [ maxrate RATE ] [ buckets NUMBER ]\n"
|
||||
" [ maxrate RATE ] [ buckets NUMBER ]\n"
|
||||
" [ [no]pacing ] [ refill_delay TIME ]\n"
|
||||
" [ low_rate_threshold RATE ]\n"
|
||||
" [ orphan_mask MASK]\n"
|
||||
@ -243,13 +243,13 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
||||
if (set_ce_threshold)
|
||||
addattr_l(n, 1024, TCA_FQ_CE_THRESHOLD,
|
||||
&ce_threshold, sizeof(ce_threshold));
|
||||
if (set_timer_slack)
|
||||
if (set_timer_slack)
|
||||
addattr_l(n, 1024, TCA_FQ_TIMER_SLACK,
|
||||
&timer_slack, sizeof(timer_slack));
|
||||
if (set_horizon)
|
||||
if (set_horizon)
|
||||
addattr_l(n, 1024, TCA_FQ_HORIZON,
|
||||
&horizon, sizeof(horizon));
|
||||
if (horizon_drop != 255)
|
||||
if (horizon_drop != 255)
|
||||
addattr_l(n, 1024, TCA_FQ_HORIZON_DROP,
|
||||
&horizon_drop, sizeof(horizon_drop));
|
||||
addattr_nest_end(n, tail);
|
||||
|
||||
@ -49,8 +49,8 @@ static void explain(void)
|
||||
|
||||
static void explain1(char *arg)
|
||||
{
|
||||
fprintf(stderr, "Illegal \"%s\"\n", arg);
|
||||
explain();
|
||||
fprintf(stderr, "Illegal \"%s\"\n", arg);
|
||||
explain();
|
||||
}
|
||||
|
||||
static int htb_parse_opt(struct qdisc_util *qu, int argc,
|
||||
|
||||
@ -649,8 +649,32 @@ static int taprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int taprio_print_xstats(struct qdisc_util *qu, FILE *f,
|
||||
struct rtattr *xstats)
|
||||
{
|
||||
struct rtattr *tb[TCA_TAPRIO_OFFLOAD_STATS_MAX + 1], *nla;
|
||||
|
||||
if (!xstats)
|
||||
return 0;
|
||||
|
||||
parse_rtattr_nested(tb, TCA_TAPRIO_OFFLOAD_STATS_MAX, xstats);
|
||||
|
||||
nla = tb[TCA_TAPRIO_OFFLOAD_STATS_WINDOW_DROPS];
|
||||
if (nla)
|
||||
print_lluint(PRINT_ANY, "window_drops", " window_drops %llu",
|
||||
rta_getattr_u64(nla));
|
||||
|
||||
nla = tb[TCA_TAPRIO_OFFLOAD_STATS_TX_OVERRUNS];
|
||||
if (nla)
|
||||
print_lluint(PRINT_ANY, "tx_overruns", " tx_overruns %llu",
|
||||
rta_getattr_u64(nla));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct qdisc_util taprio_qdisc_util = {
|
||||
.id = "taprio",
|
||||
.parse_qopt = taprio_parse_opt,
|
||||
.print_qopt = taprio_print_opt,
|
||||
.print_xstats = taprio_print_xstats,
|
||||
};
|
||||
|
||||
@ -170,7 +170,7 @@ int tc_calc_rtable_64(struct tc_ratespec *r, __u32 *rtab,
|
||||
rtab[i] = tc_calc_xmittime(bps, sz);
|
||||
}
|
||||
|
||||
r->cell_align = -1;
|
||||
r->cell_align = -1;
|
||||
r->cell_log = cell_log;
|
||||
r->linklayer = (linklayer & TC_LINKLAYER_MASK);
|
||||
return cell_log;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user