Merge branch 'master' into net-next
This commit is contained in:
commit
f6351157b9
1
Makefile
1
Makefile
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Top level Makefile for iproute2
|
||||
|
||||
ifeq ($(VERBOSE),0)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Get/set/delete bridge with netlink
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Get/set/delete fdb table with netlink
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Get mdb table with netlink
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#! /bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# This is not an autoconf generated configure
|
||||
#
|
||||
INCLUDE=${1:-"$PWD/include"}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
include ../config.mk
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include "../../include/bpf_api.h"
|
||||
|
||||
#define ENTRY_INIT 3
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
GENLOBJ=genl.o
|
||||
|
||||
include ../config.mk
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _TC_UTIL_H_
|
||||
#define _TC_UTIL_H_ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* This file creates a dummy version of dynamic loading
|
||||
* for environments where dynamic linking
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __BPF_API__
|
||||
#define __BPF_API__
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __BPF_ELF__
|
||||
#define __BPF_ELF__
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __BPF_SCM__
|
||||
#define __BPF_SCM__
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __COLOR_H__
|
||||
#define __COLOR_H__ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _IP6TABLES_USER_H
|
||||
#define _IP6TABLES_USER_H
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _IPTABLES_USER_H
|
||||
#define _IPTABLES_USER_H
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef IPTABLES_INTERNAL_H
|
||||
#define IPTABLES_INTERNAL_H 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LIBGENL_H__
|
||||
#define __LIBGENL_H__
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LIBIP6TC_H
|
||||
#define _LIBIP6TC_H
|
||||
/* Library which manipulates firewall rules. Version 0.2. */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LIBIPTC_H
|
||||
#define _LIBIPTC_H
|
||||
/* Library which manipulates filtering rules. */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LIBXTC_H
|
||||
#define _LIBXTC_H
|
||||
/* Library which manipulates filtering rules. */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LIBXTC_SHARED_H
|
||||
#define _LIBXTC_SHARED_H 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LIBNETLINK_H__
|
||||
#define __LIBNETLINK_H__ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LIST_H__
|
||||
#define __LIST_H__ 1
|
||||
/* List and hash list stuff from kernel */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LL_MAP_H__
|
||||
#define __LL_MAP_H__ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef DB_NAMES_H_
|
||||
#define DB_NAMES_H_ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __NAMESPACE_H__
|
||||
#define __NAMESPACE_H__ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef RT_NAMES_H_
|
||||
#define RT_NAMES_H_ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __RTM_MAP_H__
|
||||
#define __RTM_MAP_H__ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _XTABLES_INTERNAL_H
|
||||
#define _XTABLES_INTERNAL_H 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _XTABLES_H
|
||||
#define _XTABLES_H
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
1
ip/ifcfg
1
ip/ifcfg
|
|
@ -1,4 +1,5 @@
|
|||
#! /bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
CheckForwarding () {
|
||||
local sbase fwd
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ILA_COMMON_H_
|
||||
#define _ILA_COMMON_H_
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _IP_COMMON_H_
|
||||
#define _IP_COMMON_H_
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#define _ATFILE_SOURCE
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LWTUNNEL_H__
|
||||
#define __LETUNNEL_H__ 1
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#! /bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
if [ -z "$*" ] ; then
|
||||
exec ip -4 ro flush scope global type unicast
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
1
ip/rtpr
1
ip/rtpr
|
|
@ -1,4 +1,5 @@
|
|||
#! /bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
exec tr "[\\\\]" "[
|
||||
]"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* This file creates a dummy version of dynamic loading
|
||||
* for environments where dynamic linking
|
||||
|
|
|
|||
5
ip/xdp.h
5
ip/xdp.h
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
include ../config.mk
|
||||
|
||||
CFLAGS += -fPIC
|
||||
|
|
|
|||
155
lib/bpf.c
155
lib/bpf.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* libgenl.c GENL library
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
|
|
|||
68
lib/utils.c
68
lib/utils.c
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
INSTALL=install
|
||||
INSTALLDIR=install -m 0755 -d
|
||||
INSTALLMAN=install -m 0644
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
MAN3PAGES = $(wildcard *.3)
|
||||
|
||||
all:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
MAN7PAGES = $(wildcard *.7)
|
||||
|
||||
all:
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
SSOBJ=ss.o ssfilter.o
|
||||
LNSTATOBJ=lnstat.o lnstat_util.o
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LNSTAT_H
|
||||
#define _LNSTAT_H
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#define SSF_DCOND 0
|
||||
#define SSF_SCOND 1
|
||||
#define SSF_OR 2
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
include ../config.mk
|
||||
|
||||
DISTGEN = maketable normal pareto paretonormal
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
include ../config.mk
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
%{
|
||||
#include "emp_ematch.yacc.h"
|
||||
#include "m_ematch.h"
|
||||
|
|
|
|||
18
tc/f_bpf.c
18
tc/f_bpf.c
|
|
@ -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)
|
||||
|
|
|
|||
287
tc/f_flower.c
287
tc/f_flower.c
|
|
@ -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, ð_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
|
||||
flower_print_ip_proto(f, &ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
|
||||
flower_print_eth_type(ð_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])
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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 = {};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* f_tcindex.c Traffic control index filter
|
||||
*
|
||||
|
|
|
|||
114
tc/m_action.c
114
tc/m_action.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __TC_EMATCH_H_
|
||||
#define __TC_EMATCH_H_
|
||||
|
||||
|
|
|
|||
35
tc/m_gact.c
35
tc/m_gact.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
122
tc/m_mirred.c
122
tc/m_mirred.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
91
tc/m_vlan.c
91
tc/m_vlan.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue