Merge branch 'master' of git://git.kernel.org/pub/scm/network/iproute2/iproute2-next

Resolved conflict in tc/f_flower.c
This commit is contained in:
Stephen Hemminger 2020-01-29 05:44:53 -08:00
commit d80d22d5fd
45 changed files with 873 additions and 56 deletions

View File

@ -173,7 +173,8 @@ int rta_nest_end(struct rtattr *rta, struct rtattr *nest);
RTA_ALIGN((rta)->rta_len)))
#define parse_rtattr_nested(tb, max, rta) \
(parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
(parse_rtattr_flags((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta), \
NLA_F_NESTED))
#define parse_rtattr_one_nested(type, rta) \
(parse_rtattr_one(type, RTA_DATA(rta), RTA_PAYLOAD(rta)))

View File

@ -231,6 +231,11 @@ enum bpf_attach_type {
* When children program makes decision (like picking TCP CA or sock bind)
* parent program has a chance to override it.
*
* With BPF_F_ALLOW_MULTI a new program is added to the end of the list of
* programs for a cgroup. Though it's possible to replace an old program at
* any position by also specifying BPF_F_REPLACE flag and position itself in
* replace_bpf_fd attribute. Old program at this position will be released.
*
* A cgroup with MULTI or OVERRIDE flag allows any attach flags in sub-cgroups.
* A cgroup with NONE doesn't allow any programs in sub-cgroups.
* Ex1:
@ -249,6 +254,7 @@ enum bpf_attach_type {
*/
#define BPF_F_ALLOW_OVERRIDE (1U << 0)
#define BPF_F_ALLOW_MULTI (1U << 1)
#define BPF_F_REPLACE (1U << 2)
/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
* verifier will perform strict alignment checking as if the kernel
@ -442,6 +448,10 @@ union bpf_attr {
__u32 attach_bpf_fd; /* eBPF program to attach */
__u32 attach_type;
__u32 attach_flags;
__u32 replace_bpf_fd; /* previously attached eBPF
* program to replace if
* BPF_F_REPLACE is used
*/
};
struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */

View File

@ -142,7 +142,8 @@ struct btf_param {
enum {
BTF_VAR_STATIC = 0,
BTF_VAR_GLOBAL_ALLOCATED,
BTF_VAR_GLOBAL_ALLOCATED = 1,
BTF_VAR_GLOBAL_EXTERN = 2,
};
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe

View File

@ -79,6 +79,15 @@ typedef struct {
unsigned int timeout;
} cisco_proto;
typedef struct {
unsigned short dce; /* 1 for DCE (network side) operation */
unsigned int modulo; /* modulo (8 = basic / 128 = extended) */
unsigned int window; /* frame window size */
unsigned int t1; /* timeout t1 */
unsigned int t2; /* timeout t2 */
unsigned int n2; /* frame retry counter */
} x25_hdlc_proto;
/* PPP doesn't need any info now - supply length = 0 to ioctl */
#endif /* __ASSEMBLY__ */

View File

@ -211,6 +211,7 @@ struct if_settings {
fr_proto *fr;
fr_proto_pvc *fr_pvc;
fr_proto_pvc_info *fr_pvc_info;
x25_hdlc_proto *x25;
/* interface settings */
sync_serial_settings *sync;

View File

@ -95,6 +95,16 @@
#define BOND_XMIT_POLICY_ENCAP23 3 /* encapsulated layer 2+3 */
#define BOND_XMIT_POLICY_ENCAP34 4 /* encapsulated layer 3+4 */
/* 802.3ad port state definitions (43.4.2.2 in the 802.3ad standard) */
#define LACP_STATE_LACP_ACTIVITY 0x1
#define LACP_STATE_LACP_TIMEOUT 0x2
#define LACP_STATE_AGGREGATION 0x4
#define LACP_STATE_SYNCHRONIZATION 0x8
#define LACP_STATE_COLLECTING 0x10
#define LACP_STATE_DISTRIBUTING 0x20
#define LACP_STATE_DEFAULTED 0x40
#define LACP_STATE_EXPIRED 0x80
typedef struct ifbond {
__s32 bond_mode;
__s32 num_slaves;

View File

@ -156,6 +156,44 @@ struct bridge_vlan_xstats {
__u32 pad2;
};
struct bridge_stp_xstats {
__u64 transition_blk;
__u64 transition_fwd;
__u64 rx_bpdu;
__u64 tx_bpdu;
__u64 rx_tcn;
__u64 tx_tcn;
};
/* Bridge vlan RTM header */
struct br_vlan_msg {
__u8 family;
__u8 reserved1;
__u16 reserved2;
__u32 ifindex;
};
/* Bridge vlan RTM attributes
* [BRIDGE_VLANDB_ENTRY] = {
* [BRIDGE_VLANDB_ENTRY_INFO]
* ...
* }
*/
enum {
BRIDGE_VLANDB_UNSPEC,
BRIDGE_VLANDB_ENTRY,
__BRIDGE_VLANDB_MAX,
};
#define BRIDGE_VLANDB_MAX (__BRIDGE_VLANDB_MAX - 1)
enum {
BRIDGE_VLANDB_ENTRY_UNSPEC,
BRIDGE_VLANDB_ENTRY_INFO,
BRIDGE_VLANDB_ENTRY_RANGE,
__BRIDGE_VLANDB_ENTRY_MAX,
};
#define BRIDGE_VLANDB_ENTRY_MAX (__BRIDGE_VLANDB_ENTRY_MAX - 1)
/* Bridge multicast database attributes
* [MDBA_MDB] = {
* [MDBA_MDB_ENTRY] = {
@ -262,6 +300,7 @@ enum {
BRIDGE_XSTATS_VLAN,
BRIDGE_XSTATS_MCAST,
BRIDGE_XSTATS_PAD,
BRIDGE_XSTATS_STP,
__BRIDGE_XSTATS_MAX
};
#define BRIDGE_XSTATS_MAX (__BRIDGE_XSTATS_MAX - 1)

View File

@ -169,6 +169,7 @@ enum {
IFLA_MAX_MTU,
IFLA_PROP_LIST,
IFLA_ALT_IFNAME, /* Alternative ifname */
IFLA_PERM_ADDRESS,
__IFLA_MAX
};
@ -483,6 +484,13 @@ enum macsec_validation_type {
MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1,
};
enum macsec_offload {
MACSEC_OFFLOAD_OFF = 0,
MACSEC_OFFLOAD_PHY = 1,
__MACSEC_OFFLOAD_END,
MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
};
/* IPVLAN section */
enum {
IFLA_IPVLAN_UNSPEC,

View File

@ -45,6 +45,7 @@ enum macsec_attrs {
MACSEC_ATTR_RXSC_LIST, /* dump, nested, macsec_rxsc_attrs for each RXSC */
MACSEC_ATTR_TXSC_STATS, /* dump, nested, macsec_txsc_stats_attr */
MACSEC_ATTR_SECY_STATS, /* dump, nested, macsec_secy_stats_attr */
MACSEC_ATTR_OFFLOAD, /* config, nested, macsec_offload_attrs */
__MACSEC_ATTR_END,
NUM_MACSEC_ATTR = __MACSEC_ATTR_END,
MACSEC_ATTR_MAX = __MACSEC_ATTR_END - 1,
@ -97,6 +98,15 @@ enum macsec_sa_attrs {
MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1,
};
enum macsec_offload_attrs {
MACSEC_OFFLOAD_ATTR_UNSPEC,
MACSEC_OFFLOAD_ATTR_TYPE, /* config/dump, u8 0..2 */
MACSEC_OFFLOAD_ATTR_PAD,
__MACSEC_OFFLOAD_ATTR_END,
NUM_MACSEC_OFFLOAD_ATTR = __MACSEC_OFFLOAD_ATTR_END,
MACSEC_OFFLOAD_ATTR_MAX = __MACSEC_OFFLOAD_ATTR_END - 1,
};
enum macsec_nl_commands {
MACSEC_CMD_GET_TXSC,
MACSEC_CMD_ADD_RXSC,
@ -108,6 +118,7 @@ enum macsec_nl_commands {
MACSEC_CMD_ADD_RXSA,
MACSEC_CMD_DEL_RXSA,
MACSEC_CMD_UPD_RXSA,
MACSEC_CMD_UPD_OFFLOAD,
};
/* u64 per-RXSC stats */

View File

@ -76,6 +76,8 @@ enum {
#define IPPROTO_MPLS IPPROTO_MPLS
IPPROTO_RAW = 255, /* Raw IP packets */
#define IPPROTO_RAW IPPROTO_RAW
IPPROTO_MPTCP = 262, /* Multipath TCP connection */
#define IPPROTO_MPTCP IPPROTO_MPTCP
IPPROTO_MAX
};
#endif

View File

@ -1187,4 +1187,21 @@ enum {
#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
/* ETS */
#define TCQ_ETS_MAX_BANDS 16
enum {
TCA_ETS_UNSPEC,
TCA_ETS_NBANDS, /* u8 */
TCA_ETS_NSTRICT, /* u8 */
TCA_ETS_QUANTA, /* nested TCA_ETS_QUANTA_BAND */
TCA_ETS_QUANTA_BAND, /* u32 */
TCA_ETS_PRIOMAP, /* nested TCA_ETS_PRIOMAP_BAND */
TCA_ETS_PRIOMAP_BAND, /* u8 */
__TCA_ETS_MAX,
};
#define TCA_ETS_MAX (__TCA_ETS_MAX - 1)
#endif

View File

@ -171,6 +171,13 @@ enum {
RTM_GETLINKPROP,
#define RTM_GETLINKPROP RTM_GETLINKPROP
RTM_NEWVLAN = 112,
#define RTM_NEWNVLAN RTM_NEWVLAN
RTM_DELVLAN,
#define RTM_DELVLAN RTM_DELVLAN
RTM_GETVLAN,
#define RTM_GETVLAN RTM_GETVLAN
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@ -309,6 +316,8 @@ enum rt_scope_t {
#define RTM_F_PREFIX 0x800 /* Prefix addresses */
#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */
#define RTM_F_FIB_MATCH 0x2000 /* return full fib lookup match */
#define RTM_F_OFFLOAD 0x4000 /* route is offloaded */
#define RTM_F_TRAP 0x8000 /* route is trapping packets */
/* Reserved table identifiers */
@ -719,6 +728,8 @@ enum rtnetlink_groups {
#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
RTNLGRP_NEXTHOP,
#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP
RTNLGRP_BRVLAN,
#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)

View File

@ -317,14 +317,15 @@ enum {
#define TCP_MD5SIG_MAXKEYLEN 80
/* tcp_md5sig extension flags for TCP_MD5SIG_EXT */
#define TCP_MD5SIG_FLAG_PREFIX 1 /* address prefix length */
#define TCP_MD5SIG_FLAG_PREFIX 0x1 /* address prefix length */
#define TCP_MD5SIG_FLAG_IFINDEX 0x2 /* ifindex set */
struct tcp_md5sig {
struct __kernel_sockaddr_storage tcpm_addr; /* address associated */
__u8 tcpm_flags; /* extension flags */
__u8 tcpm_prefixlen; /* address prefix */
__u16 tcpm_keylen; /* key length */
__u32 __tcpm_pad; /* zero */
int tcpm_ifindex; /* device index for scope */
__u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
};

View File

@ -65,6 +65,7 @@ enum {
TIPC_NL_UDP_GET_REMOTEIP,
TIPC_NL_KEY_SET,
TIPC_NL_KEY_FLUSH,
TIPC_NL_ADDR_LEGACY_GET,
__TIPC_NL_CMD_MAX,
TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@ -176,6 +177,7 @@ enum {
TIPC_NLA_NET_ADDR, /* u32 */
TIPC_NLA_NET_NODEID, /* u64 */
TIPC_NLA_NET_NODEID_W1, /* u64 */
TIPC_NLA_NET_ADDR_LEGACY, /* flag */
__TIPC_NLA_NET_MAX,
TIPC_NLA_NET_MAX = __TIPC_NLA_NET_MAX - 1

47
include/uapi/linux/udp.h Normal file
View File

@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the UDP protocol.
*
* Version: @(#)udp.h 1.0.2 04/28/93
*
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _LINUX_UDP_H
#define _LINUX_UDP_H
#include <linux/types.h>
struct udphdr {
__be16 source;
__be16 dest;
__be16 len;
__sum16 check;
};
/* UDP socket options */
#define UDP_CORK 1 /* Never send partially complete segments */
#define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */
#define UDP_NO_CHECK6_TX 101 /* Disable sending checksum for UDP6X */
#define UDP_NO_CHECK6_RX 102 /* Disable accpeting checksum for UDP6 */
#define UDP_SEGMENT 103 /* Set GSO segmentation size */
#define UDP_GRO 104 /* This socket can receive UDP GRO packets */
/* UDP encapsulation types */
#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */
#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
#define UDP_ENCAP_GTP0 4 /* GSM TS 09.60 */
#define UDP_ENCAP_GTP1U 5 /* 3GPP TS 29.060 */
#define UDP_ENCAP_RXRPC 6
#define TCP_ENCAP_ESPINTCP 7 /* Yikes, this is really xfrm encap types. */
#endif /* _LINUX_UDP_H */

View File

@ -1011,6 +1011,24 @@ int print_linkinfo(struct nlmsghdr *n, void *arg)
ifi->ifi_type,
b1, sizeof(b1)));
}
if (tb[IFLA_PERM_ADDRESS]) {
unsigned int len = RTA_PAYLOAD(tb[IFLA_PERM_ADDRESS]);
if (!tb[IFLA_ADDRESS] ||
RTA_PAYLOAD(tb[IFLA_ADDRESS]) != len ||
memcmp(RTA_DATA(tb[IFLA_PERM_ADDRESS]),
RTA_DATA(tb[IFLA_ADDRESS]), len)) {
print_string(PRINT_FP, NULL, " permaddr ", NULL);
print_color_string(PRINT_ANY,
COLOR_MAC,
"permaddr",
"%s",
ll_addr_n2a(RTA_DATA(tb[IFLA_PERM_ADDRESS]),
RTA_PAYLOAD(tb[IFLA_PERM_ADDRESS]),
ifi->ifi_type,
b1, sizeof(b1)));
}
}
}
if (tb[IFLA_LINK_NETNSID]) {

View File

@ -68,6 +68,26 @@ static void print_slave_mii_status(FILE *f, struct rtattr *tb)
slave_mii_status[status]);
}
static void print_slave_oper_state(FILE *fp, const char *name, __u16 state)
{
open_json_array(PRINT_ANY, name);
print_string(PRINT_FP, NULL, " <", NULL);
#define _PF(s, str) if (state & LACP_STATE_##s) { \
state &= ~LACP_STATE_##s; \
print_string(PRINT_ANY, NULL, \
state ? "%s," : "%s", str); }
_PF(LACP_ACTIVITY, "active");
_PF(LACP_TIMEOUT, "short_timeout");
_PF(AGGREGATION, "aggregating");
_PF(SYNCHRONIZATION, "in_sync");
_PF(COLLECTING, "collecting");
_PF(DISTRIBUTING, "distributing");
_PF(DEFAULTED, "defaulted");
_PF(EXPIRED, "expired");
#undef _PF
close_json_array(PRINT_ANY, "> ");
}
static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
SPRINT_BUF(b1);
@ -106,17 +126,25 @@ static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *t
"ad_aggregator_id %d ",
rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]));
if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE])
if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]) {
__u8 state = rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]);
print_int(PRINT_ANY,
"ad_actor_oper_port_state",
"ad_actor_oper_port_state %d ",
rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]));
state);
print_slave_oper_state(f, "ad_actor_oper_port_state_str", state);
}
if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]) {
__u16 state = rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]);
if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE])
print_int(PRINT_ANY,
"ad_partner_oper_port_state",
"ad_partner_oper_port_state %d ",
rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]));
state);
print_slave_oper_state(f, "ad_partner_oper_port_state_str", state);
}
}
static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv,

