Merge branch 'master' into net-next

This commit is contained in:
Stephen Hemminger 2017-11-28 09:53:28 -08:00
commit f6351157b9
144 changed files with 1133 additions and 588 deletions

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
# Top level Makefile for iproute2
ifeq ($(VERBOSE),0)

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
BROBJ = bridge.o fdb.o monitor.o link.o mdb.o vlan.o
include ../config.mk

View File

@ -1,3 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
#define MDB_RTA(r) \
((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(struct br_mdb_entry))))

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Get/set/delete bridge with netlink
*

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Get/set/delete fdb table with netlink
*

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Get mdb table with netlink
*/

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

1
configure vendored
View File

@ -1,4 +1,5 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# This is not an autoconf generated configure
#
INCLUDE=${1:-"$PWD/include"}

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
include ../config.mk
ifeq ($(HAVE_MNL),y)

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include "../../include/bpf_api.h"
#define ENTRY_INIT 3

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
GENLOBJ=genl.o
include ../config.mk

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _TC_UTIL_H_
#define _TC_UTIL_H_ 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file creates a dummy version of dynamic loading
* for environments where dynamic linking

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __BPF_API__
#define __BPF_API__

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __BPF_ELF__
#define __BPF_ELF__

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __BPF_SCM__
#define __BPF_SCM__

View File

@ -56,13 +56,29 @@ struct bpf_cfg_ops {
void (*ebpf_cb)(void *nl, int fd, const char *annotation);
};
enum bpf_mode {
CBPF_BYTECODE,
CBPF_FILE,
EBPF_OBJECT,
EBPF_PINNED,
BPF_MODE_MAX,
};
struct bpf_cfg_in {
const char *object;
const char *section;
const char *uds;
enum bpf_prog_type type;
enum bpf_mode mode;
__u32 ifindex;
bool verbose;
int argc;
char **argv;
struct sock_filter *ops;
struct sock_filter opcodes[BPF_MAXINSNS];
union {
int n_opcodes;
int prog_fd;
};
};
/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
@ -244,8 +260,11 @@ struct bpf_cfg_in {
.off = 0, \
.imm = 0 })
int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
const struct bpf_cfg_ops *ops, void *nl);
int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops);
int bpf_load_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops,
void *nl);
int bpf_parse_and_load_common(struct bpf_cfg_in *cfg,
const struct bpf_cfg_ops *ops, void *nl);
const char *bpf_prog_to_default_section(enum bpf_prog_type type);

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __COLOR_H__
#define __COLOR_H__ 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Stub dlfcn implementation for systems that lack shared library support
* but obviously can still reference compiled-in symbols.

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _IP6TABLES_USER_H
#define _IP6TABLES_USER_H

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _IPTABLES_USER_H
#define _IPTABLES_USER_H

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef IPTABLES_INTERNAL_H
#define IPTABLES_INTERNAL_H 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBGENL_H__
#define __LIBGENL_H__

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* This is the userspace/kernel interface for Generic IP Chains,
required for libc6. */
#ifndef _FWCHAINS_KERNEL_HEADERS_H

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LIBIP6TC_H
#define _LIBIP6TC_H
/* Library which manipulates firewall rules. Version 0.2. */

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LIBIPTC_H
#define _LIBIPTC_H
/* Library which manipulates filtering rules. */

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LIBXTC_H
#define _LIBXTC_H
/* Library which manipulates filtering rules. */

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LIBXTC_SHARED_H
#define _LIBXTC_SHARED_H 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBNETLINK_H__
#define __LIBNETLINK_H__ 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIST_H__
#define __LIST_H__ 1
/* List and hash list stuff from kernel */

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LL_MAP_H__
#define __LL_MAP_H__ 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef DB_NAMES_H_
#define DB_NAMES_H_ 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NAMESPACE_H__
#define __NAMESPACE_H__ 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef RT_NAMES_H_
#define RT_NAMES_H_ 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __RTM_MAP_H__
#define __RTM_MAP_H__ 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __UTILS_H__
#define __UTILS_H__ 1
@ -88,6 +89,8 @@ int get_prefix(inet_prefix *dst, char *arg, int family);
int mask2bits(__u32 netmask);
int get_addr_ila(__u64 *val, const char *arg);
int read_prop(const char *dev, char *prop, long *value);
int parse_percent(double *val, const char *str);
int get_hex(char c);
int get_integer(int *val, const char *arg, int base);
int get_unsigned(unsigned *val, const char *arg, int base);

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _XTABLES_INTERNAL_H
#define _XTABLES_INTERNAL_H 1

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _XTABLES_H
#define _XTABLES_H

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \
ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \

View File

@ -1,4 +1,5 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
CheckForwarding () {
local sbase fwd

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ILA_COMMON_H_
#define _ILA_COMMON_H_

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _IP_COMMON_H_
#define _IP_COMMON_H_

View File

@ -631,8 +631,8 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
bool offload = strcmp(*argv, "xdpoffload") == 0;
NEXT_ARG();
if (xdp_parse(&argc, &argv, req, generic, drv,
offload))
if (xdp_parse(&argc, &argv, req, dev_index,
generic, drv, offload))
exit(-1);
} else if (strcmp(*argv, "netns") == 0) {
NEXT_ARG();

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <stdlib.h>

View File

@ -345,7 +345,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
return -1;
}
if (!metadata && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) {
if (!metadata && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID) && !set_op) {
fprintf(stderr, "vxlan: missing virtual network identifier\n");
return -1;
}
@ -367,7 +367,8 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
"Use 'dstport 0' to get default and quiet this message\n");
}
addattr32(n, 1024, IFLA_VXLAN_ID, vni);
if (VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID))
addattr32(n, 1024, IFLA_VXLAN_ID, vni);
if (gaddr)
addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
else if (daddr)

View File

@ -48,10 +48,11 @@ static int xdp_delete(struct xdp_req *xdp)
return 0;
}
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
bool drv, bool offload)
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, __u32 ifindex,
bool generic, bool drv, bool offload)
{
struct bpf_cfg_in cfg = {
.type = BPF_PROG_TYPE_XDP,
.argc = *argc,
.argv = *argv,
};
@ -59,6 +60,12 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
.req = req,
};
if (offload) {
if (!ifindex)
incomplete_command();
cfg.ifindex = ifindex;
}
if (!force)
xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST;
if (generic)
@ -74,7 +81,7 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
return xdp_delete(&xdp);
}
if (bpf_parse_common(BPF_PROG_TYPE_XDP, &cfg, &bpf_cb_ops, &xdp))
if (bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &xdp))
return -1;
*argc = cfg.argc;

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#define _ATFILE_SOURCE
#include <sys/types.h>
#include <sys/stat.h>

View File

@ -886,6 +886,7 @@ static int lwt_parse_bpf(struct rtattr *rta, size_t len,
int attr, const enum bpf_prog_type bpf_type)
{
struct bpf_cfg_in cfg = {
.type = bpf_type,
.argc = *argcp,
.argv = *argvp,
};
@ -897,7 +898,7 @@ static int lwt_parse_bpf(struct rtattr *rta, size_t len,
int err;
nest = rta_nest(rta, len, attr);
err = bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, &x);
err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x);
if (err < 0) {
fprintf(stderr, "Failed to parse eBPF program: %s\n",
strerror(-err));

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LWTUNNEL_H__
#define __LETUNNEL_H__ 1

View File

@ -223,38 +223,6 @@ static int do_del(int argc, char **argv)
return tap_del_ioctl(&ifr);
}
static int read_prop(char *dev, char *prop, long *value)
{
char fname[IFNAMSIZ+25], buf[80], *endp;
ssize_t len;
int fd;
long result;
sprintf(fname, "/sys/class/net/%s/%s", dev, prop);
fd = open(fname, O_RDONLY);
if (fd < 0) {
if (strcmp(prop, "tun_flags"))
fprintf(stderr, "open %s: %s\n", fname,
strerror(errno));
return -1;
}
len = read(fd, buf, sizeof(buf)-1);
close(fd);
if (len < 0) {
fprintf(stderr, "read %s: %s", fname, strerror(errno));
return -1;
}
buf[len] = 0;
result = strtol(buf, &endp, 0);
if (*endp != '\n') {
fprintf(stderr, "Failed to parse %s\n", fname);
return -1;
}
*value = result;
return 0;
}
static void print_flags(long flags)
{
if (flags & IFF_TUN)

View File

@ -276,7 +276,8 @@ get_failed:
if (uval > 255)
invarg("TTL must be <= 255\n", *argv);
ttl = uval;
}
} else
ttl = 0;
} else if (!matches(*argv, "tos") ||
!matches(*argv, "tclass") ||
!matches(*argv, "dsfield")) {

View File

@ -372,7 +372,7 @@ get_failed:
} else {
__u8 uval;
if (get_u8(&uval, *argv, 0) < -1)
if (get_u8(&uval, *argv, 0))
invarg("invalid ELIM", *argv);
encap_limit = uval;
flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;

View File

@ -1,4 +1,5 @@
#! /bin/sh
# SPDX-License-Identifier: GPL-2.0
if [ -z "$*" ] ; then
exec ip -4 ro flush scope global type unicast

View File

@ -1,5 +1,5 @@
#!/bin/sh
#$Id$
# SPDX-License-Identifier: GPL-2.0
#
# Script created by: Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18

View File

@ -1,4 +1,5 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
exec tr "[\\\\]" "[
]"

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file creates a dummy version of dynamic loading
* for environments where dynamic linking

View File

