|
Packit Service |
3880ab |
/*
|
|
Packit Service |
3880ab |
* q_taprio.c Time Aware Priority Scheduler
|
|
Packit Service |
3880ab |
*
|
|
Packit Service |
3880ab |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
3880ab |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
3880ab |
* as published by the Free Software Foundation; either version
|
|
Packit Service |
3880ab |
* 2 of the License, or (at your option) any later version.
|
|
Packit Service |
3880ab |
*
|
|
Packit Service |
3880ab |
* Authors: Vinicius Costa Gomes <vinicius.gomes@intel.com>
|
|
Packit Service |
3880ab |
* Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
|
|
Packit Service |
3880ab |
*/
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#include <stdio.h>
|
|
Packit Service |
3880ab |
#include <stdlib.h>
|
|
Packit Service |
3880ab |
#include <unistd.h>
|
|
Packit Service |
3880ab |
#include <syslog.h>
|
|
Packit Service |
3880ab |
#include <fcntl.h>
|
|
Packit Service |
3880ab |
#include <inttypes.h>
|
|
Packit Service |
3880ab |
#include <sys/socket.h>
|
|
Packit Service |
3880ab |
#include <netinet/in.h>
|
|
Packit Service |
3880ab |
#include <arpa/inet.h>
|
|
Packit Service |
3880ab |
#include <string.h>
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#include "utils.h"
|
|
Packit Service |
3880ab |
#include "tc_util.h"
|
|
Packit Service |
3880ab |
#include "list.h"
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
struct sched_entry {
|
|
Packit Service |
3880ab |
struct list_head list;
|
|
Packit Service |
3880ab |
uint32_t index;
|
|
Packit Service |
3880ab |
uint32_t interval;
|
|
Packit Service |
3880ab |
uint32_t gatemask;
|
|
Packit Service |
3880ab |
uint8_t cmd;
|
|
Packit Service |
3880ab |
};
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#define CLOCKID_INVALID (-1)
|
|
Packit Service |
3880ab |
static const struct static_clockid {
|
|
Packit Service |
3880ab |
const char *name;
|
|
Packit Service |
3880ab |
clockid_t clockid;
|
|
Packit Service |
3880ab |
} clockids_sysv[] = {
|
|
Packit Service |
3880ab |
{ "REALTIME", CLOCK_REALTIME },
|
|
Packit Service |
3880ab |
{ "TAI", CLOCK_TAI },
|
|
Packit Service |
3880ab |
{ "BOOTTIME", CLOCK_BOOTTIME },
|
|
Packit Service |
3880ab |
{ "MONOTONIC", CLOCK_MONOTONIC },
|
|
Packit Service |
3880ab |
{ NULL }
|
|
Packit Service |
3880ab |
};
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static void explain(void)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
fprintf(stderr,
|
|
Packit Service |
3880ab |
"Usage: ... taprio clockid CLOCKID\n"
|
|
Packit Service |
3880ab |
" [num_tc NUMBER] [map P0 P1 ...] "
|
|
Packit Service |
3880ab |
" [queues COUNT@OFFSET COUNT@OFFSET COUNT@OFFSET ...] "
|
|
Packit Service |
3880ab |
" [ [sched-entry index cmd gate-mask interval] ... ] "
|
|
Packit Service |
3880ab |
" [base-time time] [txtime-delay delay]"
|
|
Packit Service |
3880ab |
"\n"
|
|
Packit Service |
3880ab |
"CLOCKID must be a valid SYS-V id (i.e. CLOCK_TAI)\n");
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static void explain_clockid(const char *val)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
fprintf(stderr, "taprio: illegal value for \"clockid\": \"%s\".\n", val);
|
|
Packit Service |
3880ab |
fprintf(stderr, "It must be a valid SYS-V id (i.e. CLOCK_TAI)\n");
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int get_clockid(__s32 *val, const char *arg)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
const struct static_clockid *c;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
/* Drop the CLOCK_ prefix if that is being used. */
|
|
Packit Service |
3880ab |
if (strcasestr(arg, "CLOCK_") != NULL)
|
|
Packit Service |
3880ab |
arg += sizeof("CLOCK_") - 1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (c = clockids_sysv; c->name; c++) {
|
|
Packit Service |
3880ab |
if (strcasecmp(c->name, arg) == 0) {
|
|
Packit Service |
3880ab |
*val = c->clockid;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static const char* get_clock_name(clockid_t clockid)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
const struct static_clockid *c;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (c = clockids_sysv; c->name; c++) {
|
|
Packit Service |
3880ab |
if (clockid == c->clockid)
|
|
Packit Service |
3880ab |
return c->name;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return "invalid";
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static const char *entry_cmd_to_str(__u8 cmd)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
switch (cmd) {
|
|
Packit Service |
3880ab |
case TC_TAPRIO_CMD_SET_GATES:
|
|
Packit Service |
3880ab |
return "S";
|
|
Packit Service |
3880ab |
default:
|
|
Packit Service |
3880ab |
return "Invalid";
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int str_to_entry_cmd(const char *str)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
if (strcmp(str, "S") == 0)
|
|
Packit Service |
3880ab |
return TC_TAPRIO_CMD_SET_GATES;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int add_sched_list(struct list_head *sched_entries, struct nlmsghdr *n)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct sched_entry *e;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
list_for_each_entry(e, sched_entries, list) {
|
|
Packit Service |
3880ab |
struct rtattr *a;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
a = addattr_nest(n, 1024, TCA_TAPRIO_SCHED_ENTRY);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_SCHED_ENTRY_CMD, &e->cmd, sizeof(e->cmd));
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, &e->gatemask, sizeof(e->gatemask));
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_SCHED_ENTRY_INTERVAL, &e->interval, sizeof(e->interval));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
addattr_nest_end(n, a);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static void explain_sched_entry(void)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
fprintf(stderr, "Usage: ... taprio ... sched-entry <cmd> <gate mask> <interval>\n");
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static struct sched_entry *create_entry(uint32_t gatemask, uint32_t interval, uint8_t cmd)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct sched_entry *e;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
e = calloc(1, sizeof(*e));
|
|
Packit Service |
3880ab |
if (!e)
|
|
Packit Service |
3880ab |
return NULL;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
e->gatemask = gatemask;
|
|
Packit Service |
3880ab |
e->interval = interval;
|
|
Packit Service |
3880ab |
e->cmd = cmd;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return e;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int taprio_parse_opt(struct qdisc_util *qu, int argc,
|
|
Packit Service |
3880ab |
char **argv, struct nlmsghdr *n, const char *dev)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
__s32 clockid = CLOCKID_INVALID;
|
|
Packit Service |
3880ab |
struct tc_mqprio_qopt opt = { };
|
|
Packit Service |
3880ab |
__s64 cycle_time_extension = 0;
|
|
Packit Service |
3880ab |
struct list_head sched_entries;
|
|
Packit Service |
3880ab |
struct rtattr *tail, *l;
|
|
Packit Service |
3880ab |
__u32 taprio_flags = 0;
|
|
Packit Service |
3880ab |
__u32 txtime_delay = 0;
|
|
Packit Service |
3880ab |
__s64 cycle_time = 0;
|
|
Packit Service |
3880ab |
__s64 base_time = 0;
|
|
Packit Service |
3880ab |
int err, idx;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
INIT_LIST_HEAD(&sched_entries);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
while (argc > 0) {
|
|
Packit Service |
3880ab |
idx = 0;
|
|
Packit Service |
3880ab |
if (strcmp(*argv, "num_tc") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_u8(&opt.num_tc, *argv, 10)) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "Illegal \"num_tc\"\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "map") == 0) {
|
|
Packit Service |
3880ab |
while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_u8(&opt.prio_tc_map[idx], *argv, 10)) {
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
break;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
idx++;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
for ( ; idx < TC_QOPT_MAX_QUEUE; idx++)
|
|
Packit Service |
3880ab |
opt.prio_tc_map[idx] = 0;
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "queues") == 0) {
|
|
Packit Service |
3880ab |
char *tmp, *tok;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
tmp = strdup(*argv);
|
|
Packit Service |
3880ab |
if (!tmp)
|
|
Packit Service |
3880ab |
break;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
tok = strtok(tmp, "@");
|
|
Packit Service |
3880ab |
if (get_u16(&opt.count[idx], tok, 10)) {
|
|
Packit Service |
3880ab |
free(tmp);
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
break;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
tok = strtok(NULL, "@");
|
|
Packit Service |
3880ab |
if (get_u16(&opt.offset[idx], tok, 10)) {
|
|
Packit Service |
3880ab |
free(tmp);
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
break;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
free(tmp);
|
|
Packit Service |
3880ab |
idx++;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "sched-entry") == 0) {
|
|
Packit Service |
3880ab |
uint32_t mask, interval;
|
|
Packit Service |
3880ab |
struct sched_entry *e;
|
|
Packit Service |
3880ab |
uint8_t cmd;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
err = str_to_entry_cmd(*argv);
|
|
Packit Service |
3880ab |
if (err < 0) {
|
|
Packit Service |
3880ab |
explain_sched_entry();
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
cmd = err;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_u32(&mask, *argv, 16)) {
|
|
Packit Service |
3880ab |
explain_sched_entry();
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_u32(&interval, *argv, 0)) {
|
|
Packit Service |
3880ab |
explain_sched_entry();
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
e = create_entry(mask, interval, cmd);
|
|
Packit Service |
3880ab |
if (!e) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "taprio: not enough memory for new schedule entry\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
list_add_tail(&e->list, &sched_entries);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "base-time") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_s64(&base_time, *argv, 10)) {
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
break;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "cycle-time") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (cycle_time) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "taprio: duplicate \"cycle-time\" specification\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (get_s64(&cycle_time, *argv, 10)) {
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
break;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "cycle-time-extension") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (cycle_time_extension) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "taprio: duplicate \"cycle-time-extension\" specification\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (get_s64(&cycle_time_extension, *argv, 10)) {
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
break;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "clockid") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (clockid != CLOCKID_INVALID) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "taprio: duplicate \"clockid\" specification\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
if (get_clockid(&clockid, *argv)) {
|
|
Packit Service |
3880ab |
explain_clockid(*argv);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "flags") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (taprio_flags) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "taprio: duplicate \"flags\" specification\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
if (get_u32(&taprio_flags, *argv, 0)) {
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "txtime-delay") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (txtime_delay != 0) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "taprio: duplicate \"txtime-delay\" specification\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
if (get_u32(&txtime_delay, *argv, 0)) {
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
} else if (strcmp(*argv, "help") == 0) {
|
|
Packit Service |
3880ab |
explain();
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
} else {
|
|
Packit Service |
3880ab |
fprintf(stderr, "Unknown argument\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
argc--; argv++;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
tail = NLMSG_TAIL(n);
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (clockid != CLOCKID_INVALID)
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_ATTR_SCHED_CLOCKID, &clockid, sizeof(clockid));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (taprio_flags)
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_ATTR_FLAGS, &taprio_flags, sizeof(taprio_flags));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (opt.num_tc > 0)
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_ATTR_PRIOMAP, &opt, sizeof(opt));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (txtime_delay)
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_ATTR_TXTIME_DELAY, &txtime_delay, sizeof(txtime_delay));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (base_time)
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_ATTR_SCHED_BASE_TIME, &base_time, sizeof(base_time));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (cycle_time)
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME,
|
|
Packit Service |
3880ab |
&cycle_time, sizeof(cycle_time));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (cycle_time_extension)
|
|
Packit Service |
3880ab |
addattr_l(n, 1024, TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION,
|
|
Packit Service |
3880ab |
&cycle_time_extension, sizeof(cycle_time_extension));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
l = addattr_nest(n, 1024, TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST | NLA_F_NESTED);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
err = add_sched_list(&sched_entries, n);
|
|
Packit Service |
3880ab |
if (err < 0) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "Could not add schedule to netlink message\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
addattr_nest_end(n, l);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int print_sched_list(FILE *f, struct rtattr *list)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct rtattr *item;
|
|
Packit Service |
3880ab |
int rem;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (list == NULL)
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
rem = RTA_PAYLOAD(list);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
open_json_array(PRINT_JSON, "schedule");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_nl();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (item = RTA_DATA(list); RTA_OK(item, rem); item = RTA_NEXT(item, rem)) {
|
|
Packit Service |
3880ab |
struct rtattr *tb[TCA_TAPRIO_SCHED_ENTRY_MAX + 1];
|
|
Packit Service |
3880ab |
__u32 index = 0, gatemask = 0, interval = 0;
|
|
Packit Service |
3880ab |
__u8 command = 0;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
parse_rtattr_nested(tb, TCA_TAPRIO_SCHED_ENTRY_MAX, item);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_SCHED_ENTRY_INDEX])
|
|
Packit Service |
3880ab |
index = rta_getattr_u32(tb[TCA_TAPRIO_SCHED_ENTRY_INDEX]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_SCHED_ENTRY_CMD])
|
|
Packit Service |
3880ab |
command = rta_getattr_u8(tb[TCA_TAPRIO_SCHED_ENTRY_CMD]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_SCHED_ENTRY_GATE_MASK])
|
|
Packit Service |
3880ab |
gatemask = rta_getattr_u32(tb[TCA_TAPRIO_SCHED_ENTRY_GATE_MASK]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL])
|
|
Packit Service |
3880ab |
interval = rta_getattr_u32(tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
open_json_object(NULL);
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "index", "\tindex %u", index);
|
|
Packit Service |
3880ab |
print_string(PRINT_ANY, "cmd", " cmd %s", entry_cmd_to_str(command));
|
|
Packit Service |
3880ab |
print_0xhex(PRINT_ANY, "gatemask", " gatemask %#llx", gatemask);
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "interval", " interval %u", interval);
|
|
Packit Service |
3880ab |
close_json_object();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_nl();
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
close_json_array(PRINT_ANY, "");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int print_schedule(FILE *f, struct rtattr **tb)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
int64_t base_time = 0, cycle_time = 0, cycle_time_extension = 0;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_ATTR_SCHED_BASE_TIME])
|
|
Packit Service |
3880ab |
base_time = rta_getattr_s64(tb[TCA_TAPRIO_ATTR_SCHED_BASE_TIME]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME])
|
|
Packit Service |
3880ab |
cycle_time = rta_getattr_s64(tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION])
|
|
Packit Service |
3880ab |
cycle_time_extension = rta_getattr_s64(
|
|
Packit Service |
3880ab |
tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_lluint(PRINT_ANY, "base_time", "\tbase-time %lld", base_time);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_lluint(PRINT_ANY, "cycle_time", " cycle-time %lld", cycle_time);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_lluint(PRINT_ANY, "cycle_time_extension",
|
|
Packit Service |
3880ab |
" cycle-time-extension %lld", cycle_time_extension);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_sched_list(f, tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int taprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct rtattr *tb[TCA_TAPRIO_ATTR_MAX + 1];
|
|
Packit Service |
3880ab |
struct tc_mqprio_qopt *qopt = 0;
|
|
Packit Service |
3880ab |
__s32 clockid = CLOCKID_INVALID;
|
|
Packit Service |
3880ab |
int i;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (opt == NULL)
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
parse_rtattr_nested(tb, TCA_TAPRIO_ATTR_MAX, opt);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_ATTR_PRIOMAP] == NULL)
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
qopt = RTA_DATA(tb[TCA_TAPRIO_ATTR_PRIOMAP]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "tc", "tc %u ", qopt->num_tc);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
open_json_array(PRINT_ANY, "map");
|
|
Packit Service |
3880ab |
for (i = 0; i <= TC_PRIO_MAX; i++)
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, NULL, " %u", qopt->prio_tc_map[i]);
|
|
Packit Service |
3880ab |
close_json_array(PRINT_ANY, "");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_nl();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
open_json_array(PRINT_ANY, "queues");
|
|
Packit Service |
3880ab |
for (i = 0; i < qopt->num_tc; i++) {
|
|
Packit Service |
3880ab |
open_json_object(NULL);
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "offset", " offset %u", qopt->offset[i]);
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "count", " count %u", qopt->count[i]);
|
|
Packit Service |
3880ab |
close_json_object();
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
close_json_array(PRINT_ANY, "");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_nl();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID])
|
|
Packit Service |
3880ab |
clockid = rta_getattr_s32(tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_string(PRINT_ANY, "clockid", "clockid %s", get_clock_name(clockid));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_ATTR_FLAGS]) {
|
|
Packit Service |
3880ab |
__u32 flags;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
flags = rta_getattr_u32(tb[TCA_TAPRIO_ATTR_FLAGS]);
|
|
Packit Service |
3880ab |
print_0xhex(PRINT_ANY, "flags", " flags %#x", flags);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]) {
|
|
Packit Service |
3880ab |
__u32 txtime_delay;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
txtime_delay = rta_getattr_s32(tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]);
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "txtime_delay", " txtime delay %d", txtime_delay);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_schedule(f, tb);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_TAPRIO_ATTR_ADMIN_SCHED]) {
|
|
Packit Service |
3880ab |
struct rtattr *t[TCA_TAPRIO_ATTR_MAX + 1];
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
parse_rtattr_nested(t, TCA_TAPRIO_ATTR_MAX,
|
|
Packit Service |
3880ab |
tb[TCA_TAPRIO_ATTR_ADMIN_SCHED]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
open_json_object(NULL);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_schedule(f, t);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
close_json_object();
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
struct qdisc_util taprio_qdisc_util = {
|
|
Packit Service |
3880ab |
.id = "taprio",
|
|
Packit Service |
3880ab |
.parse_qopt = taprio_parse_opt,
|
|
Packit Service |
3880ab |
.print_qopt = taprio_print_opt,
|
|
Packit Service |
3880ab |
};
|