View File

@ -688,6 +688,7 @@ static void bridge_print_xstats_help(struct link_util *lu, FILE *f)
static void bridge_print_stats_attr(struct rtattr *attr, int ifindex)
{
struct rtattr *brtb[LINK_XSTATS_TYPE_MAX+1];
struct bridge_stp_xstats *sstats;
struct br_mcast_stats *mstats;
struct rtattr *i, *list;
const char *ifname = "";
@ -807,6 +808,29 @@ static void bridge_print_stats_attr(struct rtattr *attr, int ifindex)
mstats->mld_parse_errors);
close_json_object();
break;
case BRIDGE_XSTATS_STP:
sstats = RTA_DATA(i);
open_json_object("stp");
print_string(PRINT_FP, NULL,
"%-16s STP BPDU: ", "");
print_u64(PRINT_ANY, "rx_bpdu", "RX: %llu ",
sstats->rx_bpdu);
print_u64(PRINT_ANY, "tx_bpdu", "TX: %llu\n",
sstats->tx_bpdu);
print_string(PRINT_FP, NULL,
"%-16s STP TCN: ", "");
print_u64(PRINT_ANY, "rx_tcn", "RX: %llu ",
sstats->rx_tcn);
print_u64(PRINT_ANY, "tx_tcn", "TX: %llu\n",
sstats->tx_tcn);
print_string(PRINT_FP, NULL,
"%-16s STP Transitions: ", "");
print_u64(PRINT_ANY, "transition_blk", "Blocked: %llu ",
sstats->transition_blk);
print_u64(PRINT_ANY, "transition_fwd", "Forwarding: %llu\n",
sstats->transition_fwd);
close_json_object();
break;
}
}
close_json_object();
@ -843,6 +867,8 @@ int bridge_parse_xstats(struct link_util *lu, int argc, char **argv)
while (argc > 0) {
if (strcmp(*argv, "igmp") == 0 || strcmp(*argv, "mcast") == 0) {
xstats_print_attr = BRIDGE_XSTATS_MCAST;
} else if (strcmp(*argv, "stp") == 0) {
xstats_print_attr = BRIDGE_XSTATS_STP;
} else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
filter_index = ll_name_to_index(*argv);

View File

@ -368,6 +368,10 @@ void print_rt_flags(FILE *fp, unsigned int flags)
print_string(PRINT_ANY, NULL, "%s ", "linkdown");
if (flags & RTNH_F_UNRESOLVED)
print_string(PRINT_ANY, NULL, "%s ", "unresolved");
if (flags & RTM_F_OFFLOAD)
print_string(PRINT_ANY, NULL, "%s ", "rt_offload");
if (flags & RTM_F_TRAP)
print_string(PRINT_ANY, NULL, "%s ", "rt_trap");
close_json_array(PRINT_JSON, NULL);
}

