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
|
# Top level Makefile for iproute2
|
||||||
|
|
||||||
ifeq ($(VERBOSE),0)
|
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
|
BROBJ = bridge.o fdb.o monitor.o link.o mdb.o vlan.o
|
||||||
|
|
||||||
include ../config.mk
|
include ../config.mk
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
#define MDB_RTA(r) \
|
#define MDB_RTA(r) \
|
||||||
((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(struct br_mdb_entry))))
|
((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
|
* Get/set/delete bridge with netlink
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
/*
|
/*
|
||||||
* Get/set/delete fdb table with netlink
|
* Get/set/delete fdb table with netlink
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
/*
|
/*
|
||||||
* Get mdb table with netlink
|
* Get mdb table with netlink
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
# This is not an autoconf generated configure
|
# This is not an autoconf generated configure
|
||||||
#
|
#
|
||||||
INCLUDE=${1:-"$PWD/include"}
|
INCLUDE=${1:-"$PWD/include"}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
include ../config.mk
|
include ../config.mk
|
||||||
|
|
||||||
ifeq ($(HAVE_MNL),y)
|
ifeq ($(HAVE_MNL),y)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include "../../include/bpf_api.h"
|
#include "../../include/bpf_api.h"
|
||||||
|
|
||||||
#define ENTRY_INIT 3
|
#define ENTRY_INIT 3
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
GENLOBJ=genl.o
|
GENLOBJ=genl.o
|
||||||
|
|
||||||
include ../config.mk
|
include ../config.mk
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _TC_UTIL_H_
|
#ifndef _TC_UTIL_H_
|
||||||
#define _TC_UTIL_H_ 1
|
#define _TC_UTIL_H_ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
/*
|
/*
|
||||||
* This file creates a dummy version of dynamic loading
|
* This file creates a dummy version of dynamic loading
|
||||||
* for environments where dynamic linking
|
* for environments where dynamic linking
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __BPF_API__
|
#ifndef __BPF_API__
|
||||||
#define __BPF_API__
|
#define __BPF_API__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __BPF_ELF__
|
#ifndef __BPF_ELF__
|
||||||
#define __BPF_ELF__
|
#define __BPF_ELF__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __BPF_SCM__
|
#ifndef __BPF_SCM__
|
||||||
#define __BPF_SCM__
|
#define __BPF_SCM__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,29 @@ struct bpf_cfg_ops {
|
||||||
void (*ebpf_cb)(void *nl, int fd, const char *annotation);
|
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 {
|
struct bpf_cfg_in {
|
||||||
const char *object;
|
const char *object;
|
||||||
const char *section;
|
const char *section;
|
||||||
const char *uds;
|
const char *uds;
|
||||||
|
enum bpf_prog_type type;
|
||||||
|
enum bpf_mode mode;
|
||||||
|
__u32 ifindex;
|
||||||
|
bool verbose;
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
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 */
|
/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
|
||||||
|
|
@ -244,8 +260,11 @@ struct bpf_cfg_in {
|
||||||
.off = 0, \
|
.off = 0, \
|
||||||
.imm = 0 })
|
.imm = 0 })
|
||||||
|
|
||||||
int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
|
int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops);
|
||||||
const struct bpf_cfg_ops *ops, void *nl);
|
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);
|
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__
|
#ifndef __COLOR_H__
|
||||||
#define __COLOR_H__ 1
|
#define __COLOR_H__ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
/*
|
/*
|
||||||
* Stub dlfcn implementation for systems that lack shared library support
|
* Stub dlfcn implementation for systems that lack shared library support
|
||||||
* but obviously can still reference compiled-in symbols.
|
* but obviously can still reference compiled-in symbols.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _IP6TABLES_USER_H
|
#ifndef _IP6TABLES_USER_H
|
||||||
#define _IP6TABLES_USER_H
|
#define _IP6TABLES_USER_H
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _IPTABLES_USER_H
|
#ifndef _IPTABLES_USER_H
|
||||||
#define _IPTABLES_USER_H
|
#define _IPTABLES_USER_H
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef IPTABLES_INTERNAL_H
|
#ifndef IPTABLES_INTERNAL_H
|
||||||
#define IPTABLES_INTERNAL_H 1
|
#define IPTABLES_INTERNAL_H 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __LIBGENL_H__
|
#ifndef __LIBGENL_H__
|
||||||
#define __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,
|
/* This is the userspace/kernel interface for Generic IP Chains,
|
||||||
required for libc6. */
|
required for libc6. */
|
||||||
#ifndef _FWCHAINS_KERNEL_HEADERS_H
|
#ifndef _FWCHAINS_KERNEL_HEADERS_H
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _LIBIP6TC_H
|
#ifndef _LIBIP6TC_H
|
||||||
#define _LIBIP6TC_H
|
#define _LIBIP6TC_H
|
||||||
/* Library which manipulates firewall rules. Version 0.2. */
|
/* Library which manipulates firewall rules. Version 0.2. */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _LIBIPTC_H
|
#ifndef _LIBIPTC_H
|
||||||
#define _LIBIPTC_H
|
#define _LIBIPTC_H
|
||||||
/* Library which manipulates filtering rules. */
|
/* Library which manipulates filtering rules. */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _LIBXTC_H
|
#ifndef _LIBXTC_H
|
||||||
#define _LIBXTC_H
|
#define _LIBXTC_H
|
||||||
/* Library which manipulates filtering rules. */
|
/* Library which manipulates filtering rules. */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _LIBXTC_SHARED_H
|
#ifndef _LIBXTC_SHARED_H
|
||||||
#define _LIBXTC_SHARED_H 1
|
#define _LIBXTC_SHARED_H 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __LIBNETLINK_H__
|
#ifndef __LIBNETLINK_H__
|
||||||
#define __LIBNETLINK_H__ 1
|
#define __LIBNETLINK_H__ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __LIST_H__
|
#ifndef __LIST_H__
|
||||||
#define __LIST_H__ 1
|
#define __LIST_H__ 1
|
||||||
/* List and hash list stuff from kernel */
|
/* List and hash list stuff from kernel */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __LL_MAP_H__
|
#ifndef __LL_MAP_H__
|
||||||
#define __LL_MAP_H__ 1
|
#define __LL_MAP_H__ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef DB_NAMES_H_
|
#ifndef DB_NAMES_H_
|
||||||
#define DB_NAMES_H_ 1
|
#define DB_NAMES_H_ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __NAMESPACE_H__
|
#ifndef __NAMESPACE_H__
|
||||||
#define __NAMESPACE_H__ 1
|
#define __NAMESPACE_H__ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef RT_NAMES_H_
|
#ifndef RT_NAMES_H_
|
||||||
#define RT_NAMES_H_ 1
|
#define RT_NAMES_H_ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __RTM_MAP_H__
|
#ifndef __RTM_MAP_H__
|
||||||
#define __RTM_MAP_H__ 1
|
#define __RTM_MAP_H__ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __UTILS_H__
|
#ifndef __UTILS_H__
|
||||||
#define __UTILS_H__ 1
|
#define __UTILS_H__ 1
|
||||||
|
|
||||||
|
|
@ -88,6 +89,8 @@ int get_prefix(inet_prefix *dst, char *arg, int family);
|
||||||
int mask2bits(__u32 netmask);
|
int mask2bits(__u32 netmask);
|
||||||
int get_addr_ila(__u64 *val, const char *arg);
|
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_hex(char c);
|
||||||
int get_integer(int *val, const char *arg, int base);
|
int get_integer(int *val, const char *arg, int base);
|
||||||
int get_unsigned(unsigned *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
|
#ifndef _XTABLES_INTERNAL_H
|
||||||
#define _XTABLES_INTERNAL_H 1
|
#define _XTABLES_INTERNAL_H 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _XTABLES_H
|
#ifndef _XTABLES_H
|
||||||
#define _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 \
|
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 \
|
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 \
|
ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \
|
||||||
|
|
|
||||||
1
ip/ifcfg
1
ip/ifcfg
|
|
@ -1,4 +1,5 @@
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
CheckForwarding () {
|
CheckForwarding () {
|
||||||
local sbase fwd
|
local sbase fwd
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _ILA_COMMON_H_
|
#ifndef _ILA_COMMON_H_
|
||||||
#define _ILA_COMMON_H_
|
#define _ILA_COMMON_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _IP_COMMON_H_
|
#ifndef _IP_COMMON_H_
|
||||||
#define _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;
|
bool offload = strcmp(*argv, "xdpoffload") == 0;
|
||||||
|
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (xdp_parse(&argc, &argv, req, generic, drv,
|
if (xdp_parse(&argc, &argv, req, dev_index,
|
||||||
offload))
|
generic, drv, offload))
|
||||||
exit(-1);
|
exit(-1);
|
||||||
} else if (strcmp(*argv, "netns") == 0) {
|
} else if (strcmp(*argv, "netns") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -345,7 +345,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||||
return -1;
|
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");
|
fprintf(stderr, "vxlan: missing virtual network identifier\n");
|
||||||
return -1;
|
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");
|
"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)
|
if (gaddr)
|
||||||
addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
|
addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
|
||||||
else if (daddr)
|
else if (daddr)
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,11 @@ static int xdp_delete(struct xdp_req *xdp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
|
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, __u32 ifindex,
|
||||||
bool drv, bool offload)
|
bool generic, bool drv, bool offload)
|
||||||
{
|
{
|
||||||
struct bpf_cfg_in cfg = {
|
struct bpf_cfg_in cfg = {
|
||||||
|
.type = BPF_PROG_TYPE_XDP,
|
||||||
.argc = *argc,
|
.argc = *argc,
|
||||||
.argv = *argv,
|
.argv = *argv,
|
||||||
};
|
};
|
||||||
|
|
@ -59,6 +60,12 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
|
||||||
.req = req,
|
.req = req,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (offload) {
|
||||||
|
if (!ifindex)
|
||||||
|
incomplete_command();
|
||||||
|
cfg.ifindex = ifindex;
|
||||||
|
}
|
||||||
|
|
||||||
if (!force)
|
if (!force)
|
||||||
xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST;
|
xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST;
|
||||||
if (generic)
|
if (generic)
|
||||||
|
|
@ -74,7 +81,7 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
|
||||||
return xdp_delete(&xdp);
|
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;
|
return -1;
|
||||||
|
|
||||||
*argc = cfg.argc;
|
*argc = cfg.argc;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#define _ATFILE_SOURCE
|
#define _ATFILE_SOURCE
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.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)
|
int attr, const enum bpf_prog_type bpf_type)
|
||||||
{
|
{
|
||||||
struct bpf_cfg_in cfg = {
|
struct bpf_cfg_in cfg = {
|
||||||
|
.type = bpf_type,
|
||||||
.argc = *argcp,
|
.argc = *argcp,
|
||||||
.argv = *argvp,
|
.argv = *argvp,
|
||||||
};
|
};
|
||||||
|
|
@ -897,7 +898,7 @@ static int lwt_parse_bpf(struct rtattr *rta, size_t len,
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
nest = rta_nest(rta, len, attr);
|
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) {
|
if (err < 0) {
|
||||||
fprintf(stderr, "Failed to parse eBPF program: %s\n",
|
fprintf(stderr, "Failed to parse eBPF program: %s\n",
|
||||||
strerror(-err));
|
strerror(-err));
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __LWTUNNEL_H__
|
#ifndef __LWTUNNEL_H__
|
||||||
#define __LETUNNEL_H__ 1
|
#define __LETUNNEL_H__ 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -223,38 +223,6 @@ static int do_del(int argc, char **argv)
|
||||||
return tap_del_ioctl(&ifr);
|
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)
|
static void print_flags(long flags)
|
||||||
{
|
{
|
||||||
if (flags & IFF_TUN)
|
if (flags & IFF_TUN)
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,8 @@ get_failed:
|
||||||
if (uval > 255)
|
if (uval > 255)
|
||||||
invarg("TTL must be <= 255\n", *argv);
|
invarg("TTL must be <= 255\n", *argv);
|
||||||
ttl = uval;
|
ttl = uval;
|
||||||
}
|
} else
|
||||||
|
ttl = 0;
|
||||||
} else if (!matches(*argv, "tos") ||
|
} else if (!matches(*argv, "tos") ||
|
||||||
!matches(*argv, "tclass") ||
|
!matches(*argv, "tclass") ||
|
||||||
!matches(*argv, "dsfield")) {
|
!matches(*argv, "dsfield")) {
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ get_failed:
|
||||||
} else {
|
} else {
|
||||||
__u8 uval;
|
__u8 uval;
|
||||||
|
|
||||||
if (get_u8(&uval, *argv, 0) < -1)
|
if (get_u8(&uval, *argv, 0))
|
||||||
invarg("invalid ELIM", *argv);
|
invarg("invalid ELIM", *argv);
|
||||||
encap_limit = uval;
|
encap_limit = uval;
|
||||||
flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
|
flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
if [ -z "$*" ] ; then
|
if [ -z "$*" ] ; then
|
||||||
exec ip -4 ro flush scope global type unicast
|
exec ip -4 ro flush scope global type unicast
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#$Id$
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
#
|
#
|
||||||
# Script created by: Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18
|
# 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
|
#! /bin/bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
exec tr "[\\\\]" "[
|
exec tr "[\\\\]" "[
|
||||||
]"
|
]"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
/*
|
/*
|
||||||
* This file creates a dummy version of dynamic loading
|
* This file creates a dummy version of dynamic loading
|
||||||
* for environments where dynamic linking
|
* 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__
|
#ifndef __XDP__
|
||||||
#define __XDP__
|
#define __XDP__
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
|
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, __u32 ifindex,
|
||||||
bool drv, bool offload);
|
bool generic, bool drv, bool offload);
|
||||||
void xdp_dump(FILE *fp, struct rtattr *tb, bool link, bool details);
|
void xdp_dump(FILE *fp, struct rtattr *tb, bool link, bool details);
|
||||||
|
|
||||||
#endif /* __XDP__ */
|
#endif /* __XDP__ */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
include ../config.mk
|
include ../config.mk
|
||||||
|
|
||||||
CFLAGS += -fPIC
|
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
|
#ifdef HAVE_ELF
|
||||||
static int bpf_obj_open(const char *path, enum bpf_prog_type type,
|
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
|
#else
|
||||||
static int bpf_obj_open(const char *path, enum bpf_prog_type type,
|
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");
|
fprintf(stderr, "No ELF library support compiled in.\n");
|
||||||
errno = ENOSYS;
|
errno = ENOSYS;
|
||||||
|
|
@ -805,16 +805,7 @@ static int bpf_obj_pinned(const char *pathname, enum bpf_prog_type type)
|
||||||
return prog_fd;
|
return prog_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum bpf_mode {
|
static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
const char *file, *section, *uds_name;
|
const char *file, *section, *uds_name;
|
||||||
bool verbose = false;
|
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] &&
|
if (opt_tbl[CBPF_BYTECODE] &&
|
||||||
(matches(*argv, "bytecode") == 0 ||
|
(matches(*argv, "bytecode") == 0 ||
|
||||||
strcmp(*argv, "bc") == 0)) {
|
strcmp(*argv, "bc") == 0)) {
|
||||||
*mode = CBPF_BYTECODE;
|
cfg->mode = CBPF_BYTECODE;
|
||||||
} else if (opt_tbl[CBPF_FILE] &&
|
} else if (opt_tbl[CBPF_FILE] &&
|
||||||
(matches(*argv, "bytecode-file") == 0 ||
|
(matches(*argv, "bytecode-file") == 0 ||
|
||||||
strcmp(*argv, "bcf") == 0)) {
|
strcmp(*argv, "bcf") == 0)) {
|
||||||
*mode = CBPF_FILE;
|
cfg->mode = CBPF_FILE;
|
||||||
} else if (opt_tbl[EBPF_OBJECT] &&
|
} else if (opt_tbl[EBPF_OBJECT] &&
|
||||||
(matches(*argv, "object-file") == 0 ||
|
(matches(*argv, "object-file") == 0 ||
|
||||||
strcmp(*argv, "obj") == 0)) {
|
strcmp(*argv, "obj") == 0)) {
|
||||||
*mode = EBPF_OBJECT;
|
cfg->mode = EBPF_OBJECT;
|
||||||
} else if (opt_tbl[EBPF_PINNED] &&
|
} else if (opt_tbl[EBPF_PINNED] &&
|
||||||
(matches(*argv, "object-pinned") == 0 ||
|
(matches(*argv, "object-pinned") == 0 ||
|
||||||
matches(*argv, "pinned") == 0 ||
|
matches(*argv, "pinned") == 0 ||
|
||||||
matches(*argv, "fd") == 0)) {
|
matches(*argv, "fd") == 0)) {
|
||||||
*mode = EBPF_PINNED;
|
cfg->mode = EBPF_PINNED;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "What mode is \"%s\"?\n", *argv);
|
fprintf(stderr, "What mode is \"%s\"?\n", *argv);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -848,11 +839,11 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
|
||||||
|
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
file = section = uds_name = NULL;
|
file = section = uds_name = NULL;
|
||||||
if (*mode == EBPF_OBJECT || *mode == EBPF_PINNED) {
|
if (cfg->mode == EBPF_OBJECT || cfg->mode == EBPF_PINNED) {
|
||||||
file = *argv;
|
file = *argv;
|
||||||
NEXT_ARG_FWD();
|
NEXT_ARG_FWD();
|
||||||
|
|
||||||
if (*type == BPF_PROG_TYPE_UNSPEC) {
|
if (cfg->type == BPF_PROG_TYPE_UNSPEC) {
|
||||||
if (argc > 0 && matches(*argv, "type") == 0) {
|
if (argc > 0 && matches(*argv, "type") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
for (i = 0; i < ARRAY_SIZE(__bpf_prog_meta);
|
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;
|
continue;
|
||||||
if (!matches(*argv,
|
if (!matches(*argv,
|
||||||
__bpf_prog_meta[i].type)) {
|
__bpf_prog_meta[i].type)) {
|
||||||
*type = i;
|
cfg->type = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*type == BPF_PROG_TYPE_UNSPEC) {
|
if (cfg->type == BPF_PROG_TYPE_UNSPEC) {
|
||||||
fprintf(stderr, "What type is \"%s\"?\n",
|
fprintf(stderr, "What type is \"%s\"?\n",
|
||||||
*argv);
|
*argv);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
NEXT_ARG_FWD();
|
NEXT_ARG_FWD();
|
||||||
} else {
|
} 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) {
|
if (argc > 0 && matches(*argv, "section") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
section = *argv;
|
section = *argv;
|
||||||
NEXT_ARG_FWD();
|
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);
|
uds_name = getenv(BPF_ENV_UDS);
|
||||||
if (argc > 0 && !uds_name &&
|
if (argc > 0 && !uds_name &&
|
||||||
matches(*argv, "export") == 0) {
|
matches(*argv, "export") == 0) {
|
||||||
|
|
@ -902,53 +893,63 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
|
||||||
PREV_ARG();
|
PREV_ARG();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE)
|
if (cfg->mode == CBPF_BYTECODE || cfg->mode == CBPF_FILE) {
|
||||||
ret = bpf_ops_parse(argc, argv, cfg->ops, *mode == CBPF_FILE);
|
ret = bpf_ops_parse(argc, argv, cfg->opcodes,
|
||||||
else if (*mode == EBPF_OBJECT)
|
cfg->mode == CBPF_FILE);
|
||||||
ret = bpf_obj_open(file, *type, section, verbose);
|
cfg->n_opcodes = ret;
|
||||||
else if (*mode == EBPF_PINNED)
|
} else if (cfg->mode == EBPF_OBJECT) {
|
||||||
ret = bpf_obj_pinned(file, *type);
|
ret = 0; /* program will be loaded by load stage */
|
||||||
else
|
} else if (cfg->mode == EBPF_PINNED) {
|
||||||
|
ret = bpf_obj_pinned(file, cfg->type);
|
||||||
|
cfg->prog_fd = ret;
|
||||||
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
cfg->object = file;
|
cfg->object = file;
|
||||||
cfg->section = section;
|
cfg->section = section;
|
||||||
cfg->uds = uds_name;
|
cfg->uds = uds_name;
|
||||||
cfg->argc = argc;
|
cfg->argc = argc;
|
||||||
cfg->argv = argv;
|
cfg->argv = argv;
|
||||||
|
cfg->verbose = verbose;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bpf_parse_opt_tbl(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
|
static int bpf_do_load(struct bpf_cfg_in *cfg)
|
||||||
const struct bpf_cfg_ops *ops, void *nl,
|
{
|
||||||
const bool *opt_tbl)
|
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];
|
char annotation[256];
|
||||||
enum bpf_mode mode;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cfg->ops = opcodes;
|
ret = bpf_do_load(cfg);
|
||||||
ret = bpf_parse(&type, &mode, cfg, opt_tbl);
|
|
||||||
cfg->ops = NULL;
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (mode == CBPF_BYTECODE || mode == CBPF_FILE)
|
if (cfg->mode == CBPF_BYTECODE || cfg->mode == CBPF_FILE)
|
||||||
ops->cbpf_cb(nl, opcodes, ret);
|
ops->cbpf_cb(nl, cfg->opcodes, cfg->n_opcodes);
|
||||||
if (mode == EBPF_OBJECT || mode == EBPF_PINNED) {
|
if (cfg->mode == EBPF_OBJECT || cfg->mode == EBPF_PINNED) {
|
||||||
snprintf(annotation, sizeof(annotation), "%s:[%s]",
|
snprintf(annotation, sizeof(annotation), "%s:[%s]",
|
||||||
basename(cfg->object), mode == EBPF_PINNED ?
|
basename(cfg->object), cfg->mode == EBPF_PINNED ?
|
||||||
"*fsobj" : cfg->section);
|
"*fsobj" : cfg->section);
|
||||||
ops->ebpf_cb(nl, ret, annotation);
|
ops->ebpf_cb(nl, cfg->prog_fd, annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
|
int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops)
|
||||||
const struct bpf_cfg_ops *ops, void *nl)
|
|
||||||
{
|
{
|
||||||
bool opt_tbl[BPF_MODE_MAX] = {};
|
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;
|
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)
|
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] = {
|
const bool opt_tbl[BPF_MODE_MAX] = {
|
||||||
[EBPF_OBJECT] = true,
|
[EBPF_OBJECT] = true,
|
||||||
[EBPF_PINNED] = 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),
|
.size_value = sizeof(int),
|
||||||
};
|
};
|
||||||
struct bpf_cfg_in cfg = {
|
struct bpf_cfg_in cfg = {
|
||||||
|
.type = BPF_PROG_TYPE_UNSPEC,
|
||||||
.argc = argc,
|
.argc = argc,
|
||||||
.argv = argv,
|
.argv = argv,
|
||||||
};
|
};
|
||||||
struct bpf_map_ext ext = {};
|
struct bpf_map_ext ext = {};
|
||||||
int ret, prog_fd, map_fd;
|
int ret, prog_fd, map_fd;
|
||||||
enum bpf_mode mode;
|
|
||||||
uint32_t map_key;
|
uint32_t map_key;
|
||||||
|
|
||||||
prog_fd = bpf_parse(&type, &mode, &cfg, opt_tbl);
|
ret = bpf_do_parse(&cfg, opt_tbl);
|
||||||
if (prog_fd < 0)
|
if (ret < 0)
|
||||||
return prog_fd;
|
return ret;
|
||||||
|
|
||||||
|
ret = bpf_do_load(&cfg);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
prog_fd = cfg.prog_fd;
|
||||||
|
|
||||||
if (key) {
|
if (key) {
|
||||||
map_key = *key;
|
map_key = *key;
|
||||||
} else {
|
} 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) {
|
if (map_fd < 0) {
|
||||||
fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n",
|
fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n",
|
||||||
map_path, strerror(errno));
|
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,
|
ret = bpf_map_selfcheck_pinned(map_fd, &test, &ext,
|
||||||
offsetof(struct bpf_elf_map, max_elem),
|
offsetof(struct bpf_elf_map, max_elem),
|
||||||
type);
|
cfg.type);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path);
|
fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path);
|
||||||
goto out_map;
|
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));
|
return bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
|
static int bpf_prog_load_dev(enum bpf_prog_type type,
|
||||||
size_t size_insns, const char *license, char *log,
|
const struct bpf_insn *insns, size_t size_insns,
|
||||||
size_t size_log)
|
const char *license, __u32 ifindex,
|
||||||
|
char *log, size_t size_log)
|
||||||
{
|
{
|
||||||
union bpf_attr attr = {};
|
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.insns = bpf_ptr_to_u64(insns);
|
||||||
attr.insn_cnt = size_insns / sizeof(struct bpf_insn);
|
attr.insn_cnt = size_insns / sizeof(struct bpf_insn);
|
||||||
attr.license = bpf_ptr_to_u64(license);
|
attr.license = bpf_ptr_to_u64(license);
|
||||||
|
attr.prog_ifindex = ifindex;
|
||||||
|
|
||||||
if (size_log > 0) {
|
if (size_log > 0) {
|
||||||
attr.log_buf = bpf_ptr_to_u64(log);
|
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));
|
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
|
#ifdef HAVE_ELF
|
||||||
struct bpf_elf_prog {
|
struct bpf_elf_prog {
|
||||||
enum bpf_prog_type type;
|
enum bpf_prog_type type;
|
||||||
|
|
@ -1102,6 +1131,7 @@ struct bpf_elf_ctx {
|
||||||
int sec_maps;
|
int sec_maps;
|
||||||
char license[ELF_MAX_LICENSE_LEN];
|
char license[ELF_MAX_LICENSE_LEN];
|
||||||
enum bpf_prog_type type;
|
enum bpf_prog_type type;
|
||||||
|
__u32 ifindex;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
struct bpf_elf_st stat;
|
struct bpf_elf_st stat;
|
||||||
struct bpf_hash_entry *ht[256];
|
struct bpf_hash_entry *ht[256];
|
||||||
|
|
@ -1474,8 +1504,9 @@ static int bpf_prog_attach(const char *section,
|
||||||
int tries = 0, fd;
|
int tries = 0, fd;
|
||||||
retry:
|
retry:
|
||||||
errno = 0;
|
errno = 0;
|
||||||
fd = bpf_prog_load(prog->type, prog->insns, prog->size,
|
fd = bpf_prog_load_dev(prog->type, prog->insns, prog->size,
|
||||||
prog->license, ctx->log, ctx->log_size);
|
prog->license, ctx->ifindex,
|
||||||
|
ctx->log, ctx->log_size);
|
||||||
if (fd < 0 || ctx->verbose) {
|
if (fd < 0 || ctx->verbose) {
|
||||||
/* The verifier log is pretty chatty, sometimes so chatty
|
/* The verifier log is pretty chatty, sometimes so chatty
|
||||||
* on larger programs, that we could fail to dump everything
|
* 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,
|
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;
|
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);
|
bpf_get_cfg(ctx);
|
||||||
ctx->verbose = verbose;
|
ctx->verbose = verbose;
|
||||||
ctx->type = type;
|
ctx->type = type;
|
||||||
|
ctx->ifindex = ifindex;
|
||||||
|
|
||||||
ctx->obj_fd = open(pathname, O_RDONLY);
|
ctx->obj_fd = open(pathname, O_RDONLY);
|
||||||
if (ctx->obj_fd < 0)
|
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 struct bpf_elf_ctx __ctx;
|
||||||
|
|
||||||
static int bpf_obj_open(const char *pathname, enum bpf_prog_type type,
|
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;
|
struct bpf_elf_ctx *ctx = &__ctx;
|
||||||
int fd = 0, ret;
|
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) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Cannot initialize ELF context!\n");
|
fprintf(stderr, "Cannot initialize ELF context!\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
/*
|
/*
|
||||||
* libgenl.c GENL library
|
* libgenl.c GENL library
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
||||||
68
lib/utils.c
68
lib/utils.c
|
|
@ -38,6 +38,74 @@
|
||||||
int resolve_hosts;
|
int resolve_hosts;
|
||||||
int timestamp_short;
|
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)
|
int get_hex(char c)
|
||||||
{
|
{
|
||||||
if (c >= 'A' && c <= 'F')
|
if (c >= 'A' && c <= 'F')
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
INSTALL=install
|
INSTALL=install
|
||||||
INSTALLDIR=install -m 0755 -d
|
INSTALLDIR=install -m 0755 -d
|
||||||
INSTALLMAN=install -m 0644
|
INSTALLMAN=install -m 0644
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
MAN3PAGES = $(wildcard *.3)
|
MAN3PAGES = $(wildcard *.3)
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
MAN7PAGES = $(wildcard *.7)
|
MAN7PAGES = $(wildcard *.7)
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
TARGETS = ip-address.8 ip-link.8 ip-route.8
|
TARGETS = ip-address.8 ip-link.8 ip-route.8
|
||||||
|
|
||||||
MAN8PAGES = $(TARGETS) $(filter-out $(TARGETS),$(wildcard *.8))
|
MAN8PAGES = $(TARGETS) $(filter-out $(TARGETS),$(wildcard *.8))
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,8 @@ tc \- show / manipulate traffic control settings
|
||||||
\fB\-r\fR[\fIaw\fR] |
|
\fB\-r\fR[\fIaw\fR] |
|
||||||
\fB\-p\fR[\fIretty\fR] |
|
\fB\-p\fR[\fIretty\fR] |
|
||||||
\fB\-i\fR[\fIec\fR] |
|
\fB\-i\fR[\fIec\fR] |
|
||||||
\fB\-g\fR[\fIraph\fR] }
|
\fB\-g\fR[\fIraph\fR] |
|
||||||
|
\fB\-j\fR[\fIjson\fR] }
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B Tc
|
.B Tc
|
||||||
|
|
@ -443,7 +444,10 @@ see the man pages for individual qdiscs.
|
||||||
RATES
|
RATES
|
||||||
Bandwidths or rates.
|
Bandwidths or rates.
|
||||||
These parameters accept a floating point number, possibly followed by
|
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
|
.RS
|
||||||
.TP
|
.TP
|
||||||
bit or a bare number
|
bit or a bare number
|
||||||
|
|
@ -658,6 +662,10 @@ option was specified. Classes can be filtered only by
|
||||||
.BR "dev"
|
.BR "dev"
|
||||||
option.
|
option.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-j", " \-json"
|
||||||
|
Display results in JSON format.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR "\-nm" , " \-name"
|
.BR "\-nm" , " \-name"
|
||||||
resolve class name from
|
resolve class name from
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
SSOBJ=ss.o ssfilter.o
|
SSOBJ=ss.o ssfilter.o
|
||||||
LNSTATOBJ=lnstat.o lnstat_util.o
|
LNSTATOBJ=lnstat.o lnstat_util.o
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _LNSTAT_H
|
#ifndef _LNSTAT_H
|
||||||
#define _LNSTAT_H
|
#define _LNSTAT_H
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#define SSF_DCOND 0
|
#define SSF_DCOND 0
|
||||||
#define SSF_SCOND 1
|
#define SSF_SCOND 1
|
||||||
#define SSF_OR 2
|
#define SSF_OR 2
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
include ../config.mk
|
include ../config.mk
|
||||||
|
|
||||||
DISTGEN = maketable normal pareto paretonormal
|
DISTGEN = maketable normal pareto paretonormal
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
include ../config.mk
|
include ../config.mk
|
||||||
|
|
||||||
ifeq ($(HAVE_MNL),y)
|
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 \
|
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 \
|
tc_exec.o m_police.o m_estimator.o m_action.o m_ematch.o \
|
||||||
emp_ematch.yacc.o emp_ematch.lex.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 "emp_ematch.yacc.h"
|
||||||
#include "m_ematch.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;
|
unsigned int bpf_flags = 0;
|
||||||
struct bpf_cfg_in cfg = {};
|
struct bpf_cfg_in cfg = {};
|
||||||
bool seen_run = false;
|
bool seen_run = false;
|
||||||
|
bool skip_sw = false;
|
||||||
struct rtattr *tail;
|
struct rtattr *tail;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
|
@ -101,13 +102,20 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle,
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (matches(*argv, "run") == 0) {
|
if (matches(*argv, "run") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
||||||
|
if (seen_run)
|
||||||
|
duparg("run", *argv);
|
||||||
opt_bpf:
|
opt_bpf:
|
||||||
seen_run = true;
|
seen_run = true;
|
||||||
|
cfg.type = bpf_type;
|
||||||
cfg.argc = argc;
|
cfg.argc = argc;
|
||||||
cfg.argv = argv;
|
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;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
argc = cfg.argc;
|
argc = cfg.argc;
|
||||||
argv = cfg.argv;
|
argv = cfg.argv;
|
||||||
|
|
@ -131,6 +139,7 @@ opt_bpf:
|
||||||
bpf_gen_flags |= TCA_CLS_FLAGS_SKIP_HW;
|
bpf_gen_flags |= TCA_CLS_FLAGS_SKIP_HW;
|
||||||
} else if (matches(*argv, "skip_sw") == 0) {
|
} else if (matches(*argv, "skip_sw") == 0) {
|
||||||
bpf_gen_flags |= TCA_CLS_FLAGS_SKIP_SW;
|
bpf_gen_flags |= TCA_CLS_FLAGS_SKIP_SW;
|
||||||
|
skip_sw = true;
|
||||||
} else if (matches(*argv, "action") == 0) {
|
} else if (matches(*argv, "action") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (parse_action(&argc, &argv, TCA_BPF_ACT, n)) {
|
if (parse_action(&argc, &argv, TCA_BPF_ACT, n)) {
|
||||||
|
|
@ -160,6 +169,13 @@ opt_bpf:
|
||||||
NEXT_ARG_FWD();
|
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)
|
if (bpf_gen_flags)
|
||||||
addattr32(n, MAX_MSG, TCA_BPF_FLAGS_GEN, bpf_gen_flags);
|
addattr32(n, MAX_MSG, TCA_BPF_FLAGS_GEN, bpf_gen_flags);
|
||||||
if (bpf_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;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flower_print_eth_addr(FILE *f, char *name,
|
static void flower_print_eth_addr(char *name, struct rtattr *addr_attr,
|
||||||
struct rtattr *addr_attr,
|
|
||||||
struct rtattr *mask_attr)
|
struct rtattr *mask_attr)
|
||||||
{
|
{
|
||||||
|
SPRINT_BUF(namefrm);
|
||||||
|
SPRINT_BUF(out);
|
||||||
SPRINT_BUF(b1);
|
SPRINT_BUF(b1);
|
||||||
|
size_t done;
|
||||||
int bits;
|
int bits;
|
||||||
|
|
||||||
if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN)
|
if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN)
|
||||||
return;
|
return;
|
||||||
fprintf(f, "\n %s %s", name, ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN,
|
done = sprintf(out, "%s",
|
||||||
0, b1, sizeof(b1)));
|
ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN,
|
||||||
if (!mask_attr || RTA_PAYLOAD(mask_attr) != ETH_ALEN)
|
0, b1, sizeof(b1)));
|
||||||
return;
|
if (mask_attr && RTA_PAYLOAD(mask_attr) == ETH_ALEN) {
|
||||||
bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN);
|
bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN);
|
||||||
if (bits < 0)
|
if (bits < 0)
|
||||||
fprintf(f, "/%s", ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN,
|
sprintf(out + done, "/%s",
|
||||||
0, b1, sizeof(b1)));
|
ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN,
|
||||||
else if (bits < ETH_ALEN * 8)
|
0, b1, sizeof(b1)));
|
||||||
fprintf(f, "/%d", bits);
|
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)
|
struct rtattr *eth_type_attr)
|
||||||
{
|
{
|
||||||
|
SPRINT_BUF(out);
|
||||||
__be16 eth_type;
|
__be16 eth_type;
|
||||||
|
|
||||||
if (!eth_type_attr)
|
if (!eth_type_attr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
eth_type = rta_getattr_u16(eth_type_attr);
|
eth_type = rta_getattr_u16(eth_type_attr);
|
||||||
fprintf(f, "\n eth_type ");
|
|
||||||
if (eth_type == htons(ETH_P_IP))
|
if (eth_type == htons(ETH_P_IP))
|
||||||
fprintf(f, "ipv4");
|
sprintf(out, "ipv4");
|
||||||
else if (eth_type == htons(ETH_P_IPV6))
|
else if (eth_type == htons(ETH_P_IPV6))
|
||||||
fprintf(f, "ipv6");
|
sprintf(out, "ipv6");
|
||||||
else if (eth_type == htons(ETH_P_ARP))
|
else if (eth_type == htons(ETH_P_ARP))
|
||||||
fprintf(f, "arp");
|
sprintf(out, "arp");
|
||||||
else if (eth_type == htons(ETH_P_RARP))
|
else if (eth_type == htons(ETH_P_RARP))
|
||||||
fprintf(f, "rarp");
|
sprintf(out, "rarp");
|
||||||
else
|
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;
|
*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)
|
struct rtattr *ip_proto_attr)
|
||||||
{
|
{
|
||||||
|
SPRINT_BUF(out);
|
||||||
__u8 ip_proto;
|
__u8 ip_proto;
|
||||||
|
|
||||||
if (!ip_proto_attr)
|
if (!ip_proto_attr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ip_proto = rta_getattr_u8(ip_proto_attr);
|
ip_proto = rta_getattr_u8(ip_proto_attr);
|
||||||
fprintf(f, "\n ip_proto ");
|
|
||||||
if (ip_proto == IPPROTO_TCP)
|
if (ip_proto == IPPROTO_TCP)
|
||||||
fprintf(f, "tcp");
|
sprintf(out, "tcp");
|
||||||
else if (ip_proto == IPPROTO_UDP)
|
else if (ip_proto == IPPROTO_UDP)
|
||||||
fprintf(f, "udp");
|
sprintf(out, "udp");
|
||||||
else if (ip_proto == IPPROTO_SCTP)
|
else if (ip_proto == IPPROTO_SCTP)
|
||||||
fprintf(f, "sctp");
|
sprintf(out, "sctp");
|
||||||
else if (ip_proto == IPPROTO_ICMP)
|
else if (ip_proto == IPPROTO_ICMP)
|
||||||
fprintf(f, "icmp");
|
sprintf(out, "icmp");
|
||||||
else if (ip_proto == IPPROTO_ICMPV6)
|
else if (ip_proto == IPPROTO_ICMPV6)
|
||||||
fprintf(f, "icmpv6");
|
sprintf(out, "icmpv6");
|
||||||
else
|
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;
|
*p_ip_proto = ip_proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flower_print_ip_attr(FILE *f, char *name,
|
static void flower_print_ip_attr(char *name, struct rtattr *key_attr,
|
||||||
struct rtattr *key_attr,
|
|
||||||
struct rtattr *mask_attr)
|
struct rtattr *mask_attr)
|
||||||
{
|
{
|
||||||
|
SPRINT_BUF(namefrm);
|
||||||
|
SPRINT_BUF(out);
|
||||||
|
size_t done;
|
||||||
|
|
||||||
if (!key_attr)
|
if (!key_attr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(f, "\n %s %x", name, rta_getattr_u8(key_attr));
|
done = sprintf(out, "%x", rta_getattr_u8(key_attr));
|
||||||
if (!mask_attr)
|
if (mask_attr)
|
||||||
return;
|
sprintf(out + done, "/%x", rta_getattr_u8(mask_attr));
|
||||||
fprintf(f, "/%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,
|
enum flower_matching_flags type,
|
||||||
struct rtattr *attr,
|
struct rtattr *attr,
|
||||||
struct rtattr *mask_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)
|
if (type != flags_str[i].type)
|
||||||
continue;
|
continue;
|
||||||
if (mtf_mask & flags_str[i].flag) {
|
if (mtf_mask & flags_str[i].flag) {
|
||||||
if (++count == 1)
|
if (++count == 1) {
|
||||||
fprintf(f, "\n %s ", name);
|
print_string(PRINT_FP, NULL, "\n %s ", name);
|
||||||
else
|
open_json_object(name);
|
||||||
fprintf(f, "/");
|
} 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)
|
if (mtf & flags_str[i].flag)
|
||||||
fprintf(f, "%s", flags_str[i].string);
|
print_string(PRINT_FP, NULL, "%s",
|
||||||
|
flags_str[i].string);
|
||||||
else
|
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 *addr4_attr,
|
||||||
struct rtattr *mask4_attr,
|
struct rtattr *mask4_attr,
|
||||||
struct rtattr *addr6_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 *addr_attr;
|
||||||
struct rtattr *mask_attr;
|
struct rtattr *mask_attr;
|
||||||
|
SPRINT_BUF(namefrm);
|
||||||
|
SPRINT_BUF(out);
|
||||||
|
size_t done;
|
||||||
int family;
|
int family;
|
||||||
size_t len;
|
size_t len;
|
||||||
int bits;
|
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)
|
if (!addr_attr || RTA_PAYLOAD(addr_attr) != len)
|
||||||
return;
|
return;
|
||||||
fprintf(f, "\n %s %s", name, rt_addr_n2a_rta(family, addr_attr));
|
|
||||||
if (!mask_attr || RTA_PAYLOAD(mask_attr) != len)
|
if (!mask_attr || RTA_PAYLOAD(mask_attr) != len)
|
||||||
return;
|
return;
|
||||||
|
done = sprintf(out, "%s", rt_addr_n2a_rta(family, addr_attr));
|
||||||
bits = __mask_bits(RTA_DATA(mask_attr), len);
|
bits = __mask_bits(RTA_DATA(mask_attr), len);
|
||||||
if (bits < 0)
|
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)
|
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,
|
static void flower_print_ip4_addr(char *name, struct rtattr *addr_attr,
|
||||||
struct rtattr *addr_attr,
|
|
||||||
struct rtattr *mask_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);
|
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)
|
SPRINT_BUF(namefrm);
|
||||||
fprintf(f, "\n %s %d", name, rta_getattr_be16(attr));
|
|
||||||
|
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,
|
static void flower_print_tcp_flags(char *name, struct rtattr *flags_attr,
|
||||||
struct rtattr *flags_attr,
|
struct rtattr *mask_attr)
|
||||||
struct rtattr *mask_attr)
|
|
||||||
{
|
{
|
||||||
|
SPRINT_BUF(namefrm);
|
||||||
|
SPRINT_BUF(out);
|
||||||
|
size_t done;
|
||||||
|
|
||||||
if (!flags_attr)
|
if (!flags_attr)
|
||||||
return;
|
return;
|
||||||
fprintf(f, "\n %s %x", name, rta_getattr_be16(flags_attr));
|
|
||||||
if (!mask_attr)
|
done = sprintf(out, "%x", rta_getattr_be16(flags_attr));
|
||||||
return;
|
if (mask_attr)
|
||||||
fprintf(f, "/%x", rta_getattr_be16(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,
|
static void flower_print_key_id(const char *name, struct rtattr *attr)
|
||||||
struct rtattr *attr)
|
|
||||||
{
|
{
|
||||||
if (attr)
|
SPRINT_BUF(namefrm);
|
||||||
fprintf(f, "\n %s %d", name, rta_getattr_be32(attr));
|
|
||||||
|
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,
|
static void flower_print_masked_u8(const char *name, struct rtattr *attr,
|
||||||
struct rtattr *attr,
|
|
||||||
struct rtattr *mask_attr,
|
struct rtattr *mask_attr,
|
||||||
const char *(*value_to_str)(__u8 value))
|
const char *(*value_to_str)(__u8 value))
|
||||||
{
|
{
|
||||||
const char *value_str = NULL;
|
const char *value_str = NULL;
|
||||||
__u8 value, mask;
|
__u8 value, mask;
|
||||||
|
SPRINT_BUF(namefrm);
|
||||||
|
SPRINT_BUF(out);
|
||||||
|
size_t done;
|
||||||
|
|
||||||
if (!attr)
|
if (!attr)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1238,39 +1284,39 @@ static void flower_print_masked_u8(FILE *f, const char *name,
|
||||||
if (mask == UINT8_MAX && value_to_str)
|
if (mask == UINT8_MAX && value_to_str)
|
||||||
value_str = value_to_str(value);
|
value_str = value_to_str(value);
|
||||||
|
|
||||||
fprintf(f, "\n %s ", name);
|
|
||||||
|
|
||||||
if (value_str)
|
if (value_str)
|
||||||
fputs(value_str, f);
|
done = sprintf(out, "%s", value_str);
|
||||||
else
|
else
|
||||||
fprintf(f, "%d", value);
|
done = sprintf(out, "%d", value);
|
||||||
|
|
||||||
if (mask != UINT8_MAX)
|
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)
|
if (!attr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
value = rta_getattr_u32(attr);
|
sprintf(namefrm,"\n %s %%u", name);
|
||||||
|
print_uint(PRINT_ANY, name, namefrm, rta_getattr_u32(attr));
|
||||||
fprintf(f, "\n %s %d", name, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *op_attr,
|
||||||
struct rtattr *mask_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);
|
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);
|
parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt);
|
||||||
|
|
||||||
if (handle)
|
if (handle)
|
||||||
fprintf(f, "handle 0x%x ", handle);
|
print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle);
|
||||||
|
|
||||||
if (tb[TCA_FLOWER_CLASSID]) {
|
if (tb[TCA_FLOWER_CLASSID]) {
|
||||||
__u32 h = rta_getattr_u32(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 ||
|
if (TC_H_MIN(h) < TC_H_MIN_PRIORITY ||
|
||||||
TC_H_MIN(h) > (TC_H_MIN_PRIORITY + TC_QOPT_MAX_QUEUE - 1)) {
|
TC_H_MIN(h) > (TC_H_MIN_PRIORITY + TC_QOPT_MAX_QUEUE - 1)) {
|
||||||
SPRINT_BUF(b1);
|
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 {
|
} else {
|
||||||
fprintf(f, "hw_tc %u ",
|
print_uint(PRINT_ANY, "hw_tc", "hw_tc %u ",
|
||||||
TC_H_MIN(h) - TC_H_MIN_PRIORITY);
|
TC_H_MIN(h) - TC_H_MIN_PRIORITY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb[TCA_FLOWER_INDEV]) {
|
if (tb[TCA_FLOWER_INDEV]) {
|
||||||
struct rtattr *attr = 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]) {
|
if (tb[TCA_FLOWER_KEY_VLAN_ID]) {
|
||||||
struct rtattr *attr = 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]) {
|
if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) {
|
||||||
struct rtattr *attr = 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]);
|
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]);
|
tb[TCA_FLOWER_KEY_ETH_SRC_MASK]);
|
||||||
|
|
||||||
flower_print_eth_type(f, ð_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
|
flower_print_eth_type(ð_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
|
||||||
flower_print_ip_proto(f, &ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
|
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]);
|
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]);
|
tb[TCA_FLOWER_KEY_IP_TTL_MASK]);
|
||||||
|
|
||||||
flower_print_u32(f, "mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]);
|
flower_print_u32("mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]);
|
||||||
flower_print_u8(f, "mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
|
flower_print_u8("mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
|
||||||
flower_print_u8(f, "mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);
|
flower_print_u8("mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);
|
||||||
flower_print_u8(f, "mpls_ttl", tb[TCA_FLOWER_KEY_MPLS_TTL]);
|
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],
|
||||||
tb[TCA_FLOWER_KEY_IPV4_DST_MASK],
|
tb[TCA_FLOWER_KEY_IPV4_DST_MASK],
|
||||||
tb[TCA_FLOWER_KEY_IPV6_DST],
|
tb[TCA_FLOWER_KEY_IPV6_DST],
|
||||||
tb[TCA_FLOWER_KEY_IPV6_DST_MASK]);
|
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],
|
||||||
tb[TCA_FLOWER_KEY_IPV4_SRC_MASK],
|
tb[TCA_FLOWER_KEY_IPV4_SRC_MASK],
|
||||||
tb[TCA_FLOWER_KEY_IPV6_SRC],
|
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);
|
nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_DST);
|
||||||
if (nl_type >= 0)
|
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);
|
nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_SRC);
|
||||||
if (nl_type >= 0)
|
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]);
|
tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
|
||||||
|
|
||||||
nl_type = flower_icmp_attr_type(eth_type, ip_proto,
|
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,
|
nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
|
||||||
FLOWER_ICMP_FIELD_TYPE);
|
FLOWER_ICMP_FIELD_TYPE);
|
||||||
if (nl_type >= 0 && nl_mask_type >= 0)
|
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);
|
tb[nl_mask_type], NULL);
|
||||||
|
|
||||||
nl_type = flower_icmp_attr_type(eth_type, ip_proto,
|
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,
|
nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
|
||||||
FLOWER_ICMP_FIELD_CODE);
|
FLOWER_ICMP_FIELD_CODE);
|
||||||
if (nl_type >= 0 && nl_mask_type >= 0)
|
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);
|
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]);
|
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]);
|
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]);
|
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]);
|
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]);
|
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] ?
|
tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ?
|
||||||
htons(ETH_P_IP) : htons(ETH_P_IPV6),
|
htons(ETH_P_IP) : htons(ETH_P_IPV6),
|
||||||
tb[TCA_FLOWER_KEY_ENC_IPV4_DST],
|
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],
|
||||||
tb[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]);
|
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] ?
|
tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] ?
|
||||||
htons(ETH_P_IP) : htons(ETH_P_IPV6),
|
htons(ETH_P_IP) : htons(ETH_P_IPV6),
|
||||||
tb[TCA_FLOWER_KEY_ENC_IPV4_SRC],
|
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],
|
||||||
tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]);
|
tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]);
|
||||||
|
|
||||||
flower_print_key_id(f, "enc_key_id",
|
flower_print_key_id("enc_key_id", tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
|
||||||
tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
|
|
||||||
|
|
||||||
flower_print_port(f, "enc_dst_port",
|
flower_print_port("enc_dst_port", tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
|
||||||
tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
|
|
||||||
|
|
||||||
flower_print_matching_flags(f, "ip_flags",
|
flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS,
|
||||||
FLOWER_IP_FLAGS,
|
|
||||||
tb[TCA_FLOWER_KEY_FLAGS],
|
tb[TCA_FLOWER_KEY_FLAGS],
|
||||||
tb[TCA_FLOWER_KEY_FLAGS_MASK]);
|
tb[TCA_FLOWER_KEY_FLAGS_MASK]);
|
||||||
|
|
||||||
|
close_json_object();
|
||||||
|
|
||||||
if (tb[TCA_FLOWER_FLAGS]) {
|
if (tb[TCA_FLOWER_FLAGS]) {
|
||||||
__u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
|
__u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
|
||||||
|
|
||||||
if (flags & TCA_CLS_FLAGS_SKIP_HW)
|
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)
|
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)
|
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)
|
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])
|
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);
|
parse_rtattr_nested(tb, TCA_MATCHALL_MAX, opt);
|
||||||
|
|
||||||
if (handle)
|
if (handle)
|
||||||
fprintf(f, "handle 0x%x ", handle);
|
print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle);
|
||||||
|
|
||||||
if (tb[TCA_MATCHALL_CLASSID]) {
|
if (tb[TCA_MATCHALL_CLASSID]) {
|
||||||
SPRINT_BUF(b1);
|
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));
|
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]);
|
__u32 flags = rta_getattr_u32(tb[TCA_MATCHALL_FLAGS]);
|
||||||
|
|
||||||
if (flags & TCA_CLS_FLAGS_SKIP_HW)
|
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)
|
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)
|
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)
|
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])
|
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;
|
int family = strcmp(qu->id, "rsvp") == 0 ? AF_INET : AF_INET6;
|
||||||
struct tc_rsvp_pinfo pinfo = {};
|
struct tc_rsvp_pinfo pinfo = {};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
/*
|
/*
|
||||||
* f_tcindex.c Traffic control index filter
|
* f_tcindex.c Traffic control index filter
|
||||||
*
|
*
|
||||||
|
|
|
||||||
114
tc/m_action.c
114
tc/m_action.c
|
|
@ -11,10 +11,11 @@
|
||||||
* TODO:
|
* TODO:
|
||||||
* - parse to be passed a filedescriptor for logging purposes
|
* - parse to be passed a filedescriptor for logging purposes
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/socket.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
|
* with any action .so from the old days. But if someone really
|
||||||
* does that, they would know how to fix this ..
|
* does that, they would know how to fix this ..
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
fprintf(stderr, "usage: tc actions <ACTSPECOP>*\n");
|
fprintf(stderr, "usage: tc actions <ACTSPECOP>*\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Where: \tACTSPECOP := ACR | GD | FL\n"
|
"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;
|
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;
|
int argc = *argc_p;
|
||||||
char **argv = *argv_p;
|
char **argv = *argv_p;
|
||||||
|
|
||||||
if (argc) {
|
if (argc)
|
||||||
fprintf(stderr, "Unknown action \"%s\", hence option \"%s\" is unparsable\n", au->id, *argv);
|
fprintf(stderr,
|
||||||
} else {
|
"Unknown action \"%s\", hence option \"%s\" is unparsable\n",
|
||||||
|
au->id, *argv);
|
||||||
|
else
|
||||||
fprintf(stderr, "Unknown action \"%s\"\n", au->id);
|
fprintf(stderr, "Unknown action \"%s\"\n", au->id);
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,18 +139,14 @@ noexist:
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static bool
|
||||||
new_cmd(char **argv)
|
new_cmd(char **argv)
|
||||||
{
|
{
|
||||||
if ((matches(*argv, "change") == 0) ||
|
return (matches(*argv, "change") == 0) ||
|
||||||
(matches(*argv, "replace") == 0) ||
|
(matches(*argv, "replace") == 0) ||
|
||||||
(matches(*argv, "delete") == 0) ||
|
(matches(*argv, "delete") == 0) ||
|
||||||
(matches(*argv, "get") == 0) ||
|
(matches(*argv, "get") == 0) ||
|
||||||
(matches(*argv, "add") == 0))
|
(matches(*argv, "add") == 0);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
|
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;
|
int argc = *argc_p;
|
||||||
char **argv = *argv_p;
|
char **argv = *argv_p;
|
||||||
struct rtattr *tail, *tail2;
|
struct rtattr *tail, *tail2;
|
||||||
char k[16];
|
char k[FILTER_NAMESZ];
|
||||||
int act_ck_len = 0;
|
int act_ck_len = 0;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
int eap = 0; /* expect action parameters */
|
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++;
|
argv++;
|
||||||
eap = 1;
|
eap = 1;
|
||||||
#ifdef CONFIG_GACT
|
#ifdef CONFIG_GACT
|
||||||
if (!gact_ld) {
|
if (!gact_ld)
|
||||||
get_action_kind("gact");
|
get_action_kind("gact");
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
} else if (strcmp(*argv, "flowid") == 0) {
|
} else if (strcmp(*argv, "flowid") == 0) {
|
||||||
|
|
@ -207,9 +206,9 @@ done0:
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == NULL) {
|
if (a == NULL)
|
||||||
goto bad_val;
|
goto bad_val;
|
||||||
}
|
|
||||||
|
|
||||||
tail = NLMSG_TAIL(n);
|
tail = NLMSG_TAIL(n);
|
||||||
addattr_l(n, MAX_MSG, ++prio, NULL, 0);
|
addattr_l(n, MAX_MSG, ++prio, NULL, 0);
|
||||||
|
|
@ -268,7 +267,8 @@ done:
|
||||||
return 0;
|
return 0;
|
||||||
bad_val:
|
bad_val:
|
||||||
/* no need to undo things, returning from here should
|
/* 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);
|
fprintf(stderr, "parse_action: bad value (%d:%s)!\n", argc, *argv);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -301,18 +301,19 @@ static int tc_print_one_action(FILE *f, struct rtattr *arg)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (show_stats && tb[TCA_ACT_STATS]) {
|
if (show_stats && tb[TCA_ACT_STATS]) {
|
||||||
|
print_string(PRINT_FP, NULL, "\tAction statistics:\n", NULL);
|
||||||
fprintf(f, "\tAction statistics:\n");
|
open_json_object("stats");
|
||||||
print_tcstats2_attr(f, tb[TCA_ACT_STATS], "\t", NULL);
|
print_tcstats2_attr(f, tb[TCA_ACT_STATS], "\t", NULL);
|
||||||
if (tb[TCA_ACT_COOKIE]) {
|
close_json_object();
|
||||||
int strsz = RTA_PAYLOAD(tb[TCA_ACT_COOKIE]);
|
print_string(PRINT_FP, NULL, "\n", NULL);
|
||||||
char b1[strsz * 2 + 1];
|
}
|
||||||
|
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,
|
print_string(PRINT_ANY, "cookie", "\tcookie %s\n",
|
||||||
hexstring_n2a(RTA_DATA(tb[TCA_ACT_COOKIE]),
|
hexstring_n2a(RTA_DATA(tb[TCA_ACT_COOKIE]),
|
||||||
strsz, b1, sizeof(b1)));
|
strsz, b1, sizeof(b1)));
|
||||||
}
|
|
||||||
fprintf(f, "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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])
|
if (tab_flush && NULL != tb[0] && NULL == tb[1])
|
||||||
return tc_print_action_flush(f, tb[0]);
|
return tc_print_action_flush(f, tb[0]);
|
||||||
|
|
||||||
|
open_json_array(PRINT_JSON, "actions");
|
||||||
for (i = 0; i < tot_acts; i++) {
|
for (i = 0; i < tot_acts; i++) {
|
||||||
if (tb[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) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -429,9 +436,10 @@ int print_action(const struct sockaddr_nl *who,
|
||||||
return 0;
|
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;
|
struct action_util *a = NULL;
|
||||||
int argc = *argc_p;
|
int argc = *argc_p;
|
||||||
char **argv = *argv_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;
|
argc -= 1;
|
||||||
argv += 1;
|
argv += 1;
|
||||||
if (argc <= 0) {
|
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;
|
ret = -1;
|
||||||
goto bad_val;
|
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;
|
argc -= 1;
|
||||||
argv += 1;
|
argv += 1;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Error: no index specified action: %s\n", k);
|
fprintf(stderr,
|
||||||
|
"Error: no index specified action: %s\n", k);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto bad_val;
|
goto bad_val;
|
||||||
}
|
}
|
||||||
|
|
@ -536,7 +546,8 @@ bad_val:
|
||||||
return ret;
|
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;
|
int argc = *argc_p;
|
||||||
char **argv = *argv_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;
|
char **argv = *argv_p;
|
||||||
__u32 msec_since = 0;
|
__u32 msec_since = 0;
|
||||||
int argc = *argc_p;
|
int argc = *argc_p;
|
||||||
char k[16];
|
char k[FILTER_NAMESZ];
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr n;
|
struct nlmsghdr n;
|
||||||
struct tcamsg t;
|
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);
|
strncpy(k, *argv, sizeof(k) - 1);
|
||||||
#ifdef CONFIG_GACT
|
#ifdef CONFIG_GACT
|
||||||
if (!gact_ld) {
|
if (!gact_ld)
|
||||||
get_action_kind("gact");
|
get_action_kind("gact");
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
a = get_action_kind(k);
|
a = get_action_kind(k);
|
||||||
if (a == NULL) {
|
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);
|
addattr32(&req.n, MAX_MSG, TCA_ROOT_TIME_DELTA, msec_since);
|
||||||
tail4->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail4;
|
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 (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");
|
perror("Cannot send dump request");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -674,10 +687,14 @@ int do_action(int argc, char **argv)
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
|
|
||||||
if (matches(*argv, "add") == 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 ||
|
} else if (matches(*argv, "change") == 0 ||
|
||||||
matches(*argv, "replace") == 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) {
|
} else if (matches(*argv, "delete") == 0) {
|
||||||
argc -= 1;
|
argc -= 1;
|
||||||
argv += 1;
|
argv += 1;
|
||||||
|
|
@ -686,8 +703,9 @@ int do_action(int argc, char **argv)
|
||||||
argc -= 1;
|
argc -= 1;
|
||||||
argv += 1;
|
argv += 1;
|
||||||
ret = tc_action_gd(RTM_GETACTION, 0, &argc, &argv);
|
ret = tc_action_gd(RTM_GETACTION, 0, &argc, &argv);
|
||||||
} else if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
|
} else if (matches(*argv, "list") == 0 ||
|
||||||
|| matches(*argv, "lst") == 0) {
|
matches(*argv, "show") == 0 ||
|
||||||
|
matches(*argv, "lst") == 0) {
|
||||||
if (argc <= 2) {
|
if (argc <= 2) {
|
||||||
act_usage();
|
act_usage();
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -711,7 +729,9 @@ int do_action(int argc, char **argv)
|
||||||
act_usage();
|
act_usage();
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} 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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,12 +96,16 @@ static int bpf_parse_opt(struct action_util *a, int *ptr_argc, char ***ptr_argv,
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (matches(*argv, "run") == 0) {
|
if (matches(*argv, "run") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
||||||
|
if (seen_run)
|
||||||
|
duparg("run", *argv);
|
||||||
opt_bpf:
|
opt_bpf:
|
||||||
seen_run = true;
|
seen_run = true;
|
||||||
|
cfg.type = bpf_type;
|
||||||
cfg.argc = argc;
|
cfg.argc = argc;
|
||||||
cfg.argv = argv;
|
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;
|
return -1;
|
||||||
|
|
||||||
argc = cfg.argc;
|
argc = cfg.argc;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef __TC_EMATCH_H_
|
#ifndef __TC_EMATCH_H_
|
||||||
#define __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)
|
&pp.paction, false) == -1)
|
||||||
usage();
|
usage();
|
||||||
if (get_u16(&pp.pval, *argv, 10)) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
if (pp.pval > 10000) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
} else if (matches(*argv, "help") == 0) {
|
} else if (matches(*argv, "help") == 0) {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -140,7 +144,7 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
} else if (matches(*argv, "help") == 0) {
|
} 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_id, NULL, 0);
|
||||||
addattr_l(n, MAX_MSG, TCA_GACT_PARMS, &p, sizeof(p));
|
addattr_l(n, MAX_MSG, TCA_GACT_PARMS, &p, sizeof(p));
|
||||||
#ifdef CONFIG_GACT_PROB
|
#ifdef CONFIG_GACT_PROB
|
||||||
if (rd) {
|
if (rd)
|
||||||
addattr_l(n, MAX_MSG, TCA_GACT_PROB, &pp, sizeof(pp));
|
addattr_l(n, MAX_MSG, TCA_GACT_PROB, &pp, sizeof(pp));
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
|
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
|
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
|
#ifdef CONFIG_GACT_PROB
|
||||||
struct tc_gact_p *pp = NULL;
|
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);
|
parse_rtattr_nested(tb, TCA_GACT_MAX, arg);
|
||||||
|
|
||||||
if (tb[TCA_GACT_PARMS] == NULL) {
|
if (tb[TCA_GACT_PARMS] == NULL) {
|
||||||
fprintf(f, "[NULL gact parameters]");
|
print_string(PRINT_FP, NULL, "%s", "[NULL gact parameters]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p = RTA_DATA(tb[TCA_GACT_PARMS]);
|
p = RTA_DATA(tb[TCA_GACT_PARMS]);
|
||||||
|
|
||||||
fprintf(f, "gact ");
|
print_string(PRINT_ANY, "kind", "%s ", "gact");
|
||||||
print_action_control(f, "action ", p->action, "");
|
print_action_control(f, "action ", p->action, "");
|
||||||
#ifdef CONFIG_GACT_PROB
|
#ifdef CONFIG_GACT_PROB
|
||||||
if (tb[TCA_GACT_PROB] != NULL) {
|
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));
|
memset(&pp_dummy, 0, sizeof(pp_dummy));
|
||||||
pp = &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, " ");
|
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
|
#endif
|
||||||
fprintf(f, "\n\t index %u ref %d bind %d", p->index, p->refcnt,
|
print_uint(PRINT_ANY, "index", "\n\t index %u", p->index);
|
||||||
p->bindcnt);
|
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
|
||||||
|
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
|
||||||
if (show_stats) {
|
if (show_stats) {
|
||||||
if (tb[TCA_GACT_TM]) {
|
if (tb[TCA_GACT_TM]) {
|
||||||
struct tcf_t *tm = RTA_DATA(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);
|
print_tm(f, tm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(f, "\n ");
|
print_string(PRINT_FP, NULL, "%s", "\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ static int parse_ipt(struct action_util *a, int *argc_p,
|
||||||
int rargc = *argc_p;
|
int rargc = *argc_p;
|
||||||
char **argv = *argv_p;
|
char **argv = *argv_p;
|
||||||
int argc = 0, iargc = 0;
|
int argc = 0, iargc = 0;
|
||||||
char k[16];
|
char k[FILTER_NAMESZ];
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int iok = 0, ok = 0;
|
int iok = 0, ok = 0;
|
||||||
__u32 hook = 0, index = 0;
|
__u32 hook = 0, index = 0;
|
||||||
|
|
|
||||||
122
tc/m_mirred.c
122
tc/m_mirred.c
|
|
@ -28,13 +28,13 @@
|
||||||
static void
|
static void
|
||||||
explain(void)
|
explain(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>\n");
|
fprintf(stderr,
|
||||||
fprintf(stderr, "where:\n");
|
"Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>\n"
|
||||||
fprintf(stderr, "\tDIRECTION := <ingress | egress>\n");
|
"where:\n"
|
||||||
fprintf(stderr, "\tACTION := <mirror | redirect>\n");
|
"\tDIRECTION := <ingress | egress>\n"
|
||||||
fprintf(stderr, "\tINDEX is the specific policy instance id\n");
|
"\tACTION := <mirror | redirect>\n"
|
||||||
fprintf(stderr, "\tDEVICENAME is the devicename\n");
|
"\tINDEX is the specific policy instance id\n"
|
||||||
|
"\tDEVICENAME is the devicename\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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
|
static int
|
||||||
parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
|
parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
int tca_id, struct nlmsghdr *n)
|
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;
|
int ok = 0, iok = 0, mirror = 0, redir = 0, ingress = 0, egress = 0;
|
||||||
struct tc_mirred p = {};
|
struct tc_mirred p = {};
|
||||||
struct rtattr *tail;
|
struct rtattr *tail;
|
||||||
char d[16] = {};
|
char d[IFNAMSIZ] = {};
|
||||||
|
|
||||||
while (argc > 0) {
|
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) {
|
} else if (!egress && matches(*argv, "egress") == 0) {
|
||||||
egress = 1;
|
egress = 1;
|
||||||
if (ingress) {
|
if (ingress) {
|
||||||
fprintf(stderr, "Can't have both egress and ingress\n");
|
fprintf(stderr,
|
||||||
|
"Can't have both egress and ingress\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
NEXT_ARG();
|
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) {
|
} else if (!ingress && matches(*argv, "ingress") == 0) {
|
||||||
ingress = 1;
|
ingress = 1;
|
||||||
if (egress) {
|
if (egress) {
|
||||||
fprintf(stderr, "Can't have both ingress and egress\n");
|
fprintf(stderr,
|
||||||
|
"Can't have both ingress and egress\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
@ -109,30 +139,35 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (!ok) {
|
} else if (!ok) {
|
||||||
fprintf(stderr, "was expecting egress or ingress (%s)\n", *argv);
|
fprintf(stderr,
|
||||||
|
"was expecting egress or ingress (%s)\n",
|
||||||
|
*argv);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} else if (!mirror && matches(*argv, "mirror") == 0) {
|
} else if (!mirror && matches(*argv, "mirror") == 0) {
|
||||||
mirror = 1;
|
mirror = 1;
|
||||||
if (redir) {
|
if (redir) {
|
||||||
fprintf(stderr, "Can't have both mirror and redir\n");
|
fprintf(stderr,
|
||||||
|
"Can't have both mirror and redir\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p.eaction = egress ? TCA_EGRESS_MIRROR :
|
p.eaction = egress ? TCA_EGRESS_MIRROR :
|
||||||
TCA_INGRESS_MIRROR;
|
TCA_INGRESS_MIRROR;
|
||||||
p.action = TC_ACT_PIPE;
|
p.action = TC_ACT_PIPE;
|
||||||
ok++;
|
ok++;
|
||||||
} else if (!redir && matches(*argv, "redirect") == 0) {
|
} else if (!redir && matches(*argv, "redirect") == 0) {
|
||||||
redir = 1;
|
redir = 1;
|
||||||
if (mirror) {
|
if (mirror) {
|
||||||
fprintf(stderr, "Can't have both mirror and redir\n");
|
fprintf(stderr,
|
||||||
|
"Can't have both mirror and redir\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p.eaction = egress ? TCA_EGRESS_REDIR :
|
p.eaction = egress ? TCA_EGRESS_REDIR :
|
||||||
TCA_INGRESS_REDIR;
|
TCA_INGRESS_REDIR;
|
||||||
p.action = TC_ACT_STOLEN;
|
p.action = TC_ACT_STOLEN;
|
||||||
ok++;
|
ok++;
|
||||||
} else if ((redir || mirror) && matches(*argv, "dev") == 0) {
|
} else if ((redir || mirror) &&
|
||||||
|
matches(*argv, "dev") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (strlen(d))
|
if (strlen(d))
|
||||||
duparg("dev", *argv);
|
duparg("dev", *argv);
|
||||||
|
|
@ -149,18 +184,16 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok && !iok) {
|
if (!ok && !iok)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (d[0]) {
|
if (d[0]) {
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
ll_init_map(&rth);
|
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);
|
fprintf(stderr, "Cannot find device \"%s\"\n", d);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -176,16 +209,17 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
if (iok && matches(*argv, "index") == 0) {
|
if (iok && matches(*argv, "index") == 0) {
|
||||||
fprintf(stderr, "mirred: Illegal double index\n");
|
fprintf(stderr, "mirred: Illegal double index\n");
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
}
|
||||||
if (matches(*argv, "index") == 0) {
|
|
||||||
NEXT_ARG();
|
if (matches(*argv, "index") == 0) {
|
||||||
if (get_u32(&p.index, *argv, 10)) {
|
NEXT_ARG();
|
||||||
fprintf(stderr, "mirred: Illegal \"index\"\n");
|
if (get_u32(&p.index, *argv, 10)) {
|
||||||
return -1;
|
fprintf(stderr,
|
||||||
}
|
"mirred: Illegal \"index\"\n");
|
||||||
argc--;
|
return -1;
|
||||||
argv++;
|
|
||||||
}
|
}
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +276,7 @@ parse_mirred(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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 tc_mirred *p;
|
||||||
struct rtattr *tb[TCA_MIRRED_MAX + 1];
|
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);
|
parse_rtattr_nested(tb, TCA_MIRRED_MAX, arg);
|
||||||
|
|
||||||
if (tb[TCA_MIRRED_PARMS] == NULL) {
|
if (tb[TCA_MIRRED_PARMS] == NULL) {
|
||||||
fprintf(f, "[NULL mirred parameters]");
|
print_string(PRINT_FP, NULL, "%s", "[NULL mirred parameters]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p = RTA_DATA(tb[TCA_MIRRED_PARMS]);
|
p = RTA_DATA(tb[TCA_MIRRED_PARMS]);
|
||||||
|
|
||||||
/*
|
dev = ll_index_to_name(p->ifindex);
|
||||||
ll_init_map(&rth);
|
if (dev == 0) {
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
if ((dev = ll_index_to_name(p->ifindex)) == 0) {
|
|
||||||
fprintf(stderr, "Cannot find device %d\n", p->ifindex);
|
fprintf(stderr, "Cannot find device %d\n", p->ifindex);
|
||||||
return -1;
|
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, "");
|
print_action_control(f, " ", p->action, "");
|
||||||
|
|
||||||
fprintf(f, "\n ");
|
print_uint(PRINT_ANY, "index", "\n \tindex %u", p->index);
|
||||||
fprintf(f, "\tindex %u ref %d bind %d", p->index, p->refcnt,
|
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
|
||||||
p->bindcnt);
|
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
|
||||||
|
|
||||||
if (show_stats) {
|
if (show_stats) {
|
||||||
if (tb[TCA_MIRRED_TM]) {
|
if (tb[TCA_MIRRED_TM]) {
|
||||||
|
|
@ -283,7 +319,7 @@ print_mirred(struct action_util *au, FILE * f, struct rtattr *arg)
|
||||||
print_tm(f, tm);
|
print_tm(f, tm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(f, "\n ");
|
print_string(PRINT_FP, NULL, "%s", "\n ");
|
||||||
return 0;
|
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);
|
res = parse_offset(&argc, &argv, sel, &tkey);
|
||||||
goto done;
|
goto done;
|
||||||
} else {
|
} else {
|
||||||
char k[16];
|
char k[FILTER_NAMESZ];
|
||||||
struct m_pedit_util *p = NULL;
|
struct m_pedit_util *p = NULL;
|
||||||
|
|
||||||
strncpy(k, *argv, sizeof(k) - 1);
|
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)
|
static void explain(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: vlan pop\n");
|
fprintf(stderr,
|
||||||
fprintf(stderr, " vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n");
|
"Usage: vlan pop\n"
|
||||||
fprintf(stderr, " vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n");
|
" vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
|
||||||
fprintf(stderr, " VLANPROTO is one of 802.1Q or 802.1AD\n");
|
" vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
|
||||||
fprintf(stderr, " with default: 802.1Q\n");
|
" VLANPROTO is one of 802.1Q or 802.1AD\n"
|
||||||
fprintf(stderr, " CONTROL := reclassify | pipe | drop | continue | pass |\n");
|
" with default: 802.1Q\n"
|
||||||
fprintf(stderr, " goto chain <CHAIN_INDEX>\n");
|
" CONTROL := reclassify | pipe | drop | continue | pass |\n"
|
||||||
|
" goto chain <CHAIN_INDEX>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(void)
|
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;
|
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,
|
static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
int tca_id, struct nlmsghdr *n)
|
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) {
|
while (argc > 0) {
|
||||||
if (matches(*argv, "pop") == 0) {
|
if (matches(*argv, "pop") == 0) {
|
||||||
if (action) {
|
if (action) {
|
||||||
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
|
unexpected(*argv);
|
||||||
*argv);
|
|
||||||
explain();
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
action = TCA_VLAN_ACT_POP;
|
action = TCA_VLAN_ACT_POP;
|
||||||
} else if (matches(*argv, "push") == 0) {
|
} else if (matches(*argv, "push") == 0) {
|
||||||
if (action) {
|
if (action) {
|
||||||
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
|
unexpected(*argv);
|
||||||
*argv);
|
|
||||||
explain();
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
action = TCA_VLAN_ACT_PUSH;
|
action = TCA_VLAN_ACT_PUSH;
|
||||||
} else if (matches(*argv, "modify") == 0) {
|
} else if (matches(*argv, "modify") == 0) {
|
||||||
if (action) {
|
if (action) {
|
||||||
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
|
unexpected(*argv);
|
||||||
*argv);
|
|
||||||
explain();
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
action = TCA_VLAN_ACT_MODIFY;
|
action = TCA_VLAN_ACT_MODIFY;
|
||||||
} else if (matches(*argv, "id") == 0) {
|
} else if (matches(*argv, "id") == 0) {
|
||||||
if (!has_push_attribs(action)) {
|
if (!has_push_attribs(action))
|
||||||
fprintf(stderr, "\"%s\" is only valid for push/modify\n",
|
invarg("only valid for push/modify", *argv);
|
||||||
*argv);
|
|
||||||
explain();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (get_u16(&id, *argv, 0))
|
if (get_u16(&id, *argv, 0))
|
||||||
invarg("id is invalid", *argv);
|
invarg("id is invalid", *argv);
|
||||||
id_set = 1;
|
id_set = 1;
|
||||||
} else if (matches(*argv, "protocol") == 0) {
|
} else if (matches(*argv, "protocol") == 0) {
|
||||||
if (!has_push_attribs(action)) {
|
if (!has_push_attribs(action))
|
||||||
fprintf(stderr, "\"%s\" is only valid for push/modify\n",
|
invarg("only valid for push/modify", *argv);
|
||||||
*argv);
|
|
||||||
explain();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (ll_proto_a2n(&proto, *argv))
|
if (ll_proto_a2n(&proto, *argv))
|
||||||
invarg("protocol is invalid", *argv);
|
invarg("protocol is invalid", *argv);
|
||||||
proto_set = 1;
|
proto_set = 1;
|
||||||
} else if (matches(*argv, "priority") == 0) {
|
} else if (matches(*argv, "priority") == 0) {
|
||||||
if (!has_push_attribs(action)) {
|
if (!has_push_attribs(action))
|
||||||
fprintf(stderr, "\"%s\" is only valid for push/modify\n",
|
invarg("only valid for push/modify", *argv);
|
||||||
*argv);
|
|
||||||
explain();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (get_u8(&prio, *argv, 0) || (prio & ~0x7))
|
if (get_u8(&prio, *argv, 0) || (prio & ~0x7))
|
||||||
invarg("prio is invalid", *argv);
|
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);
|
parse_rtattr_nested(tb, TCA_VLAN_MAX, arg);
|
||||||
|
|
||||||
if (!tb[TCA_VLAN_PARMS]) {
|
if (!tb[TCA_VLAN_PARMS]) {
|
||||||
fprintf(f, "[NULL vlan parameters]");
|
print_string(PRINT_FP, NULL, "%s", "[NULL vlan parameters]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
parm = RTA_DATA(tb[TCA_VLAN_PARMS]);
|
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) {
|
switch (parm->v_action) {
|
||||||
case TCA_VLAN_ACT_POP:
|
|
||||||
fprintf(f, " pop");
|
|
||||||
break;
|
|
||||||
case TCA_VLAN_ACT_PUSH:
|
case TCA_VLAN_ACT_PUSH:
|
||||||
case TCA_VLAN_ACT_MODIFY:
|
case TCA_VLAN_ACT_MODIFY:
|
||||||
fprintf(f, " %s", action_names[parm->v_action]);
|
|
||||||
if (tb[TCA_VLAN_PUSH_VLAN_ID]) {
|
if (tb[TCA_VLAN_PUSH_VLAN_ID]) {
|
||||||
val = rta_getattr_u16(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]) {
|
if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
|
||||||
fprintf(f, " protocol %s",
|
__u16 proto;
|
||||||
ll_proto_n2a(rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]),
|
|
||||||
b1, sizeof(b1)));
|
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]) {
|
if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) {
|
||||||
val = rta_getattr_u8(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;
|
break;
|
||||||
}
|
}
|
||||||
print_action_control(f, " ", parm->action, "");
|
print_action_control(f, " ", parm->action, "");
|
||||||
|
|
||||||
fprintf(f, "\n\t index %u ref %d bind %d", parm->index, parm->refcnt,
|
print_uint(PRINT_ANY, "index", "\n\t index %u", parm->index);
|
||||||
parm->bindcnt);
|
print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
|
||||||
|
print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
|
||||||
|
|
||||||
if (show_stats) {
|
if (show_stats) {
|
||||||
if (tb[TCA_VLAN_TM]) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ static int parse_ipt(struct action_util *a, int *argc_p,
|
||||||
int c;
|
int c;
|
||||||
char **argv = *argv_p;
|
char **argv = *argv_p;
|
||||||
int argc;
|
int argc;
|
||||||
char k[16];
|
char k[FILTER_NAMESZ];
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int iok = 0, ok = 0;
|
int iok = 0, ok = 0;
|
||||||
__u32 hook = 0, index = 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