@ -1,10 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __XDP__
#define __XDP__
#include "utils.h"
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
bool drv, bool offload);
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, __u32 ifindex,
bool generic, bool drv, bool offload);
void xdp_dump(FILE *fp, struct rtattr *tb, bool link, bool details);
#endif /* __XDP__ */

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
include ../config.mk
CFLAGS += -fPIC

155
lib/bpf.c
View File

@ -113,10 +113,10 @@ const char *bpf_prog_to_default_section(enum bpf_prog_type type)
#ifdef HAVE_ELF
static int bpf_obj_open(const char *path, enum bpf_prog_type type,
const char *sec, bool verbose);
const char *sec, __u32 ifindex, bool verbose);
#else
static int bpf_obj_open(const char *path, enum bpf_prog_type type,
const char *sec, bool verbose)
const char *sec, __u32 ifindex, bool verbose)
{
fprintf(stderr, "No ELF library support compiled in.\n");
errno = ENOSYS;
@ -805,16 +805,7 @@ static int bpf_obj_pinned(const char *pathname, enum bpf_prog_type type)
return prog_fd;
}
enum bpf_mode {
CBPF_BYTECODE,
CBPF_FILE,
EBPF_OBJECT,
EBPF_PINNED,
BPF_MODE_MAX,
};
static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
struct bpf_cfg_in *cfg, const bool *opt_tbl)
static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl)
{
const char *file, *section, *uds_name;
bool verbose = false;
@ -827,20 +818,20 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
if (opt_tbl[CBPF_BYTECODE] &&
(matches(*argv, "bytecode") == 0 ||
strcmp(*argv, "bc") == 0)) {
*mode = CBPF_BYTECODE;
cfg->mode = CBPF_BYTECODE;
} else if (opt_tbl[CBPF_FILE] &&
(matches(*argv, "bytecode-file") == 0 ||
strcmp(*argv, "bcf") == 0)) {
*mode = CBPF_FILE;
cfg->mode = CBPF_FILE;
} else if (opt_tbl[EBPF_OBJECT] &&
(matches(*argv, "object-file") == 0 ||
strcmp(*argv, "obj") == 0)) {
*mode = EBPF_OBJECT;
cfg->mode = EBPF_OBJECT;
} else if (opt_tbl[EBPF_PINNED] &&
(matches(*argv, "object-pinned") == 0 ||
matches(*argv, "pinned") == 0 ||
matches(*argv, "fd") == 0)) {
*mode = EBPF_PINNED;
cfg->mode = EBPF_PINNED;
} else {
fprintf(stderr, "What mode is \"%s\"?\n", *argv);
return -1;
@ -848,11 +839,11 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
NEXT_ARG();
file = section = uds_name = NULL;
if (*mode == EBPF_OBJECT || *mode == EBPF_PINNED) {
if (cfg->mode == EBPF_OBJECT || cfg->mode == EBPF_PINNED) {
file = *argv;
NEXT_ARG_FWD();
if (*type == BPF_PROG_TYPE_UNSPEC) {
if (cfg->type == BPF_PROG_TYPE_UNSPEC) {
if (argc > 0 && matches(*argv, "type") == 0) {
NEXT_ARG();
for (i = 0; i < ARRAY_SIZE(__bpf_prog_meta);
@ -861,30 +852,30 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
continue;
if (!matches(*argv,
__bpf_prog_meta[i].type)) {
*type = i;
cfg->type = i;
break;
}
}
if (*type == BPF_PROG_TYPE_UNSPEC) {
if (cfg->type == BPF_PROG_TYPE_UNSPEC) {
fprintf(stderr, "What type is \"%s\"?\n",
*argv);
return -1;
}
NEXT_ARG_FWD();
} else {
*type = BPF_PROG_TYPE_SCHED_CLS;
cfg->type = BPF_PROG_TYPE_SCHED_CLS;
}
}
section = bpf_prog_to_default_section(*type);
section = bpf_prog_to_default_section(cfg->type);
if (argc > 0 && matches(*argv, "section") == 0) {
NEXT_ARG();
section = *argv;
NEXT_ARG_FWD();
}
if (__bpf_prog_meta[*type].may_uds_export) {
if (__bpf_prog_meta[cfg->type].may_uds_export) {
uds_name = getenv(BPF_ENV_UDS);
if (argc > 0 && !uds_name &&
matches(*argv, "export") == 0) {
@ -902,53 +893,63 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
PREV_ARG();
}
if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE)
ret = bpf_ops_parse(argc, argv, cfg->ops, *mode == CBPF_FILE);
else if (*mode == EBPF_OBJECT)
ret = bpf_obj_open(file, *type, section, verbose);
else if (*mode == EBPF_PINNED)
ret = bpf_obj_pinned(file, *type);
else
if (cfg->mode == CBPF_BYTECODE || cfg->mode == CBPF_FILE) {
ret = bpf_ops_parse(argc, argv, cfg->opcodes,
cfg->mode == CBPF_FILE);
cfg->n_opcodes = ret;
} else if (cfg->mode == EBPF_OBJECT) {
ret = 0; /* program will be loaded by load stage */
} else if (cfg->mode == EBPF_PINNED) {
ret = bpf_obj_pinned(file, cfg->type);
cfg->prog_fd = ret;
} else {
return -1;
}
cfg->object = file;
cfg->section = section;
cfg->uds = uds_name;
cfg->argc = argc;
cfg->argv = argv;
cfg->verbose = verbose;
return ret;
}
static int bpf_parse_opt_tbl(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
const struct bpf_cfg_ops *ops, void *nl,
const bool *opt_tbl)
static int bpf_do_load(struct bpf_cfg_in *cfg)
{
if (cfg->mode == EBPF_OBJECT) {
cfg->prog_fd = bpf_obj_open(cfg->object, cfg->type,
cfg->section, cfg->ifindex,
cfg->verbose);
return cfg->prog_fd;
}
return 0;
}
int bpf_load_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops,
void *nl)
{
struct sock_filter opcodes[BPF_MAXINSNS];
char annotation[256];
enum bpf_mode mode;
int ret;
cfg->ops = opcodes;
ret = bpf_parse(&type, &mode, cfg, opt_tbl);
cfg->ops = NULL;
ret = bpf_do_load(cfg);
if (ret < 0)
return ret;
if (mode == CBPF_BYTECODE || mode == CBPF_FILE)
ops->cbpf_cb(nl, opcodes, ret);
if (mode == EBPF_OBJECT || mode == EBPF_PINNED) {
if (cfg->mode == CBPF_BYTECODE || cfg->mode == CBPF_FILE)
ops->cbpf_cb(nl, cfg->opcodes, cfg->n_opcodes);
if (cfg->mode == EBPF_OBJECT || cfg->mode == EBPF_PINNED) {
snprintf(annotation, sizeof(annotation), "%s:[%s]",
basename(cfg->object), mode == EBPF_PINNED ?
basename(cfg->object), cfg->mode == EBPF_PINNED ?
"*fsobj" : cfg->section);
ops->ebpf_cb(nl, ret, annotation);
ops->ebpf_cb(nl, cfg->prog_fd, annotation);
}
return 0;
}
int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
const struct bpf_cfg_ops *ops, void *nl)
int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops)
{
bool opt_tbl[BPF_MODE_MAX] = {};
@ -962,12 +963,23 @@ int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
opt_tbl[EBPF_PINNED] = true;
}
return bpf_parse_opt_tbl(type, cfg, ops, nl, opt_tbl);
return bpf_do_parse(cfg, opt_tbl);
}
int bpf_parse_and_load_common(struct bpf_cfg_in *cfg,
const struct bpf_cfg_ops *ops, void *nl)
{
int ret;
ret = bpf_parse_common(cfg, ops);
if (ret < 0)
return ret;
return bpf_load_common(cfg, ops, nl);
}
int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
{
enum bpf_prog_type type = BPF_PROG_TYPE_UNSPEC;
const bool opt_tbl[BPF_MODE_MAX] = {
[EBPF_OBJECT] = true,
[EBPF_PINNED] = true,
@ -978,17 +990,24 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
.size_value = sizeof(int),
};
struct bpf_cfg_in cfg = {
.type = BPF_PROG_TYPE_UNSPEC,
.argc = argc,
.argv = argv,
};
struct bpf_map_ext ext = {};
int ret, prog_fd, map_fd;
enum bpf_mode mode;
uint32_t map_key;
prog_fd = bpf_parse(&type, &mode, &cfg, opt_tbl);
if (prog_fd < 0)
return prog_fd;
ret = bpf_do_parse(&cfg, opt_tbl);
if (ret < 0)
return ret;
ret = bpf_do_load(&cfg);
if (ret < 0)
return ret;
prog_fd = cfg.prog_fd;
if (key) {
map_key = *key;
} else {
@ -1000,7 +1019,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
}
}
map_fd = bpf_obj_get(map_path, type);
map_fd = bpf_obj_get(map_path, cfg.type);
if (map_fd < 0) {
fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n",
map_path, strerror(errno));
@ -1010,7 +1029,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
ret = bpf_map_selfcheck_pinned(map_fd, &test, &ext,
offsetof(struct bpf_elf_map, max_elem),
type);
cfg.type);
if (ret < 0) {
fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path);
goto out_map;
@ -1047,9 +1066,10 @@ int bpf_prog_detach_fd(int target_fd, enum bpf_attach_type type)
return bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
}
int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
size_t size_insns, const char *license, char *log,
size_t size_log)
static int bpf_prog_load_dev(enum bpf_prog_type type,
const struct bpf_insn *insns, size_t size_insns,
const char *license, __u32 ifindex,
char *log, size_t size_log)
{
union bpf_attr attr = {};
@ -1057,6 +1077,7 @@ int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
attr.insns = bpf_ptr_to_u64(insns);
attr.insn_cnt = size_insns / sizeof(struct bpf_insn);
attr.license = bpf_ptr_to_u64(license);
attr.prog_ifindex = ifindex;
if (size_log > 0) {
attr.log_buf = bpf_ptr_to_u64(log);
@ -1067,6 +1088,14 @@ int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
return bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
}
int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
size_t size_insns, const char *license, char *log,
size_t size_log)
{
return bpf_prog_load_dev(type, insns, size_insns, license, 0,
log, size_log);
}
#ifdef HAVE_ELF
struct bpf_elf_prog {
enum bpf_prog_type type;
@ -1102,6 +1131,7 @@ struct bpf_elf_ctx {
int sec_maps;
char license[ELF_MAX_LICENSE_LEN];
enum bpf_prog_type type;
__u32 ifindex;
bool verbose;
struct bpf_elf_st stat;
struct bpf_hash_entry *ht[256];
@ -1474,8 +1504,9 @@ static int bpf_prog_attach(const char *section,
int tries = 0, fd;
retry:
errno = 0;
fd = bpf_prog_load(prog->type, prog->insns, prog->size,
prog->license, ctx->log, ctx->log_size);
fd = bpf_prog_load_dev(prog->type, prog->insns, prog->size,
prog->license, ctx->ifindex,
ctx->log, ctx->log_size);
if (fd < 0 || ctx->verbose) {
/* The verifier log is pretty chatty, sometimes so chatty
* on larger programs, that we could fail to dump everything
@ -2403,7 +2434,8 @@ static void bpf_get_cfg(struct bpf_elf_ctx *ctx)
}
static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
enum bpf_prog_type type, bool verbose)
enum bpf_prog_type type, __u32 ifindex,
bool verbose)
{
int ret = -EINVAL;
@ -2415,6 +2447,7 @@ static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
bpf_get_cfg(ctx);
ctx->verbose = verbose;
ctx->type = type;
ctx->ifindex = ifindex;
ctx->obj_fd = open(pathname, O_RDONLY);
if (ctx->obj_fd < 0)
@ -2506,12 +2539,12 @@ static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure)
static struct bpf_elf_ctx __ctx;
static int bpf_obj_open(const char *pathname, enum bpf_prog_type type,
const char *section, bool verbose)
const char *section, __u32 ifindex, bool verbose)
{
struct bpf_elf_ctx *ctx = &__ctx;
int fd = 0, ret;
ret = bpf_elf_ctx_init(ctx, pathname, type, verbose);
ret = bpf_elf_ctx_init(ctx, pathname, type, ifindex, verbose);
if (ret < 0) {
fprintf(stderr, "Cannot initialize ELF context!\n");
return ret;

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <errno.h>
#include <string.h>
#include <sys/types.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <errno.h>
#include <string.h>
#include <sys/types.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <sys/wait.h>
#include <stdio.h>
#include <errno.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <errno.h>
#include <string.h>
#include <sys/types.h>

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* libgenl.c GENL library
*/

View File

@ -1,3 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <errno.h>
#include <string.h>
#include <sys/types.h>

View File

@ -1,3 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <errno.h>
#include <string.h>
#include <sys/types.h>

View File

@ -38,6 +38,74 @@
int resolve_hosts;
int timestamp_short;
int read_prop(const char *dev, char *prop, long *value)
{
char fname[128], buf[80], *endp, *nl;
FILE *fp;
long result;
int ret;
ret = snprintf(fname, sizeof(fname), "/sys/class/net/%s/%s",
dev, prop);
if (ret <= 0 || ret >= sizeof(fname)) {
fprintf(stderr, "could not build pathname for property\n");
return -1;
}
fp = fopen(fname, "r");
if (fp == NULL) {
fprintf(stderr, "fopen %s: %s\n", fname, strerror(errno));
return -1;
}
if (!fgets(buf, sizeof(buf), fp)) {
fprintf(stderr, "property \"%s\" in file %s is currently unknown\n", prop, fname);
fclose(fp);
goto out;
}
nl = strchr(buf, '\n');
if (nl)
*nl = '\0';
fclose(fp);
result = strtol(buf, &endp, 0);
if (*endp || buf == endp) {
fprintf(stderr, "value \"%s\" in file %s is not a number\n",
buf, fname);
goto out;
}
if ((result == LONG_MAX || result == LONG_MIN) && errno == ERANGE) {
fprintf(stderr, "strtol %s: %s", fname, strerror(errno));
goto out;
}
*value = result;
return 0;
out:
fprintf(stderr, "Failed to parse %s\n", fname);
return -1;
}
/* Parse a percent e.g: '30%'
* return: 0 = ok, -1 = error, 1 = out of range
*/
int parse_percent(double *val, const char *str)
{
char *p;
*val = strtod(str, &p) / 100.;
if (*val == HUGE_VALF || *val == HUGE_VALL)
return 1;
if (*val == 0.0 || (*p && strcmp(p, "%")))
return -1;
return 0;
}
int get_hex(char c)
{
if (c >= 'A' && c <= 'F')

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
INSTALL=install
INSTALLDIR=install -m 0755 -d
INSTALLMAN=install -m 0644

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
MAN3PAGES = $(wildcard *.3)
all:

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
MAN7PAGES = $(wildcard *.7)
all:

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
TARGETS = ip-address.8 ip-link.8 ip-route.8
MAN8PAGES = $(TARGETS) $(filter-out $(TARGETS),$(wildcard *.8))

View File

@ -74,7 +74,8 @@ tc \- show / manipulate traffic control settings
\fB\-r\fR[\fIaw\fR] |
\fB\-p\fR[\fIretty\fR] |
\fB\-i\fR[\fIec\fR] |
\fB\-g\fR[\fIraph\fR] }
\fB\-g\fR[\fIraph\fR] |
\fB\-j\fR[\fIjson\fR] }
.SH DESCRIPTION
.B Tc
@ -443,7 +444,10 @@ see the man pages for individual qdiscs.
RATES
Bandwidths or rates.
These parameters accept a floating point number, possibly followed by
a unit (both SI and IEC units supported).
either a unit (both SI and IEC units supported), or a float followed by a '%'
character to specify the rate as a percentage of the device's speed
(e.g. 5%, 99.5%). Warning: specifying the rate as a percentage means a fraction
of the current speed; if the speed changes, the value will not be recalculated.
.RS
.TP
bit or a bare number
@ -658,6 +662,10 @@ option was specified. Classes can be filtered only by
.BR "dev"
option.
.TP
.BR "\-j", " \-json"
Display results in JSON format.
.TP
.BR "\-nm" , " \-name"
resolve class name from

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
SSOBJ=ss.o ssfilter.o
LNSTATOBJ=lnstat.o lnstat_util.o

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LNSTAT_H
#define _LNSTAT_H

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#define SSF_DCOND 0
#define SSF_SCOND 1
#define SSF_OR 2

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
include ../config.mk
DISTGEN = maketable normal pareto paretonormal

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
include ../config.mk
ifeq ($(HAVE_MNL),y)

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
TCOBJ= tc.o tc_qdisc.o tc_class.o tc_filter.o tc_util.o tc_monitor.o \
tc_exec.o m_police.o m_estimator.o m_action.o m_ematch.o \
emp_ematch.yacc.o emp_ematch.lex.o

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
%{
#include "emp_ematch.yacc.h"
#include "m_ematch.h"

View File

@ -82,6 +82,7 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle,
unsigned int bpf_flags = 0;
struct bpf_cfg_in cfg = {};
bool seen_run = false;
bool skip_sw = false;
struct rtattr *tail;
int ret = 0;
@ -101,13 +102,20 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle,
while (argc > 0) {
if (matches(*argv, "run") == 0) {
NEXT_ARG();
if (seen_run)
duparg("run", *argv);
opt_bpf:
seen_run = true;
cfg.type = bpf_type;
cfg.argc = argc;
cfg.argv = argv;
if (bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, n))
if (bpf_parse_common(&cfg, &bpf_cb_ops) < 0) {
fprintf(stderr,
"Unable to parse bpf command line\n");
return -1;
}
argc = cfg.argc;
argv = cfg.argv;
@ -131,6 +139,7 @@ opt_bpf:
bpf_gen_flags |= TCA_CLS_FLAGS_SKIP_HW;
} else if (matches(*argv, "skip_sw") == 0) {
bpf_gen_flags |= TCA_CLS_FLAGS_SKIP_SW;
skip_sw = true;
} else if (matches(*argv, "action") == 0) {
NEXT_ARG();
if (parse_action(&argc, &argv, TCA_BPF_ACT, n)) {
@ -160,6 +169,13 @@ opt_bpf:
NEXT_ARG_FWD();
}
if (skip_sw)
cfg.ifindex = t->tcm_ifindex;
if (bpf_load_common(&cfg, &bpf_cb_ops, n) < 0) {
fprintf(stderr, "Unable to load program\n");
return -1;
}
if (bpf_gen_flags)
addattr32(n, MAX_MSG, TCA_BPF_FLAGS_GEN, bpf_gen_flags);
if (bpf_flags)

View File

@ -1037,89 +1037,105 @@ static int __mask_bits(char *addr, size_t len)
return bits;
}
static void flower_print_eth_addr(FILE *f, char *name,
struct rtattr *addr_attr,
static void flower_print_eth_addr(char *name, struct rtattr *addr_attr,
struct rtattr *mask_attr)
{
SPRINT_BUF(namefrm);
SPRINT_BUF(out);
SPRINT_BUF(b1);
size_t done;
int bits;
if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN)
return;
fprintf(f, "\n %s %s", name, ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN,
0, b1, sizeof(b1)));
if (!mask_attr || RTA_PAYLOAD(mask_attr) != ETH_ALEN)
return;
bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN);
if (bits < 0)
fprintf(f, "/%s", ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN,
0, b1, sizeof(b1)));
else if (bits < ETH_ALEN * 8)
fprintf(f, "/%d", bits);
done = sprintf(out, "%s",
ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN,
0, b1, sizeof(b1)));
if (mask_attr && RTA_PAYLOAD(mask_attr) == ETH_ALEN) {
bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN);
if (bits < 0)
sprintf(out + done, "/%s",
ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN,
0, b1, sizeof(b1)));
else if (bits < ETH_ALEN * 8)
sprintf(out + done, "/%d", bits);
}
sprintf(namefrm, "\n %s %%s", name);
print_string(PRINT_ANY, name, namefrm, out);
}
static void flower_print_eth_type(FILE *f, __be16 *p_eth_type,
static void flower_print_eth_type(__be16 *p_eth_type,
struct rtattr *eth_type_attr)
{
SPRINT_BUF(out);
__be16 eth_type;
if (!eth_type_attr)
return;
eth_type = rta_getattr_u16(eth_type_attr);
fprintf(f, "\n eth_type ");
if (eth_type == htons(ETH_P_IP))
fprintf(f, "ipv4");
sprintf(out, "ipv4");
else if (eth_type == htons(ETH_P_IPV6))
fprintf(f, "ipv6");
sprintf(out, "ipv6");
else if (eth_type == htons(ETH_P_ARP))
fprintf(f, "arp");
sprintf(out, "arp");
else if (eth_type == htons(ETH_P_RARP))
fprintf(f, "rarp");
sprintf(out, "rarp");
else
fprintf(f, "%04x", ntohs(eth_type));
sprintf(out, "%04x", ntohs(eth_type));
print_string(PRINT_ANY, "eth_type", "\n eth_type %s", out);
*p_eth_type = eth_type;
}
static void flower_print_ip_proto(FILE *f, __u8 *p_ip_proto,
static void flower_print_ip_proto(__u8 *p_ip_proto,
struct rtattr *ip_proto_attr)
{
SPRINT_BUF(out);
__u8 ip_proto;
if (!ip_proto_attr)
return;
ip_proto = rta_getattr_u8(ip_proto_attr);
fprintf(f, "\n ip_proto ");
if (ip_proto == IPPROTO_TCP)
fprintf(f, "tcp");
sprintf(out, "tcp");
else if (ip_proto == IPPROTO_UDP)
fprintf(f, "udp");
sprintf(out, "udp");
else if (ip_proto == IPPROTO_SCTP)
fprintf(f, "sctp");
sprintf(out, "sctp");
else if (ip_proto == IPPROTO_ICMP)
fprintf(f, "icmp");
sprintf(out, "icmp");
else if (ip_proto == IPPROTO_ICMPV6)
fprintf(f, "icmpv6");
sprintf(out, "icmpv6");
else
fprintf(f, "%02x", ip_proto);
sprintf(out, "%02x", ip_proto);
print_string(PRINT_ANY, "ip_proto", "\n ip_proto %s", out);
*p_ip_proto = ip_proto;
}
static void flower_print_ip_attr(FILE *f, char *name,
struct rtattr *key_attr,
static void flower_print_ip_attr(char *name, struct rtattr *key_attr,
struct rtattr *mask_attr)
{
SPRINT_BUF(namefrm);
SPRINT_BUF(out);
size_t done;
if (!key_attr)
return;
fprintf(f, "\n %s %x", name, rta_getattr_u8(key_attr));
if (!mask_attr)
return;
fprintf(f, "/%x", rta_getattr_u8(mask_attr));
done = sprintf(out, "%x", rta_getattr_u8(key_attr));
if (mask_attr)
sprintf(out + done, "/%x", rta_getattr_u8(mask_attr));
sprintf(namefrm, "\n %s %%x", name);
print_string(PRINT_ANY, name, namefrm, out);
}
static void flower_print_matching_flags(FILE *f, char *name,
static void flower_print_matching_flags(char *name,
enum flower_matching_flags type,
struct rtattr *attr,
struct rtattr *mask_attr)
@ -1139,20 +1155,28 @@ static void flower_print_matching_flags(FILE *f, char *name,
if (type != flags_str[i].type)
continue;
if (mtf_mask & flags_str[i].flag) {
if (++count == 1)
fprintf(f, "\n %s ", name);
else
fprintf(f, "/");
if (++count == 1) {
print_string(PRINT_FP, NULL, "\n %s ", name);
open_json_object(name);
} else {
print_string(PRINT_FP, NULL, "/", NULL);
}
print_bool(PRINT_JSON, flags_str[i].string, NULL,
mtf & flags_str[i].flag);
if (mtf & flags_str[i].flag)
fprintf(f, "%s", flags_str[i].string);
print_string(PRINT_FP, NULL, "%s",
flags_str[i].string);
else
fprintf(f, "no%s", flags_str[i].string);
print_string(PRINT_FP, NULL, "no%s",
flags_str[i].string);
}
}
if (count)
close_json_object();
}
static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type,
static void flower_print_ip_addr(char *name, __be16 eth_type,
struct rtattr *addr4_attr,
struct rtattr *mask4_attr,
struct rtattr *addr6_attr,
@ -1160,6 +1184,9 @@ static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type,
{
struct rtattr *addr_attr;
struct rtattr *mask_attr;
SPRINT_BUF(namefrm);
SPRINT_BUF(out);
size_t done;
int family;
size_t len;
int bits;
@ -1179,56 +1206,75 @@ static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type,
}
if (!addr_attr || RTA_PAYLOAD(addr_attr) != len)
return;
fprintf(f, "\n %s %s", name, rt_addr_n2a_rta(family, addr_attr));
if (!mask_attr || RTA_PAYLOAD(mask_attr) != len)
return;
done = sprintf(out, "%s", rt_addr_n2a_rta(family, addr_attr));
bits = __mask_bits(RTA_DATA(mask_attr), len);
if (bits < 0)
fprintf(f, "/%s", rt_addr_n2a_rta(family, mask_attr));
sprintf(out + done, "/%s", rt_addr_n2a_rta(family, mask_attr));
else if (bits < len * 8)
fprintf(f, "/%d", bits);
sprintf(out + done, "/%d", bits);
sprintf(namefrm, "\n %s %%s", name);
print_string(PRINT_ANY, name, namefrm, out);
}
static void flower_print_ip4_addr(FILE *f, char *name,
struct rtattr *addr_attr,
static void flower_print_ip4_addr(char *name, struct rtattr *addr_attr,
struct rtattr *mask_attr)
{
return flower_print_ip_addr(f, name, htons(ETH_P_IP),
return flower_print_ip_addr(name, htons(ETH_P_IP),
addr_attr, mask_attr, 0, 0);
}
static void flower_print_port(FILE *f, char *name, struct rtattr *attr)
static void flower_print_port(char *name, struct rtattr *attr)
{
if (attr)
fprintf(f, "\n %s %d", name, rta_getattr_be16(attr));
SPRINT_BUF(namefrm);
if (!attr)
return;
sprintf(namefrm,"\n %s %%u", name);
print_uint(PRINT_ANY, name, namefrm, rta_getattr_be16(attr));
}
static void flower_print_tcp_flags(FILE *f, char *name,
struct rtattr *flags_attr,
struct rtattr *mask_attr)
static void flower_print_tcp_flags(char *name, struct rtattr *flags_attr,
struct rtattr *mask_attr)
{
SPRINT_BUF(namefrm);
SPRINT_BUF(out);
size_t done;
if (!flags_attr)
return;
fprintf(f, "\n %s %x", name, rta_getattr_be16(flags_attr));
if (!mask_attr)
return;
fprintf(f, "/%x", rta_getattr_be16(mask_attr));
done = sprintf(out, "%x", rta_getattr_be16(flags_attr));
if (mask_attr)
sprintf(out + done, "%x", rta_getattr_be16(flags_attr));
sprintf(namefrm, "\n %s %%s", name);
print_string(PRINT_ANY, name, namefrm, out);
}
static void flower_print_key_id(FILE *f, const char *name,
struct rtattr *attr)
static void flower_print_key_id(const char *name, struct rtattr *attr)
{
if (attr)
fprintf(f, "\n %s %d", name, rta_getattr_be32(attr));
SPRINT_BUF(namefrm);
if (!attr)
return;
sprintf(namefrm,"\n %s %%u", name);
print_uint(PRINT_ANY, name, namefrm, rta_getattr_be32(attr));
}
static void flower_print_masked_u8(FILE *f, const char *name,
struct rtattr *attr,
static void flower_print_masked_u8(const char *name, struct rtattr *attr,
struct rtattr *mask_attr,
const char *(*value_to_str)(__u8 value))
{
const char *value_str = NULL;
__u8 value, mask;
SPRINT_BUF(namefrm);
SPRINT_BUF(out);
size_t done;
if (!attr)
return;
@ -1238,39 +1284,39 @@ static void flower_print_masked_u8(FILE *f, const char *name,
if (mask == UINT8_MAX && value_to_str)
value_str = value_to_str(value);
fprintf(f, "\n %s ", name);
if (value_str)
fputs(value_str, f);
done = sprintf(out, "%s", value_str);
else
fprintf(f, "%d", value);
done = sprintf(out, "%d", value);
if (mask != UINT8_MAX)
fprintf(f, "/%d", mask);
sprintf(out + done, "/%d", mask);
sprintf(namefrm,"\n %s %%s", name);
print_string(PRINT_ANY, name, namefrm, out);
}
static void flower_print_u8(FILE *f, const char *name, struct rtattr *attr)
static void flower_print_u8(const char *name, struct rtattr *attr)
{
flower_print_masked_u8(f, name, attr, NULL, NULL);
flower_print_masked_u8(name, attr, NULL, NULL);
}
static void flower_print_u32(FILE *f, const char *name, struct rtattr *attr)
static void flower_print_u32(const char *name, struct rtattr *attr)
{
__u32 value;
SPRINT_BUF(namefrm);
if (!attr)
return;
value = rta_getattr_u32(attr);
fprintf(f, "\n %s %d", name, value);
sprintf(namefrm,"\n %s %%u", name);
print_uint(PRINT_ANY, name, namefrm, rta_getattr_u32(attr));
}
static void flower_print_arp_op(FILE *f, const char *name,
static void flower_print_arp_op(const char *name,
struct rtattr *op_attr,
struct rtattr *mask_attr)
{
flower_print_masked_u8(f, name, op_attr, mask_attr,
flower_print_masked_u8(name, op_attr, mask_attr,
flower_print_arp_op_to_name);
}
@ -1288,7 +1334,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt);
if (handle)
fprintf(f, "handle 0x%x ", handle);
print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle);
if (tb[TCA_FLOWER_CLASSID]) {
__u32 h = rta_getattr_u32(tb[TCA_FLOWER_CLASSID]);
@ -1296,56 +1342,62 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
if (TC_H_MIN(h) < TC_H_MIN_PRIORITY ||
TC_H_MIN(h) > (TC_H_MIN_PRIORITY + TC_QOPT_MAX_QUEUE - 1)) {
SPRINT_BUF(b1);
fprintf(f, "classid %s ", sprint_tc_classid(h, b1));
print_string(PRINT_ANY, "classid", "classid %s ",
sprint_tc_classid(h, b1));
} else {
fprintf(f, "hw_tc %u ",
TC_H_MIN(h) - TC_H_MIN_PRIORITY);
print_uint(PRINT_ANY, "hw_tc", "hw_tc %u ",
TC_H_MIN(h) - TC_H_MIN_PRIORITY);
}
}
if (tb[TCA_FLOWER_INDEV]) {
struct rtattr *attr = tb[TCA_FLOWER_INDEV];
fprintf(f, "\n indev %s", rta_getattr_str(attr));
print_string(PRINT_ANY, "indev", "\n indev %s",
rta_getattr_str(attr));
}
open_json_object("keys");
if (tb[TCA_FLOWER_KEY_VLAN_ID]) {
struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ID];
fprintf(f, "\n vlan_id %d", rta_getattr_u16(attr));
print_uint(PRINT_ANY, "vlan_id", "\n vlan_id %u",
rta_getattr_u16(attr));
}
if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) {
struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_PRIO];
fprintf(f, "\n vlan_prio %d", rta_getattr_u8(attr));
print_uint(PRINT_ANY, "vlan_prio", "\n vlan_prio %d",
rta_getattr_u8(attr));
}
flower_print_eth_addr(f, "dst_mac", tb[TCA_FLOWER_KEY_ETH_DST],
flower_print_eth_addr("dst_mac", tb[TCA_FLOWER_KEY_ETH_DST],
tb[TCA_FLOWER_KEY_ETH_DST_MASK]);
flower_print_eth_addr(f, "src_mac", tb[TCA_FLOWER_KEY_ETH_SRC],
flower_print_eth_addr("src_mac", tb[TCA_FLOWER_KEY_ETH_SRC],
tb[TCA_FLOWER_KEY_ETH_SRC_MASK]);
flower_print_eth_type(f, &eth_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
flower_print_ip_proto(f, &ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
flower_print_eth_type(&eth_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
flower_print_ip_proto(&ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
flower_print_ip_attr(f, "ip_tos", tb[TCA_FLOWER_KEY_IP_TOS],
flower_print_ip_attr("ip_tos", tb[TCA_FLOWER_KEY_IP_TOS],
tb[TCA_FLOWER_KEY_IP_TOS_MASK]);
flower_print_ip_attr(f, "ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL],
flower_print_ip_attr("ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL],
tb[TCA_FLOWER_KEY_IP_TTL_MASK]);
flower_print_u32(f, "mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]);
flower_print_u8(f, "mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
flower_print_u8(f, "mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);
flower_print_u8(f, "mpls_ttl", tb[TCA_FLOWER_KEY_MPLS_TTL]);
flower_print_u32("mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]);
flower_print_u8("mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
flower_print_u8("mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);
flower_print_u8("mpls_ttl", tb[TCA_FLOWER_KEY_MPLS_TTL]);
flower_print_ip_addr(f, "dst_ip", eth_type,
flower_print_ip_addr("dst_ip", eth_type,
tb[TCA_FLOWER_KEY_IPV4_DST],
tb[TCA_FLOWER_KEY_IPV4_DST_MASK],
tb[TCA_FLOWER_KEY_IPV6_DST],
tb[TCA_FLOWER_KEY_IPV6_DST_MASK]);
flower_print_ip_addr(f, "src_ip", eth_type,
flower_print_ip_addr("src_ip", eth_type,
tb[TCA_FLOWER_KEY_IPV4_SRC],
tb[TCA_FLOWER_KEY_IPV4_SRC_MASK],
tb[TCA_FLOWER_KEY_IPV6_SRC],
@ -1353,12 +1405,12 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_DST);
if (nl_type >= 0)
flower_print_port(f, "dst_port", tb[nl_type]);
flower_print_port("dst_port", tb[nl_type]);
nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_SRC);
if (nl_type >= 0)
flower_print_port(f, "src_port", tb[nl_type]);
flower_print_port("src_port", tb[nl_type]);
flower_print_tcp_flags(f, "tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS],
flower_print_tcp_flags("tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS],
tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
nl_type = flower_icmp_attr_type(eth_type, ip_proto,
@ -1366,7 +1418,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
FLOWER_ICMP_FIELD_TYPE);
if (nl_type >= 0 && nl_mask_type >= 0)
flower_print_masked_u8(f, "icmp_type", tb[nl_type],
flower_print_masked_u8("icmp_type", tb[nl_type],
tb[nl_mask_type], NULL);
nl_type = flower_icmp_attr_type(eth_type, ip_proto,
@ -1374,21 +1426,21 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
FLOWER_ICMP_FIELD_CODE);
if (nl_type >= 0 && nl_mask_type >= 0)
flower_print_masked_u8(f, "icmp_code", tb[nl_type],
flower_print_masked_u8("icmp_code", tb[nl_type],
tb[nl_mask_type], NULL);
flower_print_ip4_addr(f, "arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP],
flower_print_ip4_addr("arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP],
tb[TCA_FLOWER_KEY_ARP_SIP_MASK]);
flower_print_ip4_addr(f, "arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP],
flower_print_ip4_addr("arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP],
tb[TCA_FLOWER_KEY_ARP_TIP_MASK]);
flower_print_arp_op(f, "arp_op", tb[TCA_FLOWER_KEY_ARP_OP],
flower_print_arp_op("arp_op", tb[TCA_FLOWER_KEY_ARP_OP],
tb[TCA_FLOWER_KEY_ARP_OP_MASK]);
flower_print_eth_addr(f, "arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA],
flower_print_eth_addr("arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA],
tb[TCA_FLOWER_KEY_ARP_SHA_MASK]);
flower_print_eth_addr(f, "arp_tha", tb[TCA_FLOWER_KEY_ARP_THA],
flower_print_eth_addr("arp_tha", tb[TCA_FLOWER_KEY_ARP_THA],
tb[TCA_FLOWER_KEY_ARP_THA_MASK]);
flower_print_ip_addr(f, "enc_dst_ip",
flower_print_ip_addr("enc_dst_ip",
tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ?
htons(ETH_P_IP) : htons(ETH_P_IPV6),
tb[TCA_FLOWER_KEY_ENC_IPV4_DST],
@ -1396,7 +1448,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
tb[TCA_FLOWER_KEY_ENC_IPV6_DST],
tb[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]);
flower_print_ip_addr(f, "enc_src_ip",
flower_print_ip_addr("enc_src_ip",
tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] ?
htons(ETH_P_IP) : htons(ETH_P_IPV6),
tb[TCA_FLOWER_KEY_ENC_IPV4_SRC],
@ -1404,29 +1456,28 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
tb[TCA_FLOWER_KEY_ENC_IPV6_SRC],
tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]);
flower_print_key_id(f, "enc_key_id",
tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
flower_print_key_id("enc_key_id", tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
flower_print_port(f, "enc_dst_port",
tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
flower_print_port("enc_dst_port", tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
flower_print_matching_flags(f, "ip_flags",
FLOWER_IP_FLAGS,
flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS,
tb[TCA_FLOWER_KEY_FLAGS],
tb[TCA_FLOWER_KEY_FLAGS_MASK]);
close_json_object();
if (tb[TCA_FLOWER_FLAGS]) {
__u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
if (flags & TCA_CLS_FLAGS_SKIP_HW)
fprintf(f, "\n skip_hw");
print_bool(PRINT_ANY, "skip_hw", "\n skip_hw", true);
if (flags & TCA_CLS_FLAGS_SKIP_SW)
fprintf(f, "\n skip_sw");
print_bool(PRINT_ANY, "skip_sw", "\n skip_sw", true);
if (flags & TCA_CLS_FLAGS_IN_HW)
fprintf(f, "\n in_hw");
print_bool(PRINT_ANY, "in_hw", "\n in_hw", true);
else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
fprintf(f, "\n not_in_hw");
print_bool(PRINT_ANY, "not_in_hw", "\n not_in_hw", true);
}
if (tb[TCA_FLOWER_ACT])

View File

@ -121,11 +121,11 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f,
parse_rtattr_nested(tb, TCA_MATCHALL_MAX, opt);
if (handle)
fprintf(f, "handle 0x%x ", handle);
print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle);
if (tb[TCA_MATCHALL_CLASSID]) {
SPRINT_BUF(b1);
fprintf(f, "flowid %s ",
print_string(PRINT_ANY, "flowid", "flowid %s ",
sprint_tc_classid(rta_getattr_u32(tb[TCA_MATCHALL_CLASSID]), b1));
}
@ -133,14 +133,14 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f,
__u32 flags = rta_getattr_u32(tb[TCA_MATCHALL_FLAGS]);
if (flags & TCA_CLS_FLAGS_SKIP_HW)
fprintf(f, "\n skip_hw");
print_bool(PRINT_ANY, "skip_hw", "\n skip_hw", true);
if (flags & TCA_CLS_FLAGS_SKIP_SW)
fprintf(f, "\n skip_sw");
print_bool(PRINT_ANY, "skip_sw", "\n skip_sw", true);
if (flags & TCA_CLS_FLAGS_IN_HW)
fprintf(f, "\n in_hw");
print_bool(PRINT_ANY, "in_hw", "\n in_hw", true);
else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
fprintf(f, "\n not_in_hw");
print_bool(PRINT_ANY, "not_in_hw", "\n not_in_hw", true);
}
if (tb[TCA_MATCHALL_ACT])

View File

@ -169,7 +169,8 @@ done:
}
static int rsvp_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
static int rsvp_parse_opt(struct filter_util *qu, char *handle, int argc,
char **argv, struct nlmsghdr *n)
{
int family = strcmp(qu->id, "rsvp") == 0 ? AF_INET : AF_INET6;
struct tc_rsvp_pinfo pinfo = {};

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* f_tcindex.c Traffic control index filter
*

View File

@ -11,10 +11,11 @@
* TODO:
* - parse to be passed a filedescriptor for logging purposes
*
*/
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
@ -41,7 +42,7 @@ static void act_usage(void)
* with any action .so from the old days. But if someone really
* does that, they would know how to fix this ..
*
*/
*/
fprintf(stderr, "usage: tc actions <ACTSPECOP>*\n");
fprintf(stderr,
"Where: \tACTSPECOP := ACR | GD | FL\n"
@ -68,16 +69,19 @@ static int print_noaopt(struct action_util *au, FILE *f, struct rtattr *opt)
return 0;
}
static int parse_noaopt(struct action_util *au, int *argc_p, char ***argv_p, int code, struct nlmsghdr *n)
static int parse_noaopt(struct action_util *au, int *argc_p,
char ***argv_p, int code, struct nlmsghdr *n)
{
int argc = *argc_p;
char **argv = *argv_p;
if (argc) {
fprintf(stderr, "Unknown action \"%s\", hence option \"%s\" is unparsable\n", au->id, *argv);
} else {
if (argc)
fprintf(stderr,
"Unknown action \"%s\", hence option \"%s\" is unparsable\n",
au->id, *argv);
else
fprintf(stderr, "Unknown action \"%s\"\n", au->id);
}
return -1;
}
@ -135,18 +139,14 @@ noexist:
return a;
}
static int
static bool
new_cmd(char **argv)
{
if ((matches(*argv, "change") == 0) ||
return (matches(*argv, "change") == 0) ||
(matches(*argv, "replace") == 0) ||
(matches(*argv, "delete") == 0) ||
(matches(*argv, "get") == 0) ||
(matches(*argv, "add") == 0))
return 1;
return 0;
(matches(*argv, "add") == 0);
}
int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
@ -154,7 +154,7 @@ int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
int argc = *argc_p;
char **argv = *argv_p;
struct rtattr *tail, *tail2;
char k[16];
char k[FILTER_NAMESZ];
int act_ck_len = 0;
int ok = 0;
int eap = 0; /* expect action parameters */
@ -179,9 +179,8 @@ int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
argv++;
eap = 1;
#ifdef CONFIG_GACT
if (!gact_ld) {
if (!gact_ld)
get_action_kind("gact");
}
#endif
continue;
} else if (strcmp(*argv, "flowid") == 0) {
@ -207,9 +206,9 @@ done0:
goto done;
}
if (a == NULL) {
if (a == NULL)
goto bad_val;
}
tail = NLMSG_TAIL(n);
addattr_l(n, MAX_MSG, ++prio, NULL, 0);
@ -268,7 +267,8 @@ done:
return 0;
bad_val:
/* no need to undo things, returning from here should
* cause enough pain */
* cause enough pain
*/
fprintf(stderr, "parse_action: bad value (%d:%s)!\n", argc, *argv);
return -1;
}
@ -301,18 +301,19 @@ static int tc_print_one_action(FILE *f, struct rtattr *arg)
return err;
if (show_stats && tb[TCA_ACT_STATS]) {
fprintf(f, "\tAction statistics:\n");
print_string(PRINT_FP, NULL, "\tAction statistics:\n", NULL);
open_json_object("stats");
print_tcstats2_attr(f, tb[TCA_ACT_STATS], "\t", NULL);
if (tb[TCA_ACT_COOKIE]) {
int strsz = RTA_PAYLOAD(tb[TCA_ACT_COOKIE]);
char b1[strsz * 2 + 1];
close_json_object();
print_string(PRINT_FP, NULL, "\n", NULL);
}
if (tb[TCA_ACT_COOKIE]) {
int strsz = RTA_PAYLOAD(tb[TCA_ACT_COOKIE]);
char b1[strsz * 2 + 1];
fprintf(f, "\n\tcookie len %d %s ", strsz,
hexstring_n2a(RTA_DATA(tb[TCA_ACT_COOKIE]),
strsz, b1, sizeof(b1)));
}
fprintf(f, "\n");
print_string(PRINT_ANY, "cookie", "\tcookie %s\n",
hexstring_n2a(RTA_DATA(tb[TCA_ACT_COOKIE]),
strsz, b1, sizeof(b1)));
}
return 0;
@ -363,15 +364,21 @@ tc_print_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts)
if (tab_flush && NULL != tb[0] && NULL == tb[1])
return tc_print_action_flush(f, tb[0]);
open_json_array(PRINT_JSON, "actions");
for (i = 0; i < tot_acts; i++) {
if (tb[i]) {
fprintf(f, "\n\taction order %d: ", i);
open_json_object(NULL);
print_uint(PRINT_ANY, "order",
"\n\taction order %u: ", i);
if (tc_print_one_action(f, tb[i]) < 0) {
fprintf(f, "Error printing action\n");
print_string(PRINT_FP, NULL,
"Error printing action\n", NULL);
}
close_json_object();
}
}
close_json_object();
return 0;
}
@ -429,9 +436,10 @@ int print_action(const struct sockaddr_nl *who,
return 0;
}
static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p)
static int tc_action_gd(int cmd, unsigned int flags,
int *argc_p, char ***argv_p)
{
char k[16];
char k[FILTER_NAMESZ];
struct action_util *a = NULL;
int argc = *argc_p;
char **argv = *argv_p;
@ -485,7 +493,8 @@ static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p
argc -= 1;
argv += 1;
if (argc <= 0) {
fprintf(stderr, "Error: no index specified action: %s\n", k);
fprintf(stderr,
"Error: no index specified action: %s\n", k);
ret = -1;
goto bad_val;
}
@ -500,7 +509,8 @@ static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p
argc -= 1;
argv += 1;
} else {
fprintf(stderr, "Error: no index specified action: %s\n", k);
fprintf(stderr,
"Error: no index specified action: %s\n", k);
ret = -1;
goto bad_val;
}
@ -536,7 +546,8 @@ bad_val:
return ret;
}
static int tc_action_modify(int cmd, unsigned int flags, int *argc_p, char ***argv_p)
static int tc_action_modify(int cmd, unsigned int flags,
int *argc_p, char ***argv_p)
{
int argc = *argc_p;
char **argv = *argv_p;
@ -581,7 +592,7 @@ static int tc_act_list_or_flush(int *argc_p, char ***argv_p, int event)
char **argv = *argv_p;
__u32 msec_since = 0;
int argc = *argc_p;
char k[16];
char k[FILTER_NAMESZ];
struct {
struct nlmsghdr n;
struct tcamsg t;
@ -597,9 +608,9 @@ static int tc_act_list_or_flush(int *argc_p, char ***argv_p, int event)
strncpy(k, *argv, sizeof(k) - 1);
#ifdef CONFIG_GACT
if (!gact_ld) {
if (!gact_ld)
get_action_kind("gact");
}
#endif
a = get_action_kind(k);
if (a == NULL) {
@ -637,10 +648,12 @@ static int tc_act_list_or_flush(int *argc_p, char ***argv_p, int event)
addattr32(&req.n, MAX_MSG, TCA_ROOT_TIME_DELTA, msec_since);
tail4->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail4;
}
msg_size = NLMSG_ALIGN(req.n.nlmsg_len) - NLMSG_ALIGN(sizeof(struct nlmsghdr));
msg_size = NLMSG_ALIGN(req.n.nlmsg_len)
- NLMSG_ALIGN(sizeof(struct nlmsghdr));
if (event == RTM_GETACTION) {
if (rtnl_dump_request(&rth, event, (void *)&req.t, msg_size) < 0) {
if (rtnl_dump_request(&rth, event,
(void *)&req.t, msg_size) < 0) {
perror("Cannot send dump request");
return 1;
}
@ -674,10 +687,14 @@ int do_action(int argc, char **argv)
while (argc > 0) {
if (matches(*argv, "add") == 0) {
ret = tc_action_modify(RTM_NEWACTION, NLM_F_EXCL|NLM_F_CREATE, &argc, &argv);
ret = tc_action_modify(RTM_NEWACTION,
NLM_F_EXCL | NLM_F_CREATE,
&argc, &argv);
} else if (matches(*argv, "change") == 0 ||
matches(*argv, "replace") == 0) {
ret = tc_action_modify(RTM_NEWACTION, NLM_F_CREATE|NLM_F_REPLACE, &argc, &argv);
ret = tc_action_modify(RTM_NEWACTION,
NLM_F_CREATE | NLM_F_REPLACE,
&argc, &argv);
} else if (matches(*argv, "delete") == 0) {
argc -= 1;
argv += 1;
@ -686,8 +703,9 @@ int do_action(int argc, char **argv)
argc -= 1;
argv += 1;
ret = tc_action_gd(RTM_GETACTION, 0, &argc, &argv);
} else if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
|| matches(*argv, "lst") == 0) {
} else if (matches(*argv, "list") == 0 ||
matches(*argv, "show") == 0 ||
matches(*argv, "lst") == 0) {
if (argc <= 2) {
act_usage();
return -1;
@ -711,7 +729,9 @@ int do_action(int argc, char **argv)
act_usage();
return -1;
} else {
fprintf(stderr, "Command \"%s\" is unknown, try \"tc actions help\".\n", *argv);
fprintf(stderr,
"Command \"%s\" is unknown, try \"tc actions help\".\n",
*argv);
return -1;
}

View File

@ -96,12 +96,16 @@ static int bpf_parse_opt(struct action_util *a, int *ptr_argc, char ***ptr_argv,
while (argc > 0) {
if (matches(*argv, "run") == 0) {
NEXT_ARG();
if (seen_run)
duparg("run", *argv);
opt_bpf:
seen_run = true;
cfg.type = bpf_type;
cfg.argc = argc;
cfg.argv = argv;
if (bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, n))
if (bpf_parse_and_load_common(&cfg, &bpf_cb_ops, n))
return -1;
argc = cfg.argc;

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __TC_EMATCH_H_
#define __TC_EMATCH_H_

View File

@ -115,17 +115,21 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p,
&pp.paction, false) == -1)
usage();
if (get_u16(&pp.pval, *argv, 10)) {
fprintf(stderr, "Illegal probability val 0x%x\n", pp.pval);
fprintf(stderr,
"Illegal probability val 0x%x\n",
pp.pval);
return -1;
}
if (pp.pval > 10000) {
fprintf(stderr, "Illegal probability val 0x%x\n", pp.pval);
fprintf(stderr,
"Illegal probability val 0x%x\n",
pp.pval);
return -1;
}
argc--;
argv++;
} else if (matches(*argv, "help") == 0) {
usage();
usage();
}
}
#endif
@ -140,7 +144,7 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p,
argc--;
argv++;
} else if (matches(*argv, "help") == 0) {
usage();
usage();
}
}
@ -148,9 +152,8 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p,
addattr_l(n, MAX_MSG, tca_id, NULL, 0);
addattr_l(n, MAX_MSG, TCA_GACT_PARMS, &p, sizeof(p));
#ifdef CONFIG_GACT_PROB
if (rd) {
if (rd)
addattr_l(n, MAX_MSG, TCA_GACT_PROB, &pp, sizeof(pp));
}
#endif
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
@ -160,7 +163,7 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p,
}
static int
print_gact(struct action_util *au, FILE * f, struct rtattr *arg)
print_gact(struct action_util *au, FILE *f, struct rtattr *arg)
{
#ifdef CONFIG_GACT_PROB
struct tc_gact_p *pp = NULL;
@ -175,12 +178,12 @@ print_gact(struct action_util *au, FILE * f, struct rtattr *arg)
parse_rtattr_nested(tb, TCA_GACT_MAX, arg);
if (tb[TCA_GACT_PARMS] == NULL) {
fprintf(f, "[NULL gact parameters]");
print_string(PRINT_FP, NULL, "%s", "[NULL gact parameters]");
return -1;
}
p = RTA_DATA(tb[TCA_GACT_PARMS]);
fprintf(f, "gact ");
print_string(PRINT_ANY, "kind", "%s ", "gact");
print_action_control(f, "action ", p->action, "");
#ifdef CONFIG_GACT_PROB
if (tb[TCA_GACT_PROB] != NULL) {
@ -190,12 +193,16 @@ print_gact(struct action_util *au, FILE * f, struct rtattr *arg)
memset(&pp_dummy, 0, sizeof(pp_dummy));
pp = &pp_dummy;
}
fprintf(f, "\n\t random type %s", prob_n2a(pp->ptype));
open_json_object("prob");
print_string(PRINT_ANY, "random_type", "\n\t random type %s",
prob_n2a(pp->ptype));
print_action_control(f, " ", pp->paction, " ");
fprintf(f, "val %d", pp->pval);
print_int(PRINT_ANY, "val", "val %d", pp->pval);
close_json_object();
#endif
fprintf(f, "\n\t index %u ref %d bind %d", p->index, p->refcnt,
p->bindcnt);
print_uint(PRINT_ANY, "index", "\n\t index %u", p->index);
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
if (show_stats) {
if (tb[TCA_GACT_TM]) {
struct tcf_t *tm = RTA_DATA(tb[TCA_GACT_TM]);
@ -203,7 +210,7 @@ print_gact(struct action_util *au, FILE * f, struct rtattr *arg)
print_tm(f, tm);
}
}
fprintf(f, "\n ");
print_string(PRINT_FP, NULL, "%s", "\n");
return 0;
}

View File

@ -286,7 +286,7 @@ static int parse_ipt(struct action_util *a, int *argc_p,
int rargc = *argc_p;
char **argv = *argv_p;
int argc = 0, iargc = 0;
char k[16];
char k[FILTER_NAMESZ];
int size = 0;
int iok = 0, ok = 0;
__u32 hook = 0, index = 0;

View File

@ -28,13 +28,13 @@
static void
explain(void)
{
fprintf(stderr, "Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>\n");
fprintf(stderr, "where:\n");
fprintf(stderr, "\tDIRECTION := <ingress | egress>\n");
fprintf(stderr, "\tACTION := <mirror | redirect>\n");
fprintf(stderr, "\tINDEX is the specific policy instance id\n");
fprintf(stderr, "\tDEVICENAME is the devicename\n");
fprintf(stderr,
"Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>\n"
"where:\n"
"\tDIRECTION := <ingress | egress>\n"
"\tACTION := <mirror | redirect>\n"
"\tINDEX is the specific policy instance id\n"
"\tDEVICENAME is the devicename\n");
}
static void
@ -60,6 +60,34 @@ static const char *mirred_n2a(int action)
}
}
static const char *mirred_direction(int action)
{
switch (action) {
case TCA_EGRESS_REDIR:
case TCA_EGRESS_MIRROR:
return "egress";
case TCA_INGRESS_REDIR:
case TCA_INGRESS_MIRROR:
return "ingress";
default:
return "unknown";
}
}
static const char *mirred_action(int action)
{
switch (action) {
case TCA_EGRESS_REDIR:
case TCA_INGRESS_REDIR:
return "redirect";
case TCA_EGRESS_MIRROR:
case TCA_INGRESS_MIRROR:
return "mirror";
default:
return "unknown";
}
}
static int
parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
int tca_id, struct nlmsghdr *n)
@ -70,7 +98,7 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
int ok = 0, iok = 0, mirror = 0, redir = 0, ingress = 0, egress = 0;
struct tc_mirred p = {};
struct rtattr *tail;
char d[16] = {};
char d[IFNAMSIZ] = {};
while (argc > 0) {
@ -79,7 +107,8 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
} else if (!egress && matches(*argv, "egress") == 0) {
egress = 1;
if (ingress) {
fprintf(stderr, "Can't have both egress and ingress\n");
fprintf(stderr,
"Can't have both egress and ingress\n");
return -1;
}
NEXT_ARG();
@ -88,7 +117,8 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
} else if (!ingress && matches(*argv, "ingress") == 0) {
ingress = 1;
if (egress) {
fprintf(stderr, "Can't have both ingress and egress\n");
fprintf(stderr,
"Can't have both ingress and egress\n");
return -1;
}
NEXT_ARG();
@ -109,30 +139,35 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
break;
}
} else if (!ok) {
fprintf(stderr, "was expecting egress or ingress (%s)\n", *argv);
fprintf(stderr,
"was expecting egress or ingress (%s)\n",
*argv);
break;
} else if (!mirror && matches(*argv, "mirror") == 0) {
mirror = 1;
if (redir) {
fprintf(stderr, "Can't have both mirror and redir\n");
fprintf(stderr,
"Can't have both mirror and redir\n");
return -1;
}
p.eaction = egress ? TCA_EGRESS_MIRROR :
TCA_INGRESS_MIRROR;
TCA_INGRESS_MIRROR;
p.action = TC_ACT_PIPE;
ok++;
} else if (!redir && matches(*argv, "redirect") == 0) {
redir = 1;
if (mirror) {
fprintf(stderr, "Can't have both mirror and redir\n");
fprintf(stderr,
"Can't have both mirror and redir\n");
return -1;
}
p.eaction = egress ? TCA_EGRESS_REDIR :
TCA_INGRESS_REDIR;
TCA_INGRESS_REDIR;
p.action = TC_ACT_STOLEN;
ok++;
} else if ((redir || mirror) && matches(*argv, "dev") == 0) {
} else if ((redir || mirror) &&
matches(*argv, "dev") == 0) {
NEXT_ARG();
if (strlen(d))
duparg("dev", *argv);
@ -149,18 +184,16 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
NEXT_ARG();
}
if (!ok && !iok) {
if (!ok && !iok)
return -1;
}
if (d[0]) {
int idx;
ll_init_map(&rth);
if ((idx = ll_name_to_index(d)) == 0) {
idx = ll_name_to_index(d);
if (idx == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n", d);
return -1;
}
@ -176,16 +209,17 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
if (iok && matches(*argv, "index") == 0) {
fprintf(stderr, "mirred: Illegal double index\n");
return -1;
} else {
if (matches(*argv, "index") == 0) {
NEXT_ARG();
if (get_u32(&p.index, *argv, 10)) {
fprintf(stderr, "mirred: Illegal \"index\"\n");
return -1;
}
argc--;
argv++;
}
if (matches(*argv, "index") == 0) {
NEXT_ARG();
if (get_u32(&p.index, *argv, 10)) {
fprintf(stderr,
"mirred: Illegal \"index\"\n");
return -1;
}
argc--;
argv++;
}
}
@ -242,7 +276,7 @@ parse_mirred(struct action_util *a, int *argc_p, char ***argv_p,
}
static int
print_mirred(struct action_util *au, FILE * f, struct rtattr *arg)
print_mirred(struct action_util *au, FILE *f, struct rtattr *arg)
{
struct tc_mirred *p;
struct rtattr *tb[TCA_MIRRED_MAX + 1];
@ -254,27 +288,29 @@ print_mirred(struct action_util *au, FILE * f, struct rtattr *arg)
parse_rtattr_nested(tb, TCA_MIRRED_MAX, arg);
if (tb[TCA_MIRRED_PARMS] == NULL) {
fprintf(f, "[NULL mirred parameters]");
print_string(PRINT_FP, NULL, "%s", "[NULL mirred parameters]");
return -1;
}
p = RTA_DATA(tb[TCA_MIRRED_PARMS]);
/*
ll_init_map(&rth);
*/
if ((dev = ll_index_to_name(p->ifindex)) == 0) {
dev = ll_index_to_name(p->ifindex);
if (dev == 0) {
fprintf(stderr, "Cannot find device %d\n", p->ifindex);
return -1;
}
fprintf(f, "mirred (%s to device %s)", mirred_n2a(p->eaction), dev);
print_string(PRINT_ANY, "kind", "%s ", "mirred");
print_string(PRINT_FP, NULL, "(%s", mirred_n2a(p->eaction));
print_string(PRINT_JSON, "mirred_action", NULL,
mirred_action(p->eaction));
print_string(PRINT_JSON, "direction", NULL,
mirred_direction(p->eaction));
print_string(PRINT_ANY, "to_dev", " to device %s)", dev);
print_action_control(f, " ", p->action, "");
fprintf(f, "\n ");
fprintf(f, "\tindex %u ref %d bind %d", p->index, p->refcnt,
p->bindcnt);
print_uint(PRINT_ANY, "index", "\n \tindex %u", p->index);
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
if (show_stats) {
if (tb[TCA_MIRRED_TM]) {
@ -283,7 +319,7 @@ print_mirred(struct action_util *au, FILE * f, struct rtattr *arg)
print_tm(f, tm);
}
}
fprintf(f, "\n ");
print_string(PRINT_FP, NULL, "%s", "\n ");
return 0;
}

View File

@ -524,7 +524,7 @@ static int parse_munge(int *argc_p, char ***argv_p, struct m_pedit_sel *sel)
res = parse_offset(&argc, &argv, sel, &tkey);
goto done;
} else {
char k[16];
char k[FILTER_NAMESZ];
struct m_pedit_util *p = NULL;
strncpy(k, *argv, sizeof(k) - 1);

View File

@ -27,13 +27,14 @@ static const char * const action_names[] = {
static void explain(void)
{
fprintf(stderr, "Usage: vlan pop\n");
fprintf(stderr, " vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n");
fprintf(stderr, " vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n");
fprintf(stderr, " VLANPROTO is one of 802.1Q or 802.1AD\n");
fprintf(stderr, " with default: 802.1Q\n");
fprintf(stderr, " CONTROL := reclassify | pipe | drop | continue | pass |\n");
fprintf(stderr, " goto chain <CHAIN_INDEX>\n");
fprintf(stderr,
"Usage: vlan pop\n"
" vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
" vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
" VLANPROTO is one of 802.1Q or 802.1AD\n"
" with default: 802.1Q\n"
" CONTROL := reclassify | pipe | drop | continue | pass |\n"
" goto chain <CHAIN_INDEX>\n");
}
static void usage(void)
@ -47,6 +48,14 @@ static bool has_push_attribs(int action)
return action == TCA_VLAN_ACT_PUSH || action == TCA_VLAN_ACT_MODIFY;
}
static void unexpected(const char *arg)
{
fprintf(stderr,
"unexpected \"%s\" - action already specified\n",
arg);
explain();
}
static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
int tca_id, struct nlmsghdr *n)
{
@ -70,57 +79,42 @@ static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
while (argc > 0) {
if (matches(*argv, "pop") == 0) {
if (action) {
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
*argv);
explain();
unexpected(*argv);
return -1;
}
action = TCA_VLAN_ACT_POP;
} else if (matches(*argv, "push") == 0) {
if (action) {
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
*argv);
explain();
unexpected(*argv);
return -1;
}
action = TCA_VLAN_ACT_PUSH;
} else if (matches(*argv, "modify") == 0) {
if (action) {
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
*argv);
explain();
unexpected(*argv);
return -1;
}
action = TCA_VLAN_ACT_MODIFY;
} else if (matches(*argv, "id") == 0) {
if (!has_push_attribs(action)) {
fprintf(stderr, "\"%s\" is only valid for push/modify\n",
*argv);
explain();
return -1;
}
if (!has_push_attribs(action))
invarg("only valid for push/modify", *argv);
NEXT_ARG();
if (get_u16(&id, *argv, 0))
invarg("id is invalid", *argv);
id_set = 1;
} else if (matches(*argv, "protocol") == 0) {
if (!has_push_attribs(action)) {
fprintf(stderr, "\"%s\" is only valid for push/modify\n",
*argv);
explain();
return -1;
}
if (!has_push_attribs(action))
invarg("only valid for push/modify", *argv);
NEXT_ARG();
if (ll_proto_a2n(&proto, *argv))
invarg("protocol is invalid", *argv);
proto_set = 1;
} else if (matches(*argv, "priority") == 0) {
if (!has_push_attribs(action)) {
fprintf(stderr, "\"%s\" is only valid for push/modify\n",
*argv);
explain();
return -1;
}
if (!has_push_attribs(action))
invarg("only valid for push/modify", *argv);
NEXT_ARG();
if (get_u8(&prio, *argv, 0) || (prio & ~0x7))
invarg("prio is invalid", *argv);
@ -195,39 +189,40 @@ static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg)
parse_rtattr_nested(tb, TCA_VLAN_MAX, arg);
if (!tb[TCA_VLAN_PARMS]) {
fprintf(f, "[NULL vlan parameters]");
print_string(PRINT_FP, NULL, "%s", "[NULL vlan parameters]");
return -1;
}
parm = RTA_DATA(tb[TCA_VLAN_PARMS]);
fprintf(f, " vlan");
print_string(PRINT_ANY, "kind", "%s ", "vlan");
print_string(PRINT_ANY, "vlan_action", " %s",
action_names[parm->v_action]);
switch (parm->v_action) {
case TCA_VLAN_ACT_POP:
fprintf(f, " pop");
break;
case TCA_VLAN_ACT_PUSH:
case TCA_VLAN_ACT_MODIFY:
fprintf(f, " %s", action_names[parm->v_action]);
if (tb[TCA_VLAN_PUSH_VLAN_ID]) {
val = rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
fprintf(f, " id %u", val);
print_uint(PRINT_ANY, "id", " id %u", val);
}
if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
fprintf(f, " protocol %s",
ll_proto_n2a(rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]),
b1, sizeof(b1)));
__u16 proto;
proto = rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]);
print_string(PRINT_ANY, "protocol", " protocol %s",
ll_proto_n2a(proto, b1, sizeof(b1)));
}
if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) {
val = rta_getattr_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]);
fprintf(f, " priority %u", val);
print_uint(PRINT_ANY, "priority", " priority %u", val);
}
break;
}
print_action_control(f, " ", parm->action, "");
fprintf(f, "\n\t index %u ref %d bind %d", parm->index, parm->refcnt,
parm->bindcnt);
print_uint(PRINT_ANY, "index", "\n\t index %u", parm->index);
print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
if (show_stats) {
if (tb[TCA_VLAN_TM]) {
@ -237,7 +232,7 @@ static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg)
}
}
fprintf(f, "\n ");
print_string(PRINT_FP, NULL, "%s", "\n");
return 0;
}

View File

@ -154,7 +154,7 @@ static int parse_ipt(struct action_util *a, int *argc_p,
int c;
char **argv = *argv_p;
int argc;
char k[16];
char k[FILTER_NAMESZ];
int size = 0;
int iok = 0, ok = 0;
__u32 hook = 0, index = 0;

Some files were not shown because too many files have changed in this diff Show More