View File

@ -229,6 +229,8 @@ static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
struct rtattr *tb[SEG6_LOCAL_MAX + 1];
int action;
SPRINT_BUF(b1);
parse_rtattr_nested(tb, SEG6_LOCAL_MAX, encap);
if (!tb[SEG6_LOCAL_ACTION])
@ -246,8 +248,9 @@ static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
}
if (tb[SEG6_LOCAL_TABLE])
print_uint(PRINT_ANY, "table",
"table %u ", rta_getattr_u32(tb[SEG6_LOCAL_TABLE]));
print_string(PRINT_ANY, "table", "table %s ",
rtnl_rttable_n2a(rta_getattr_u32(tb[SEG6_LOCAL_TABLE]),
b1, sizeof(b1)));
if (tb[SEG6_LOCAL_NH4]) {
print_string(PRINT_ANY, "nh4",
@ -654,7 +657,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
NEXT_ARG();
if (table_ok++)
duparg2("table", *argv);
get_u32(&table, *argv, 0);
rtnl_rttable_a2n(&table, *argv);
ret = rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table);
} else if (strcmp(*argv, "nh4") == 0) {
NEXT_ARG();

View File

@ -34,6 +34,7 @@
#include <netdb.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/udp.h>
#include "utils.h"
#include "xfrm.h"
@ -753,12 +754,15 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
fprintf(fp, "type ");
switch (e->encap_type) {
case 1:
case UDP_ENCAP_ESPINUDP_NON_IKE:
fprintf(fp, "espinudp-nonike ");
break;
case 2:
case UDP_ENCAP_ESPINUDP:
fprintf(fp, "espinudp ");
break;
case TCP_ENCAP_ESPINTCP:
fprintf(fp, "espintcp ");
break;
default:
fprintf(fp, "%u ", e->encap_type);
break;
@ -1208,9 +1212,11 @@ int xfrm_encap_type_parse(__u16 *type, int *argcp, char ***argvp)
char **argv = *argvp;
if (strcmp(*argv, "espinudp-nonike") == 0)
*type = 1;
*type = UDP_ENCAP_ESPINUDP_NON_IKE;
else if (strcmp(*argv, "espinudp") == 0)
*type = 2;
*type = UDP_ENCAP_ESPINUDP;
else if (strcmp(*argv, "espintcp") == 0)
*type = TCP_ENCAP_ESPINTCP;
else
invarg("ENCAP-TYPE value is invalid", *argv);

View File

@ -130,7 +130,7 @@ static void usage(void)
"LIMIT-LIST := [ LIMIT-LIST ] limit LIMIT\n"
"LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n"
" { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n"
"ENCAP := { espinudp | espinudp-nonike } SPORT DPORT OADDR\n"
"ENCAP := { espinudp | espinudp-nonike | espintcp } SPORT DPORT OADDR\n"
"DIR := in | out\n");
exit(-1);

View File

@ -207,7 +207,7 @@ ip-xfrm \- transform configuration
.ti -8
.IR ENCAP " :="
.RB "{ " espinudp " | " espinudp-nonike " }"
.RB "{ " espinudp " | " espinudp-nonike " | " espintcp " }"
.IR SPORT " " DPORT " " OADDR
.ti -8
@ -548,7 +548,7 @@ sets limits in seconds, bytes, or numbers of packets.
.TP
.I ENCAP
encapsulates packets with protocol
.BR espinudp " or " espinudp-nonike ","
.BR espinudp ", " espinudp-nonike ", or " espintcp ","
.RI "using source port " SPORT ", destination port " DPORT
.RI ", and original address " OADDR "."

192
man/man8/tc-ets.8 Normal file
View File

@ -0,0 +1,192 @@
.TH TC 8 "December 2019" "iproute2" "Linux"
.SH NAME
ETS \- Enhanced Transmission Selection scheduler
.SH SYNOPSIS
.B tc qdisc ... ets [ bands
number
.B ] [ strict
number
.B ] [ quanta
bytes bytes bytes...
.B ] [ priomap
band band band...
.B ]
.B tc class ... ets [ quantum
bytes
.B ]
.SH DESCRIPTION
The Enhanced Transmission Selection scheduler is a classful queuing
discipline that merges functionality of PRIO and DRR qdiscs in one
scheduler. ETS makes it easy to configure a set of strict and
bandwidth-sharing bands to implement the transmission selection described
in 802.1Qaz.
On creation with 'tc qdisc add', a fixed number of bands is created. Each
band is a class, although it is not possible to directly add and remove
bands with 'tc class' commands. The number of bands to be created must
instead be specified on the command line as the qdisc is added.
The minor number of classid to use when referring to a band is the band
number increased by one. Thus band 0 will have classid of major:1, band 1
that of major:2, etc.
ETS bands are of two types: some number may be in strict mode, the
remaining ones are in bandwidth-sharing mode.
.SH ALGORITHM
When dequeuing, strict bands are tried first, if there are any. Band 0 is
tried first. If it did not deliver a packet, band 1 is tried next, and so
on until one of the bands delivers a packet, or the strict bands are
exhausted.
If no packet has been dequeued from any of the strict bands, if there are
any bandwidth-sharing bands, the dequeuing proceeds according to the DRR
algorithm. Each bandwidth-sharing band is assigned a deficit counter,
initialized to quantum assigned by a
.B quanta
element. ETS maintains an (internal) ''active'' list of bandwidth-sharing
bands whose qdiscs are non-empty. This list is used for dequeuing. A packet
is dequeued from the band at the head of the list if the packet size is
smaller or equal to the deficit counter. If the counter is too small, it is
increased by
.B quantum
and the scheduler moves on to the next band in the active list.
Only qdiscs that own their queue should be added below the
bandwidth-sharing bands. Attaching to them non-work-conserving qdiscs like
TBF does not make sense \-\- other qdiscs in the active list will be
skipped until the dequeue operation succeeds. This limitation does not
exist with the strict bands.
.SH CLASSIFICATION
The ETS qdisc allows three ways to decide which band to enqueue a packet
to:
- Packet priority can be directly set to a class handle, in which case that
is the queue where the packet will be put. For example, band number 2 of
a qdisc with handle of 11: will have classid 11:3. To mark a packet for
queuing to this band, the packet priority should be set to 0x110003.
- A tc filter attached to the qdisc can put the packet to a band by using
the \fBflowid\fR keyword.
- As a last resort, the ETS qdisc consults its priomap (see below), which
maps packets to bands based on packet priority.
.SH PARAMETERS
.TP
strict
The number of bands that should be created in strict mode. If not given,
this value is 0.
.TP
quanta
Each bandwidth-sharing band needs to know its quantum, which is the amount
of bytes a band is allowed to dequeue before the scheduler moves to the
next bandwidth-sharing band. The
.B quanta
argument lists quanta for the individual bandwidth-sharing bands.
The minimum value of each quantum is 1. If
.B quanta
is not given, the default is no bandwidth-sharing bands, but note that when
specifying a large number of
.B bands,
the extra ones are in bandwidth-sharing mode by default.
.TP
bands
Number of bands given explicitly. This value has to be at least large
enough to cover the strict bands specified through the
.B strict
keyword and bandwidth-sharing bands specified in
.B quanta.
If a larger value is given, any extra bands are in bandwidth-sharing mode,
and their quanta are deduced from the interface MTU. If no value is given,
as many bands are created as necessary to cover all bands implied by the
.B strict
and
.B quanta
keywords.
.TP
priomap
The priomap maps the priority of a packet to a band. The argument is a list
of numbers. The first number indicates which band the packets with priority
0 should be put to, the second is for priority 1, and so on.
There can be up to 16 numbers in the list. If there are fewer, the default
band that traffic with one of the unmentioned priorities goes to is the
last one.
.SH EXAMPLE & USAGE
.P
Add a qdisc with 8 bandwidth-sharing bands, using the interface MTU as
their quanta. Since all quanta are the same, this will lead to equal
distribution of bandwidth between the bands, each will get about 12.5% of
the link. The low 8 priorities go to individual bands in a reverse 1:1
fashion (such that the highest priority goes to the first band).
.P
# tc qdisc add dev eth0 root handle 1: ets bands 8 priomap 7 6 5 4 3 2 1 0
.br
# tc qdisc show dev eth0
.br
qdisc ets 1: root refcnt 2 bands 8 quanta 1514 1514 1514 1514 1514 1514 1514 1514 priomap 7 6 5 4 3 2 1 0 7 7 7 7 7 7 7 7
.P
Tweak the first band of the above qdisc to give it a quantum of 2650, which
will give it about 20% of the link (and about 11.5% to the remaining
bands):
.P
# tc class change dev eth0 classid 1:1 ets quantum 2650
.br
# tc qdisc show dev eth0
.br
qdisc ets 1: root refcnt 2 bands 8 quanta 2650 1514 1514 1514 1514 1514 1514 1514 priomap 7 6 5 4 3 2 1 0 7 7 7 7 7 7 7 7
.P
Create a purely strict Qdisc with reverse 1:1 mapping between priorities
and bands:
.P
# tc qdisc add dev eth0 root handle 1: ets strict 8 priomap 7 6 5 4 3 2 1 0
.br
# tc qdisc sh dev eth0
.br
qdisc ets 1: root refcnt 2 bands 8 strict 8 priomap 7 6 5 4 3 2 1 0 7 7 7 7 7 7 7 7
.P
Add a Qdisc with 6 bands, 3 strict and 3 ETS with 35%-30%-25% weights:
.P
# tc qdisc add dev eth0 root handle 1: ets strict 3 quanta 3500 3000 2500 priomap 0 1 1 1 2 3 4 5
.br
# tc qdisc sh dev eth0
.br
qdisc ets 1: root refcnt 2 bands 6 strict 3 quanta 3500 3000 2500 priomap 0 1 1 1 2 3 4 5 5 5 5 5 5 5 5 5
.P
Create a Qdisc such that traffic with priorities 2, 3 and 4 are strictly
prioritized over other traffic, and the rest goes into bandwidth-sharing
classes with equal weights:
.P
# tc qdisc add dev eth0 root handle 1: ets bands 8 strict 3 priomap 3 4 0 1 2 5 6 7
.br
# tc qdisc sh dev eth0
.br
qdisc ets 1: root refcnt 2 bands 8 strict 3 quanta 1514 1514 1514 1514 1514 priomap 3 4 0 1 2 5 6 7 7 7 7 7 7 7 7 7
.SH SEE ALSO
.BR tc (8),
.BR tc-prio (8),
.BR tc-drr (8)
.SH AUTHOR
Parts of both this manual page and the code itself are taken from PRIO and
DRR qdiscs.
.br
ETS qdisc itself was written by Petr Machata.

View File

@ -394,6 +394,12 @@ DSMARK
Classify packets based on TOS field, change TOS field of packets based on
classification.
.TP
ETS
The ETS qdisc is a queuing discipline that merges functionality of PRIO and DRR
qdiscs in one scheduler. ETS makes it easy to configure a set of strict and
bandwidth-sharing bands to implement the transmission selection described in
802.1Qaz.
.TP
HFSC
Hierarchical Fair Service Curve guarantees precise bandwidth and delay allocation for leaf classes and allocates excess bandwidth fairly. Unlike HTB, it makes use of packet dropping to achieve low delays which interactive sessions benefit from.
.TP
@ -844,6 +850,7 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2.
.BR tc-codel (8),
.BR tc-drr (8),
.BR tc-ematch (8),
.BR tc-ets (8),
.BR tc-flow (8),
.BR tc-flower (8),
.BR tc-fq (8),

View File

@ -1135,10 +1135,10 @@ static void buf_free_all(void)
buffer.chunks = 0;
}
/* Get current screen width, default to 80 columns if TIOCGWINSZ fails */
/* Get current screen width, returns -1 if TIOCGWINSZ fails */
static int render_screen_width(void)
{
int width = 80;
int width = -1;
if (isatty(STDOUT_FILENO)) {
struct winsize w;
@ -1159,9 +1159,15 @@ static int render_screen_width(void)
*/
static void render_calc_width(void)
{
int screen_width = render_screen_width();
int screen_width, first, len = 0, linecols = 0;
struct column *c, *eol = columns - 1;
int first, len = 0, linecols = 0;
bool compact_output = false;
screen_width = render_screen_width();
if (screen_width == -1) {
screen_width = INT_MAX;
compact_output = true;
}
/* First pass: set width for each column to measured content length */
for (first = 1, c = columns; c - columns < COL_MAX; c++) {
@ -1183,6 +1189,11 @@ static void render_calc_width(void)
first = 0;
}
if (compact_output) {
/* Compact output, skip extending columns. */
return;
}
/* Second pass: find out newlines and distribute available spacing */
for (c = columns; c - columns < COL_MAX; c++) {
int pad, spacing, rem, last;

View File

@ -79,6 +79,7 @@ TCMODULES += q_cbs.o
TCMODULES += q_etf.o
TCMODULES += q_taprio.o
TCMODULES += q_plug.o
TCMODULES += q_ets.o
TCSO :=
ifeq ($(TC_CONFIG_ATM),y)

View File

@ -2134,7 +2134,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_PRIO];
print_nl();
print_uint(PRINT_ANY, "cvlan_prio", " cvlan_prio %d",
print_uint(PRINT_ANY, "cvlan_prio", " cvlan_prio %d",
rta_getattr_u8(attr));
}
@ -2291,7 +2291,8 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
print_uint(PRINT_ANY, "in_hw_count",
" in_hw_count %u", count);
}
} else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) {
}
else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) {
print_nl();
print_bool(PRINT_ANY, "not_in_hw", " not_in_hw", true);
}

