|
Packit Service |
3880ab |
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
|
|
Packit Service |
3880ab |
/* Copyright 2020 NXP */
|
|
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 <string.h>
|
|
Packit Service |
3880ab |
#include <linux/if_ether.h>
|
|
Packit Service |
3880ab |
#include "utils.h"
|
|
Packit Service |
3880ab |
#include "rt_names.h"
|
|
Packit Service |
3880ab |
#include "tc_util.h"
|
|
Packit Service |
3880ab |
#include "list.h"
|
|
Packit Service |
3880ab |
#include <linux/tc_act/tc_gate.h>
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
struct gate_entry {
|
|
Packit Service |
3880ab |
struct list_head list;
|
|
Packit Service |
3880ab |
uint8_t gate_state;
|
|
Packit Service |
3880ab |
uint32_t interval;
|
|
Packit Service |
3880ab |
int32_t ipv;
|
|
Packit Service |
3880ab |
int32_t maxoctets;
|
|
Packit Service |
3880ab |
};
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#define CLOCKID_INVALID (-1)
|
|
Packit Service |
3880ab |
static const struct clockid_table {
|
|
Packit Service |
3880ab |
const char *name;
|
|
Packit Service |
3880ab |
clockid_t clockid;
|
|
Packit Service |
3880ab |
} clockt_map[] = {
|
|
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: gate [ priority PRIO-SPEC ] [ base-time BASE-TIME ]\n"
|
|
Packit Service |
3880ab |
" [ cycle-time CYCLE-TIME ]\n"
|
|
Packit Service |
3880ab |
" [ cycle-time-ext CYCLE-TIME-EXT ]\n"
|
|
Packit Service |
3880ab |
" [ clockid CLOCKID ] [flags FLAGS]\n"
|
|
Packit Service |
3880ab |
" [ sched-entry GATE0 INTERVAL [ INTERNAL-PRIO-VALUE MAX-OCTETS ] ]\n"
|
|
Packit Service |
3880ab |
" [ sched-entry GATE1 INTERVAL [ INTERNAL-PRIO-VALUE MAX-OCTETS ] ]\n"
|
|
Packit Service |
3880ab |
" ......\n"
|
|
Packit Service |
3880ab |
" [ sched-entry GATEn INTERVAL [ INTERNAL-PRIO-VALUE MAX-OCTETS ] ]\n"
|
|
Packit Service |
3880ab |
" [ CONTROL ]\n"
|
|
Packit Service |
3880ab |
" GATEn := open | close\n"
|
|
Packit Service |
3880ab |
" INTERVAL : nanoseconds period of gate slot\n"
|
|
Packit Service |
3880ab |
" INTERNAL-PRIO-VALUE : internal priority decide which\n"
|
|
Packit Service |
3880ab |
" rx queue number direct to.\n"
|
|
Packit Service |
3880ab |
" default to be -1 which means wildcard.\n"
|
|
Packit Service |
3880ab |
" MAX-OCTETS : maximum number of MSDU octets that are\n"
|
|
Packit Service |
3880ab |
" permitted to pas the gate during the\n"
|
|
Packit Service |
3880ab |
" specified TimeInterval.\n"
|
|
Packit Service |
3880ab |
" default to be -1 which means wildcard.\n"
|
|
Packit Service |
3880ab |
" CONTROL := pipe | drop | continue | pass |\n"
|
|
Packit Service |
3880ab |
" goto chain <CHAIN_INDEX>\n");
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static void usage(void)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
explain();
|
|
Packit Service |
3880ab |
exit(-1);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static void explain_entry_format(void)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
fprintf(stderr, "Usage: sched-entry <open | close> <interval> [ <interval ipv> <octets max bytes> ]\n");
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int parse_gate(struct action_util *a, int *argc_p, char ***argv_p,
|
|
Packit Service |
3880ab |
int tca_id, struct nlmsghdr *n);
|
|
Packit Service |
3880ab |
static int print_gate(struct action_util *au, FILE *f, struct rtattr *arg);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
struct action_util gate_action_util = {
|
|
Packit Service |
3880ab |
.id = "gate",
|
|
Packit Service |
3880ab |
.parse_aopt = parse_gate,
|
|
Packit Service |
3880ab |
.print_aopt = print_gate,
|
|
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 clockid_table *c;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (strcasestr(arg, "CLOCK_") != NULL)
|
|
Packit Service |
3880ab |
arg += sizeof("CLOCK_") - 1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (c = clockt_map; c->name; c++) {
|
|
Packit Service |
3880ab |
if (strcasecmp(c->name, arg) == 0) {
|
|
Packit Service |
3880ab |
*val = c->clockid;
|
|
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 clockid_table *c;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (c = clockt_map; 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 int get_gate_state(__u8 *val, const char *arg)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
if (!strcasecmp("OPEN", arg)) {
|
|
Packit Service |
3880ab |
*val = 1;
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!strcasecmp("CLOSE", arg)) {
|
|
Packit Service |
3880ab |
*val = 0;
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static struct gate_entry *create_gate_entry(uint8_t gate_state,
|
|
Packit Service |
3880ab |
uint32_t interval,
|
|
Packit Service |
3880ab |
int32_t ipv,
|
|
Packit Service |
3880ab |
int32_t maxoctets)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct gate_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->gate_state = gate_state;
|
|
Packit Service |
3880ab |
e->interval = interval;
|
|
Packit Service |
3880ab |
e->ipv = ipv;
|
|
Packit Service |
3880ab |
e->maxoctets = maxoctets;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return e;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int add_gate_list(struct list_head *gate_entries, struct nlmsghdr *n)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct gate_entry *e;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
list_for_each_entry(e, gate_entries, list) {
|
|
Packit Service |
3880ab |
struct rtattr *a;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
a = addattr_nest(n, 1024, TCA_GATE_ONE_ENTRY | NLA_F_NESTED);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (e->gate_state)
|
|
Packit Service |
3880ab |
addattr(n, MAX_MSG, TCA_GATE_ENTRY_GATE);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_ENTRY_INTERVAL,
|
|
Packit Service |
3880ab |
&e->interval, sizeof(e->interval));
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_ENTRY_IPV,
|
|
Packit Service |
3880ab |
&e->ipv, sizeof(e->ipv));
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_ENTRY_MAX_OCTETS,
|
|
Packit Service |
3880ab |
&e->maxoctets, sizeof(e->maxoctets));
|
|
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 free_entries(struct list_head *gate_entries)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct gate_entry *e, *n;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
list_for_each_entry_safe(e, n, gate_entries, list) {
|
|
Packit Service |
3880ab |
list_del(&e->list);
|
|
Packit Service |
3880ab |
free(e);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int parse_gate(struct action_util *a, int *argc_p, char ***argv_p,
|
|
Packit Service |
3880ab |
int tca_id, struct nlmsghdr *n)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct tc_gate parm = {.action = TC_ACT_PIPE};
|
|
Packit Service |
3880ab |
struct list_head gate_entries;
|
|
Packit Service |
3880ab |
__s32 clockid = CLOCKID_INVALID;
|
|
Packit Service |
3880ab |
struct rtattr *tail, *nle;
|
|
Packit Service |
3880ab |
char **argv = *argv_p;
|
|
Packit Service |
3880ab |
int argc = *argc_p;
|
|
Packit Service |
3880ab |
__s64 base_time = 0;
|
|
Packit Service |
3880ab |
__s64 cycle_time = 0;
|
|
Packit Service |
3880ab |
__s64 cycle_time_ext = 0;
|
|
Packit Service |
3880ab |
int entry_num = 0;
|
|
Packit Service |
3880ab |
char *invalidarg;
|
|
Packit Service |
3880ab |
__u32 flags = 0;
|
|
Packit Service |
3880ab |
int prio = -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
int err;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (matches(*argv, "gate") != 0)
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (argc <= 0)
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
INIT_LIST_HEAD(&gate_entries);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
while (argc > 0) {
|
|
Packit Service |
3880ab |
if (matches(*argv, "index") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_u32(&parm.index, *argv, 10)) {
|
|
Packit Service |
3880ab |
invalidarg = "index";
|
|
Packit Service |
3880ab |
goto err_arg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (matches(*argv, "priority") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_s32(&prio, *argv, 0)) {
|
|
Packit Service |
3880ab |
invalidarg = "priority";
|
|
Packit Service |
3880ab |
goto err_arg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (matches(*argv, "base-time") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_s64(&base_time, *argv, 10) &&
|
|
Packit Service |
3880ab |
get_time64(&base_time, *argv)) {
|
|
Packit Service |
3880ab |
invalidarg = "base-time";
|
|
Packit Service |
3880ab |
goto err_arg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (matches(*argv, "cycle-time") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_s64(&cycle_time, *argv, 10) &&
|
|
Packit Service |
3880ab |
get_time64(&cycle_time, *argv)) {
|
|
Packit Service |
3880ab |
invalidarg = "cycle-time";
|
|
Packit Service |
3880ab |
goto err_arg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (matches(*argv, "cycle-time-ext") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_s64(&cycle_time_ext, *argv, 10) &&
|
|
Packit Service |
3880ab |
get_time64(&cycle_time_ext, *argv)) {
|
|
Packit Service |
3880ab |
invalidarg = "cycle-time-ext";
|
|
Packit Service |
3880ab |
goto err_arg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (matches(*argv, "clockid") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_clockid(&clockid, *argv)) {
|
|
Packit Service |
3880ab |
invalidarg = "clockid";
|
|
Packit Service |
3880ab |
goto err_arg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (matches(*argv, "flags") == 0) {
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
if (get_u32(&flags, *argv, 0)) {
|
|
Packit Service |
3880ab |
invalidarg = "flags";
|
|
Packit Service |
3880ab |
goto err_arg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
} else if (matches(*argv, "sched-entry") == 0) {
|
|
Packit Service |
3880ab |
unsigned int maxoctets_uint = 0;
|
|
Packit Service |
3880ab |
int32_t maxoctets = -1;
|
|
Packit Service |
3880ab |
struct gate_entry *e;
|
|
Packit Service |
3880ab |
uint8_t gate_state = 0;
|
|
Packit Service |
3880ab |
__s64 interval_s64 = 0;
|
|
Packit Service |
3880ab |
uint32_t interval = 0;
|
|
Packit Service |
3880ab |
int32_t ipv = -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!NEXT_ARG_OK()) {
|
|
Packit Service |
3880ab |
explain_entry_format();
|
|
Packit Service |
3880ab |
fprintf(stderr, "\"sched-entry\" is imcomplete\n");
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (get_gate_state(&gate_state, *argv)) {
|
|
Packit Service |
3880ab |
explain_entry_format();
|
|
Packit Service |
3880ab |
fprintf(stderr, "\"sched-entry\" is imcomplete\n");
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!NEXT_ARG_OK()) {
|
|
Packit Service |
3880ab |
explain_entry_format();
|
|
Packit Service |
3880ab |
fprintf(stderr, "\"sched-entry\" is imcomplete\n");
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (get_u32(&interval, *argv, 0) &&
|
|
Packit Service |
3880ab |
get_time64(&interval_s64, *argv)) {
|
|
Packit Service |
3880ab |
explain_entry_format();
|
|
Packit Service |
3880ab |
fprintf(stderr, "\"sched-entry\" is imcomplete\n");
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (interval_s64 > UINT_MAX) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "\"interval\" is too large\n");
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
} else if (interval_s64) {
|
|
Packit Service |
3880ab |
interval = interval_s64;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!NEXT_ARG_OK())
|
|
Packit Service |
3880ab |
goto create_entry;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (get_s32(&ipv, *argv, 0)) {
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
goto create_entry;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!gate_state)
|
|
Packit Service |
3880ab |
ipv = -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!NEXT_ARG_OK())
|
|
Packit Service |
3880ab |
goto create_entry;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
NEXT_ARG();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (get_s32(&maxoctets, *argv, 0) &&
|
|
Packit Service |
3880ab |
get_size(&maxoctets_uint, *argv))
|
|
Packit Service |
3880ab |
PREV_ARG();
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (maxoctets_uint > INT_MAX) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "\"maxoctets\" is too large\n");
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
} else if (maxoctets_uint ) {
|
|
Packit Service |
3880ab |
maxoctets = maxoctets_uint;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!gate_state)
|
|
Packit Service |
3880ab |
maxoctets = -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
create_entry:
|
|
Packit Service |
3880ab |
e = create_gate_entry(gate_state, interval,
|
|
Packit Service |
3880ab |
ipv, maxoctets);
|
|
Packit Service |
3880ab |
if (!e) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "gate: not enough memory\n");
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
list_add_tail(&e->list, &gate_entries);
|
|
Packit Service |
3880ab |
entry_num++;
|
|
Packit Service |
3880ab |
} else if (matches(*argv, "help") == 0) {
|
|
Packit Service |
3880ab |
usage();
|
|
Packit Service |
3880ab |
} else {
|
|
Packit Service |
3880ab |
break;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
argc--;
|
|
Packit Service |
3880ab |
argv++;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
parse_action_control_dflt(&argc, &argv, &parm.action,
|
|
Packit Service |
3880ab |
false, TC_ACT_PIPE);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!entry_num && !parm.index) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "gate: must add at least one entry\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
tail = addattr_nest(n, MAX_MSG, tca_id | NLA_F_NESTED);
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_PARMS, &parm, sizeof(parm));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (prio != -1)
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_PRIORITY, &prio, sizeof(prio));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (flags)
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_FLAGS, &flags, sizeof(flags));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (base_time)
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_BASE_TIME,
|
|
Packit Service |
3880ab |
&base_time, sizeof(base_time));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (cycle_time)
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_CYCLE_TIME,
|
|
Packit Service |
3880ab |
&cycle_time, sizeof(cycle_time));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (cycle_time_ext)
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_CYCLE_TIME_EXT,
|
|
Packit Service |
3880ab |
&cycle_time_ext, sizeof(cycle_time_ext));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (clockid != CLOCKID_INVALID)
|
|
Packit Service |
3880ab |
addattr_l(n, MAX_MSG, TCA_GATE_CLOCKID,
|
|
Packit Service |
3880ab |
&clockid, sizeof(clockid));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
nle = addattr_nest(n, MAX_MSG, TCA_GATE_ENTRY_LIST | NLA_F_NESTED);
|
|
Packit Service |
3880ab |
err = add_gate_list(&gate_entries, n);
|
|
Packit Service |
3880ab |
if (err < 0) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "Could not add entries to netlink message\n");
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
addattr_nest_end(n, nle);
|
|
Packit Service |
3880ab |
addattr_nest_end(n, tail);
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
*argc_p = argc;
|
|
Packit Service |
3880ab |
*argv_p = argv;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
err_arg:
|
|
Packit Service |
3880ab |
invarg(invalidarg, *argv);
|
|
Packit Service |
3880ab |
free_entries(&gate_entries);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int print_gate_list(struct rtattr *list)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct rtattr *item;
|
|
Packit Service |
3880ab |
int rem;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
rem = RTA_PAYLOAD(list);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "%s", _SL_);
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "\tschedule:%s", _SL_);
|
|
Packit Service |
3880ab |
open_json_array(PRINT_JSON, "schedule");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (item = RTA_DATA(list);
|
|
Packit Service |
3880ab |
RTA_OK(item, rem);
|
|
Packit Service |
3880ab |
item = RTA_NEXT(item, rem)) {
|
|
Packit Service |
3880ab |
struct rtattr *tb[TCA_GATE_ENTRY_MAX + 1];
|
|
Packit Service |
3880ab |
__u32 index = 0, interval = 0;
|
|
Packit Service |
3880ab |
__u8 gate_state = 0;
|
|
Packit Service |
3880ab |
__s32 ipv = -1, maxoctets = -1;
|
|
Packit Service |
3880ab |
char buf[22];
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
parse_rtattr_nested(tb, TCA_GATE_ENTRY_MAX, item);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_ENTRY_INDEX])
|
|
Packit Service |
3880ab |
index = rta_getattr_u32(tb[TCA_GATE_ENTRY_INDEX]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_ENTRY_GATE])
|
|
Packit Service |
3880ab |
gate_state = 1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_ENTRY_INTERVAL])
|
|
Packit Service |
3880ab |
interval = rta_getattr_u32(tb[TCA_GATE_ENTRY_INTERVAL]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_ENTRY_IPV])
|
|
Packit Service |
3880ab |
ipv = rta_getattr_s32(tb[TCA_GATE_ENTRY_IPV]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_ENTRY_MAX_OCTETS])
|
|
Packit Service |
3880ab |
maxoctets = rta_getattr_s32(tb[TCA_GATE_ENTRY_MAX_OCTETS]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
open_json_object(NULL);
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "number", "\t number %4u", index);
|
|
Packit Service |
3880ab |
print_string(PRINT_ANY, "gate_state", "\tgate-state %s ",
|
|
Packit Service |
3880ab |
gate_state ? "open" : "close");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_uint(PRINT_JSON, "interval", NULL, interval);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "\tinterval %s",
|
|
Packit Service |
3880ab |
sprint_time64(interval, buf));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (ipv != -1) {
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "ipv", "\t ipv %-10u", ipv);
|
|
Packit Service |
3880ab |
} else {
|
|
Packit Service |
3880ab |
print_int(PRINT_JSON, "ipv", NULL, ipv);
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "\t ipv %s", "wildcard");
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (maxoctets != -1) {
|
|
Packit Service |
3880ab |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
3880ab |
print_uint(PRINT_JSON, "max_octets", NULL, maxoctets);
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "\t max-octets %s",
|
|
Packit Service |
3880ab |
sprint_size(maxoctets, buf));
|
|
Packit Service |
3880ab |
} else {
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL,
|
|
Packit Service |
3880ab |
"\t max-octets %s", "wildcard");
|
|
Packit Service |
3880ab |
print_int(PRINT_JSON, "max_octets", NULL, maxoctets);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
close_json_object();
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "%s", _SL_);
|
|
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_gate(struct action_util *au, FILE *f, struct rtattr *arg)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct tc_gate *parm;
|
|
Packit Service |
3880ab |
struct rtattr *tb[TCA_GATE_MAX + 1];
|
|
Packit Service |
3880ab |
__s32 clockid = CLOCKID_INVALID;
|
|
Packit Service |
3880ab |
__s64 base_time = 0;
|
|
Packit Service |
3880ab |
__s64 cycle_time = 0;
|
|
Packit Service |
3880ab |
__s64 cycle_time_ext = 0;
|
|
Packit Service |
3880ab |
char buf[22];
|
|
Packit Service |
3880ab |
int prio = -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (arg == NULL)
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
parse_rtattr_nested(tb, TCA_GATE_MAX, arg);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!tb[TCA_GATE_PARMS]) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "Missing gate parameters\n");
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "%s", "\n");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
parm = RTA_DATA(tb[TCA_GATE_PARMS]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_PRIORITY])
|
|
Packit Service |
3880ab |
prio = rta_getattr_s32(tb[TCA_GATE_PRIORITY]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (prio != -1) {
|
|
Packit Service |
3880ab |
print_int(PRINT_ANY, "priority", "\tpriority %-8d", prio);
|
|
Packit Service |
3880ab |
} else {
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "\tpriority %s", "wildcard");
|
|
Packit Service |
3880ab |
print_int(PRINT_JSON, "priority", NULL, prio);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_CLOCKID])
|
|
Packit Service |
3880ab |
clockid = rta_getattr_s32(tb[TCA_GATE_CLOCKID]);
|
|
Packit Service |
3880ab |
print_string(PRINT_ANY, "clockid", "\tclockid %s",
|
|
Packit Service |
3880ab |
get_clock_name(clockid));
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_FLAGS]) {
|
|
Packit Service |
3880ab |
__u32 flags;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
flags = rta_getattr_u32(tb[TCA_GATE_FLAGS]);
|
|
Packit Service |
3880ab |
print_0xhex(PRINT_ANY, "flags", "\tflags %#x", flags);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "%s", "\n");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_BASE_TIME])
|
|
Packit Service |
3880ab |
base_time = rta_getattr_s64(tb[TCA_GATE_BASE_TIME]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "\tbase-time %s",
|
|
Packit Service |
3880ab |
sprint_time64(base_time, buf));
|
|
Packit Service |
3880ab |
print_lluint(PRINT_JSON, "base_time", NULL, base_time);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_CYCLE_TIME])
|
|
Packit Service |
3880ab |
cycle_time = rta_getattr_s64(tb[TCA_GATE_CYCLE_TIME]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL,
|
|
Packit Service |
3880ab |
"\tcycle-time %s", sprint_time64(cycle_time, buf));
|
|
Packit Service |
3880ab |
print_lluint(PRINT_JSON, "cycle_time", NULL, cycle_time);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_CYCLE_TIME_EXT])
|
|
Packit Service |
3880ab |
cycle_time_ext = rta_getattr_s64(tb[TCA_GATE_CYCLE_TIME_EXT]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "\tcycle-time-ext %s",
|
|
Packit Service |
3880ab |
sprint_time64(cycle_time_ext, buf));
|
|
Packit Service |
3880ab |
print_lluint(PRINT_JSON, "cycle_time_ext", NULL, cycle_time_ext);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_ENTRY_LIST])
|
|
Packit Service |
3880ab |
print_gate_list(tb[TCA_GATE_ENTRY_LIST]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_action_control(f, "\t", parm->action, "");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_uint(PRINT_ANY, "index", "\n\t index %u", parm->index);
|
|
Packit Service |
3880ab |
print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
|
|
Packit Service |
3880ab |
print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (show_stats) {
|
|
Packit Service |
3880ab |
if (tb[TCA_GATE_TM]) {
|
|
Packit Service |
3880ab |
struct tcf_t *tm = RTA_DATA(tb[TCA_GATE_TM]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_tm(f, tm);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
print_string(PRINT_FP, NULL, "%s", "\n");
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|