View File

@ -205,7 +205,7 @@ print_csum(struct action_util *au, FILE *f, struct rtattr *arg)
uflag_4, uflag_5, uflag_6, uflag_7);
print_string(PRINT_ANY, "csum", "(%s) ", buf);
print_action_control(f, "action ", sel->action, "\n");
print_action_control(f, "action ", sel->action, _SL_);
print_uint(PRINT_ANY, "index", "\tindex %u", sel->index);
print_int(PRINT_ANY, "ref", " ref %d", sel->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", sel->bindcnt);
@ -217,7 +217,7 @@ print_csum(struct action_util *au, FILE *f, struct rtattr *arg)
print_tm(f, tm);
}
}
print_string(PRINT_FP, NULL, "%s", "\n");
print_nl();
return 0;
}

View File

@ -473,7 +473,8 @@ static int print_ct(struct action_util *au, FILE *f, struct rtattr *arg)
print_action_control(f, " ", p->action, "");
print_uint(PRINT_ANY, "index", "\n\t index %u", p->index);
print_nl();
print_uint(PRINT_ANY, "index", "\t index %u", p->index);
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
@ -484,7 +485,7 @@ static int print_ct(struct action_util *au, FILE *f, struct rtattr *arg)
print_tm(f, tm);
}
}
print_string(PRINT_FP, NULL, "%s", "\n ");
print_nl();
return 0;
}

View File

@ -193,13 +193,15 @@ print_gact(struct action_util *au, FILE *f, struct rtattr *arg)
pp = &pp_dummy;
}
open_json_object("prob");
print_string(PRINT_ANY, "random_type", "\n\t random type %s",
print_nl();
print_string(PRINT_ANY, "random_type", "\t random type %s",
prob_n2a(pp->ptype));
print_action_control(f, " ", pp->paction, " ");
print_int(PRINT_ANY, "val", "val %d", pp->pval);
close_json_object();
#endif
print_uint(PRINT_ANY, "index", "\n\t index %u", p->index);
print_nl();
print_uint(PRINT_ANY, "index", "\t index %u", p->index);
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
if (show_stats) {
@ -209,7 +211,7 @@ print_gact(struct action_util *au, FILE *f, struct rtattr *arg)
print_tm(f, tm);
}
}
print_string(PRINT_FP, NULL, "%s", "\n");
print_nl();
return 0;
}

View File

@ -307,7 +307,8 @@ print_mirred(struct action_util *au, FILE *f, struct rtattr *arg)
print_string(PRINT_ANY, "to_dev", " to device %s)", dev);
print_action_control(f, " ", p->action, "");
print_uint(PRINT_ANY, "index", "\n \tindex %u", p->index);
print_nl();
print_uint(PRINT_ANY, "index", "\tindex %u", p->index);
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
@ -318,7 +319,7 @@ print_mirred(struct action_util *au, FILE *f, struct rtattr *arg)
print_tm(f, tm);
}
}
print_string(PRINT_FP, NULL, "%s", "\n ");
print_nl();
return 0;
}

View File

@ -252,7 +252,8 @@ static int print_mpls(struct action_util *au, FILE *f, struct rtattr *arg)
}
print_action_control(f, " ", parm->action, "");
print_uint(PRINT_ANY, "index", "\n\t index %u", parm->index);
print_nl();
print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);

View File

@ -820,7 +820,7 @@ static int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
sel->nkeys);
}
fprintf(f, "\n ");
print_nl();
free(keys_ex);
return 0;

View File

@ -194,7 +194,7 @@ static int print_simple(struct action_util *au, FILE *f, struct rtattr *arg)
print_tm(f, tm);
}
}
fprintf(f, "\n");
print_nl();
return 0;
}

View File

@ -420,7 +420,8 @@ static void tunnel_key_print_geneve_options(const char *name,
uint8_t type;
open_json_array(PRINT_JSON, name);
print_string(PRINT_FP, name, "\n\t%s ", "geneve_opt");
print_nl();
print_string(PRINT_FP, name, "\t%s ", "geneve_opt");
while (rem) {
parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, i, rem);

View File

@ -219,7 +219,8 @@ static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg)
}
print_action_control(f, " ", parm->action, "");
print_uint(PRINT_ANY, "index", "\n\t index %u", parm->index);
print_nl();
print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
@ -231,7 +232,7 @@ static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg)
}
}
print_string(PRINT_FP, NULL, "%s", "\n");
print_nl();
return 0;
}

View File

@ -391,7 +391,7 @@ print_ipt(struct action_util *au, FILE *f, struct rtattr *arg)
print_tm(f, tm);
}
}
fprintf(f, "\n");
print_nl();
xtables_free_opts(1);

View File

@ -766,7 +766,7 @@ static int cake_print_xstats(struct qdisc_util *qu, FILE *f,
fprintf(f, " ");
for (i = 0; i < num_tins; i++)
fprintf(f, " Tin %u", i);
fprintf(f, "\n");
fprintf(f, "%s", _SL_);
};
#define GET_TSTAT(i, attr) (tstat[i][TCA_CAKE_TIN_STATS_ ## attr])
@ -775,7 +775,7 @@ static int cake_print_xstats(struct qdisc_util *qu, FILE *f,
fprintf(f, name); \
for (i = 0; i < num_tins; i++) \
fprintf(f, " %12" fmts, val); \
fprintf(f, "\n"); \
fprintf(f, "%s", _SL_); \
} \
} while (0)

342
tc/q_ets.c Normal file
View File

@ -0,0 +1,342 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Enhanced Transmission Selection - 802.1Qaz-based Qdisc
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "utils.h"
#include "tc_util.h"
static void explain(void)
{
fprintf(stderr, "Usage: ... ets [bands NUMBER] [strict NUMBER] [quanta Q1 Q2...] [priomap P1 P2...]\n");
}
static void cexplain(void)
{
fprintf(stderr, "Usage: ... ets [quantum Q1]\n");
}
static unsigned int parse_quantum(const char *arg)
{
unsigned int quantum;
if (get_unsigned(&quantum, arg, 10)) {
fprintf(stderr, "Illegal \"quanta\" element\n");
return 0;
}
if (!quantum)
fprintf(stderr, "\"quanta\" must be > 0\n");
return quantum;
}
static int parse_nbands(const char *arg, __u8 *pnbands, const char *what)
{
unsigned int tmp;
if (get_unsigned(&tmp, arg, 10)) {
fprintf(stderr, "Illegal \"%s\"\n", what);
return -1;
}
if (tmp > TCQ_ETS_MAX_BANDS) {
fprintf(stderr, "The number of \"%s\" must be <= %d\n",
what, TCQ_ETS_MAX_BANDS);
return -1;
}
*pnbands = tmp;
return 0;
}
static int ets_parse_opt(struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n, const char *dev)
{
__u8 nbands = 0;
__u8 nstrict = 0;
bool quanta_mode = false;
unsigned int nquanta = 0;
__u32 quanta[TCQ_ETS_MAX_BANDS];
bool priomap_mode = false;
unsigned int nprio = 0;
__u8 priomap[TC_PRIO_MAX + 1];
unsigned int tmp;
struct rtattr *tail, *nest;
while (argc > 0) {
if (strcmp(*argv, "bands") == 0) {
if (nbands) {
fprintf(stderr, "Duplicate \"bands\"\n");
return -1;
}
NEXT_ARG();
if (parse_nbands(*argv, &nbands, "bands"))
return -1;
priomap_mode = quanta_mode = false;
} else if (strcmp(*argv, "strict") == 0) {
if (nstrict) {
fprintf(stderr, "Duplicate \"strict\"\n");
return -1;
}
NEXT_ARG();
if (parse_nbands(*argv, &nstrict, "strict"))
return -1;
priomap_mode = quanta_mode = false;
} else if (strcmp(*argv, "quanta") == 0) {
if (nquanta) {
fprintf(stderr, "Duplicate \"quanta\"\n");
return -1;
}
NEXT_ARG();
priomap_mode = false;
quanta_mode = true;
goto parse_quantum;
} else if (strcmp(*argv, "priomap") == 0) {
if (nprio) {
fprintf(stderr, "Duplicate \"priomap\"\n");
return -1;
}
NEXT_ARG();
priomap_mode = true;
quanta_mode = false;
goto parse_priomap;
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
} else if (quanta_mode) {
unsigned int quantum;
parse_quantum:
quantum = parse_quantum(*argv);
if (!quantum)
return -1;
quanta[nquanta++] = quantum;
} else if (priomap_mode) {
unsigned int band;
parse_priomap:
if (get_unsigned(&band, *argv, 10)) {
fprintf(stderr, "Illegal \"priomap\" element\n");
return -1;
}
if (nprio > TC_PRIO_MAX) {
fprintf(stderr, "\"priomap\" index cannot be higher than %u\n", TC_PRIO_MAX);
return -1;
}
priomap[nprio++] = band;
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
explain();
return -1;
}
argc--; argv++;
}
if (!nbands)
nbands = nquanta + nstrict;
if (!nbands) {
fprintf(stderr, "One of \"bands\", \"quanta\" or \"strict\" needs to be specified\n");
explain();
return -1;
}
if (nbands < 1) {
fprintf(stderr, "The number of \"bands\" must be >= 1\n");
explain();
return -1;
}
if (nstrict + nquanta > nbands) {
fprintf(stderr, "Not enough total bands to cover all the strict bands and quanta\n");
explain();
return -1;
}
for (tmp = 0; tmp < nprio; tmp++) {
if (priomap[tmp] >= nbands) {
fprintf(stderr, "\"priomap\" element is out of bounds\n");
return -1;
}
}
tail = addattr_nest(n, 1024, TCA_OPTIONS | NLA_F_NESTED);
addattr_l(n, 1024, TCA_ETS_NBANDS, &nbands, sizeof(nbands));
if (nstrict)
addattr_l(n, 1024, TCA_ETS_NSTRICT, &nstrict, sizeof(nstrict));
if (nquanta) {
nest = addattr_nest(n, 1024, TCA_ETS_QUANTA | NLA_F_NESTED);
for (tmp = 0; tmp < nquanta; tmp++)
addattr_l(n, 1024, TCA_ETS_QUANTA_BAND,
&quanta[tmp], sizeof(quanta[0]));
addattr_nest_end(n, nest);
}
if (nprio) {
nest = addattr_nest(n, 1024, TCA_ETS_PRIOMAP | NLA_F_NESTED);
for (tmp = 0; tmp < nprio; tmp++)
addattr_l(n, 1024, TCA_ETS_PRIOMAP_BAND,
&priomap[tmp], sizeof(priomap[0]));
addattr_nest_end(n, nest);
}
addattr_nest_end(n, tail);
return 0;
}
static int ets_parse_copt(struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n, const char *dev)
{
unsigned int quantum = 0;
struct rtattr *tail;
while (argc > 0) {
if (strcmp(*argv, "quantum") == 0) {
if (quantum) {
fprintf(stderr, "Duplicate \"quantum\"\n");
return -1;
}
NEXT_ARG();
quantum = parse_quantum(*argv);
if (!quantum)
return -1;
} else if (strcmp(*argv, "help") == 0) {
cexplain();
return -1;
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
cexplain();
return -1;
}
argc--; argv++;
}
tail = addattr_nest(n, 1024, TCA_OPTIONS | NLA_F_NESTED);
if (quantum)
addattr_l(n, 1024, TCA_ETS_QUANTA_BAND, &quantum,
sizeof(quantum));
addattr_nest_end(n, tail);
return 0;
}
static int ets_print_opt_quanta(struct rtattr *opt)
{
int len = RTA_PAYLOAD(opt);
unsigned int offset;
open_json_array(PRINT_ANY, "quanta");
for (offset = 0; offset < len; ) {
struct rtattr *tb[TCA_ETS_MAX + 1] = {NULL};
struct rtattr *attr;
__u32 quantum;
attr = RTA_DATA(opt) + offset;
parse_rtattr(tb, TCA_ETS_MAX, attr, len - offset);
offset += RTA_LENGTH(RTA_PAYLOAD(attr));
if (!tb[TCA_ETS_QUANTA_BAND]) {
fprintf(stderr, "No ETS band quantum\n");
return -1;
}
quantum = rta_getattr_u32(tb[TCA_ETS_QUANTA_BAND]);
print_uint(PRINT_ANY, NULL, " %u", quantum);
}
close_json_array(PRINT_ANY, " ");
return 0;
}
static int ets_print_opt_priomap(struct rtattr *opt)
{
int len = RTA_PAYLOAD(opt);
unsigned int offset;
open_json_array(PRINT_ANY, "priomap");
for (offset = 0; offset < len; ) {
struct rtattr *tb[TCA_ETS_MAX + 1] = {NULL};
struct rtattr *attr;
__u8 band;
attr = RTA_DATA(opt) + offset;
parse_rtattr(tb, TCA_ETS_MAX, attr, len - offset);
offset += RTA_LENGTH(RTA_PAYLOAD(attr)) + 3 /* padding */;
if (!tb[TCA_ETS_PRIOMAP_BAND]) {
fprintf(stderr, "No ETS priomap band\n");
return -1;
}
band = rta_getattr_u8(tb[TCA_ETS_PRIOMAP_BAND]);
print_uint(PRINT_ANY, NULL, " %u", band);
}
close_json_array(PRINT_ANY, " ");
return 0;
}
static int ets_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
struct rtattr *tb[TCA_ETS_MAX + 1];
__u8 nbands;
__u8 nstrict;
int err;
if (opt == NULL)
return 0;
parse_rtattr_nested(tb, TCA_ETS_MAX, opt);
if (!tb[TCA_ETS_NBANDS] || !tb[TCA_ETS_PRIOMAP]) {
fprintf(stderr, "Incomplete ETS options\n");
return -1;
}
nbands = rta_getattr_u8(tb[TCA_ETS_NBANDS]);
print_uint(PRINT_ANY, "bands", "bands %u ", nbands);
if (tb[TCA_ETS_NSTRICT]) {
nstrict = rta_getattr_u8(tb[TCA_ETS_NSTRICT]);
print_uint(PRINT_ANY, "strict", "strict %u ", nstrict);
}
if (tb[TCA_ETS_QUANTA]) {
err = ets_print_opt_quanta(tb[TCA_ETS_QUANTA]);
if (err)
return err;
}
return ets_print_opt_priomap(tb[TCA_ETS_PRIOMAP]);
}
static int ets_print_copt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
struct rtattr *tb[TCA_ETS_MAX + 1];
__u32 quantum;
if (opt == NULL)
return 0;
parse_rtattr_nested(tb, TCA_ETS_MAX, opt);
if (tb[TCA_ETS_QUANTA_BAND]) {
quantum = rta_getattr_u32(tb[TCA_ETS_QUANTA_BAND]);
print_uint(PRINT_ANY, "quantum", "quantum %u ", quantum);
}
return 0;
}
struct qdisc_util ets_qdisc_util = {
.id = "ets",
.parse_qopt = ets_parse_opt,
.parse_copt = ets_parse_copt,
.print_qopt = ets_print_opt,
.print_copt = ets_print_copt,
};

View File

@ -257,7 +257,8 @@ static int fq_codel_print_xstats(struct qdisc_util *qu, FILE *f,
if (st->qdisc_stats.drop_overmemory)
print_uint(PRINT_ANY, "drop_overmemory", " drop_overmemory %u",
st->qdisc_stats.drop_overmemory);
print_uint(PRINT_ANY, "new_flows_len", "\n new_flows_len %u",
print_nl();
print_uint(PRINT_ANY, "new_flows_len", " new_flows_len %u",
st->qdisc_stats.new_flows_len);
print_uint(PRINT_ANY, "old_flows_len", " old_flows_len %u",
st->qdisc_stats.old_flows_len);

View File

@ -246,8 +246,8 @@ static void graph_cls_show(FILE *fp, char *buf, struct hlist_head *root_list,
"+---(%s)", cls_id_str);
strcat(buf, str);
parse_rtattr(tb, TCA_MAX, (struct rtattr *)cls->data,
cls->data_len);
parse_rtattr_flags(tb, TCA_MAX, (struct rtattr *)cls->data,
cls->data_len, NLA_F_NESTED);
if (tb[TCA_KIND] == NULL) {
strcat(buf, " [unknown qdisc kind] ");
@ -327,7 +327,7 @@ int print_class(struct nlmsghdr *n, void *arg)
if (filter_classid && t->tcm_handle != filter_classid)
return 0;
parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);
parse_rtattr_flags(tb, TCA_MAX, TCA_RTA(t), len, NLA_F_NESTED);
if (tb[TCA_KIND] == NULL) {
fprintf(stderr, "print_class: NULL kind\n");

View File

@ -267,7 +267,7 @@ int print_filter(struct nlmsghdr *n, void *arg)
return -1;
}
parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);
parse_rtattr_flags(tb, TCA_MAX, TCA_RTA(t), len, NLA_F_NESTED);
if (tb[TCA_KIND] == NULL && (n->nlmsg_type == RTM_NEWTFILTER ||
n->nlmsg_type == RTM_GETTFILTER ||
@ -364,11 +364,11 @@ int print_filter(struct nlmsghdr *n, void *arg)
close_json_object();
}
}
print_string(PRINT_FP, NULL, "\n", NULL);
print_nl();
if (show_stats && (tb[TCA_STATS] || tb[TCA_STATS2])) {
print_tcstats_attr(fp, tb, " ", NULL);
print_string(PRINT_FP, NULL, "\n", NULL);
print_nl();
}
close_json_object();

View File

@ -235,7 +235,7 @@ int print_qdisc(struct nlmsghdr *n, void *arg)
if (filter_ifindex && filter_ifindex != t->tcm_ifindex)
return 0;
parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);
parse_rtattr_flags(tb, TCA_MAX, TCA_RTA(t), len, NLA_F_NESTED);
if (tb[TCA_KIND] == NULL) {
fprintf(stderr, "print_qdisc: NULL kind\n");
@ -317,11 +317,11 @@ int print_qdisc(struct nlmsghdr *n, void *arg)
}
close_json_object();
print_string(PRINT_FP, NULL, "\n", NULL);
print_nl();
if (show_details && tb[TCA_STAB]) {
print_size_table(fp, " ", tb[TCA_STAB]);
print_string(PRINT_FP, NULL, "\n", NULL);
print_nl();
}
if (show_stats) {
@ -329,12 +329,12 @@ int print_qdisc(struct nlmsghdr *n, void *arg)
if (tb[TCA_STATS] || tb[TCA_STATS2] || tb[TCA_XSTATS]) {
print_tcstats_attr(fp, tb, " ", &xstats);
print_string(PRINT_FP, NULL, "\n", NULL);
print_nl();
}
if (q && xstats && q->print_xstats) {
q->print_xstats(q, fp, xstats);
print_string(PRINT_FP, NULL, "\n", NULL);
print_nl();
}
}
close_json_object();
@ -461,7 +461,7 @@ static int tc_qdisc_block_exists_cb(struct nlmsghdr *n, void *arg)
if (len < 0)
return -1;
parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);
parse_rtattr_flags(tb, TCA_MAX, TCA_RTA(t), len, NLA_F_NESTED);
if (tb[TCA_KIND] == NULL)
return -1;

View File

@ -869,7 +869,7 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat
memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]),
MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
if (!tbs[TCA_STATS_RATE_EST])
print_string(PRINT_FP, NULL, "\n", "");
print_nl();
print_uint(PRINT_JSON, "backlog", NULL, q.backlog);
print_string(PRINT_FP, NULL, "%s", prefix);
print_string(PRINT_FP, NULL, "backlog %s",