* [PATCH] tcp: fix sequence numbers for repaired sockets re-using TIME-WAIT sockets
From: Stefan Baranoff @ 2018-07-10 21:25 UTC (permalink / raw)
To: netdev
Cc: Andrey Vagin, Pavel Emelyanov, Stefan Baranoff, Eric Dumazet,
David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI
This patch fixes a bug where the sequence numbers of a socket created using
TCP repair functionality are lower than set after connect is called.
This occurs when the repair socket overlaps with a TIME-WAIT socket and
triggers the re-use code. The amount lower is equal to the number of times
that a particular IP/port set is re-used and then put back into TIME-WAIT.
Re-using the first time the sequence number is 1 lower, closing that socket
and then re-opening (with repair) a new socket with the same addresses/ports
puts the sequence number 2 lower than set via setsockopt. The third time is
3 lower, etc. I have not tested what the limit of this acrewal is, if any.
The fix is, if a socket is in repair mode, to respect the already set
sequence number and timestamp when it would have already re-used the
TIME-WAIT socket.
Signed-off-by: Stefan Baranoff <sbaranoff@gmail.com>
---
net/ipv4/tcp_ipv4.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index bea17f1..3b2711e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -156,11 +156,24 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
*/
if (tcptw->tw_ts_recent_stamp &&
(!twp || (reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
- tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
- if (tp->write_seq == 0)
- tp->write_seq = 1;
- tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
- tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
+ /* In case of repair and re-using TIME-WAIT sockets we still
+ * want to be sure that it is safe as above but honor the
+ * sequence numbers and time stamps set as part of the repair
+ * process.
+ *
+ * Without this check re-using a TIME-WAIT socket with TCP
+ * repair would accumulate a -1 on the repair assigned
+ * sequence number. The first time it is reused the sequence
+ * is -1, the second time -2, etc. This fixes that issue
+ * without appearing to create any others.
+ */
+ if (likely(!tp->repair)) {
+ tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
+ if (tp->write_seq == 0)
+ tp->write_seq = 1;
+ tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
+ tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
+ }
sock_hold(sktw);
return 1;
}
--
1.8.3.1
^ permalink raw reply related
* RE: [net] sch_fq_codel: zero q->flows_cnt when fq_codel_init fails
From: Keller, Jacob E @ 2018-07-10 21:22 UTC (permalink / raw)
To: Cong Wang; +Cc: Linux Kernel Network Developers, Eric Dumazet
In-Reply-To: <CAM_iQpWC0Zv=4RApRz9s3L9g-r=+FaYXbRrRx+s_GNLwk+9ekQ@mail.gmail.com>
> -----Original Message-----
> From: Cong Wang [mailto:xiyou.wangcong@gmail.com]
> Sent: Tuesday, July 10, 2018 1:32 PM
> To: Keller, Jacob E <jacob.e.keller@intel.com>
> Cc: Linux Kernel Network Developers <netdev@vger.kernel.org>; Eric Dumazet
> <edumazet@google.com>
> Subject: Re: [net] sch_fq_codel: zero q->flows_cnt when fq_codel_init fails
>
> On Mon, Jul 9, 2018 at 8:37 AM Jacob Keller <jacob.e.keller@intel.com> wrote:
> > +alloc_failure:
> > + kfree(q->flows);
>
> You need to call kvfree() instead.
>
> Other than this,
>
> Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
>
> For net-next, I will send a patch to skip ->reset() for ->init() failure
> case, there is no reason to reset queues since qdisc is not even
> activated.
Thanks, I sent a v2.
Regards,
Jake
^ permalink raw reply
* [net v2] sch_fq_codel: zero q->flows_cnt when fq_codel_init fails
From: Jacob Keller @ 2018-07-10 21:22 UTC (permalink / raw)
To: netdev; +Cc: Cong Wang, Eric Dumazet, Jacob Keller
When fq_codel_init fails, qdisc_create_dflt will cleanup by using
qdisc_destroy. This function calls the ->reset() op prior to calling the
->destroy() op.
Unfortunately, during the failure flow for sch_fq_codel, the ->flows
parameter is not initialized, so the fq_codel_reset function will null
pointer dereference.
kernel: BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
kernel: IP: fq_codel_reset+0x58/0xd0 [sch_fq_codel]
kernel: PGD 0 P4D 0
kernel: Oops: 0000 [#1] SMP PTI
kernel: Modules linked in: i40iw i40e(OE) xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack tun bridge stp llc devlink ebtable_filter ebtables ip6table_filter ip6_tables rpcrdma ib_isert iscsi_target_mod sunrpc ib_iser libiscsi scsi_transport_iscsi ib_srpt target_core_mod ib_srp scsi_transport_srp ib_ipoib rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm iw_cm intel_rapl sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel intel_cstate iTCO_wdt iTCO_vendor_support intel_uncore ib_core intel_rapl_perf mei_me mei joydev i2c_i801 lpc_ich ioatdma shpchp wmi sch_fq_codel xfs libcrc32c mgag200 ixgbe drm_kms_helper isci ttm fi
rewire_ohci
kernel: mdio drm igb libsas crc32c_intel firewire_core ptp pps_core scsi_transport_sas crc_itu_t dca i2c_algo_bit ipmi_si ipmi_devintf ipmi_msghandler [last unloaded: i40e]
kernel: CPU: 10 PID: 4219 Comm: ip Tainted: G OE 4.16.13custom-fq-codel-test+ #3
kernel: Hardware name: Intel Corporation S2600CO/S2600CO, BIOS SE5C600.86B.02.05.0004.051120151007 05/11/2015
kernel: RIP: 0010:fq_codel_reset+0x58/0xd0 [sch_fq_codel]
kernel: RSP: 0018:ffffbfbf4c1fb620 EFLAGS: 00010246
kernel: RAX: 0000000000000400 RBX: 0000000000000000 RCX: 00000000000005b9
kernel: RDX: 0000000000000000 RSI: ffff9d03264a60c0 RDI: ffff9cfd17b31c00
kernel: RBP: 0000000000000001 R08: 00000000000260c0 R09: ffffffffb679c3e9
kernel: R10: fffff1dab06a0e80 R11: ffff9cfd163af800 R12: ffff9cfd17b31c00
kernel: R13: 0000000000000001 R14: ffff9cfd153de600 R15: 0000000000000001
kernel: FS: 00007fdec2f92800(0000) GS:ffff9d0326480000(0000) knlGS:0000000000000000
kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
kernel: CR2: 0000000000000008 CR3: 0000000c1956a006 CR4: 00000000000606e0
kernel: Call Trace:
kernel: qdisc_destroy+0x56/0x140
kernel: qdisc_create_dflt+0x8b/0xb0
kernel: mq_init+0xc1/0xf0
kernel: qdisc_create_dflt+0x5a/0xb0
kernel: dev_activate+0x205/0x230
kernel: __dev_open+0xf5/0x160
kernel: __dev_change_flags+0x1a3/0x210
kernel: dev_change_flags+0x21/0x60
kernel: do_setlink+0x660/0xdf0
kernel: ? down_trylock+0x25/0x30
kernel: ? xfs_buf_trylock+0x1a/0xd0 [xfs]
kernel: ? rtnl_newlink+0x816/0x990
kernel: ? _xfs_buf_find+0x327/0x580 [xfs]
kernel: ? _cond_resched+0x15/0x30
kernel: ? kmem_cache_alloc+0x20/0x1b0
kernel: ? rtnetlink_rcv_msg+0x200/0x2f0
kernel: ? rtnl_calcit.isra.30+0x100/0x100
kernel: ? netlink_rcv_skb+0x4c/0x120
kernel: ? netlink_unicast+0x19e/0x260
kernel: ? netlink_sendmsg+0x1ff/0x3c0
kernel: ? sock_sendmsg+0x36/0x40
kernel: ? ___sys_sendmsg+0x295/0x2f0
kernel: ? ebitmap_cmp+0x6d/0x90
kernel: ? dev_get_by_name_rcu+0x73/0x90
kernel: ? skb_dequeue+0x52/0x60
kernel: ? __inode_wait_for_writeback+0x7f/0xf0
kernel: ? bit_waitqueue+0x30/0x30
kernel: ? fsnotify_grab_connector+0x3c/0x60
kernel: ? __sys_sendmsg+0x51/0x90
kernel: ? do_syscall_64+0x74/0x180
kernel: ? entry_SYSCALL_64_after_hwframe+0x3d/0xa2
kernel: Code: 00 00 48 89 87 00 02 00 00 8b 87 a0 01 00 00 85 c0 0f 84 84 00 00 00 31 ed 48 63 dd 83 c5 01 48 c1 e3 06 49 03 9c 24 90 01 00 00 <48> 8b 73 08 48 8b 3b e8 6c 9a 4f f6 48 8d 43 10 48 c7 03 00 00
kernel: RIP: fq_codel_reset+0x58/0xd0 [sch_fq_codel] RSP: ffffbfbf4c1fb620
kernel: CR2: 0000000000000008
kernel: ---[ end trace e81a62bede66274e ]---
This is caused because flows_cnt is non-zero, but flows hasn't been
initialized. fq_codel_init has left the private data in a partially
initialized state.
To fix this, reset flows_cnt to 0 when we fail to initialize.
Additionally, to make the state more consistent, also cleanup the flows
pointer when the allocation of backlogs fails.
This fixes the NULL pointer dereference, since both the for-loop and
memset in fq_codel_reset will be no-ops when flow_cnt is zero.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
net/sched/sch_fq_codel.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index cd2e0e342fb6..6c0a9d5dbf94 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -479,24 +479,28 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
q->cparams.mtu = psched_mtu(qdisc_dev(sch));
if (opt) {
- int err = fq_codel_change(sch, opt, extack);
+ err = fq_codel_change(sch, opt, extack);
if (err)
- return err;
+ goto init_failure;
}
err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
- return err;
+ goto init_failure;
if (!q->flows) {
q->flows = kvcalloc(q->flows_cnt,
sizeof(struct fq_codel_flow),
GFP_KERNEL);
- if (!q->flows)
- return -ENOMEM;
+ if (!q->flows) {
+ err = -ENOMEM;
+ goto init_failure;
+ }
q->backlogs = kvcalloc(q->flows_cnt, sizeof(u32), GFP_KERNEL);
- if (!q->backlogs)
- return -ENOMEM;
+ if (!q->backlogs) {
+ err = -ENOMEM;
+ goto alloc_failure;
+ }
for (i = 0; i < q->flows_cnt; i++) {
struct fq_codel_flow *flow = q->flows + i;
@@ -509,6 +513,13 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
else
sch->flags &= ~TCQ_F_CAN_BYPASS;
return 0;
+
+alloc_failure:
+ kvfree(q->flows);
+ q->flows = NULL;
+init_failure:
+ q->flows_cnt = 0;
+ return err;
}
static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
--
2.18.0.409.g86b1da64138f
^ permalink raw reply related
* [PATCH net-next v2 0/8] be2net: small structures clean-up
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
The series:
- removes unused / unneccessary fields in several be2net structures
- re-order fields in some structures to eliminate holes, cache-lines
crosses
- as result reduces size of main struct be_adapter by 4kB
Ivan Vecera (8):
be2net: remove unused old AIC info
be2net: remove unused old custom busy-poll fields
be2net: remove desc field from be_eq_obj
be2net: reorder fields in be_eq_obj structure
be2net: move txcp field in be_tx_obj to eliminate holes in the struct
be2net: remove unused tx_jiffies field from be_tx_stats
be2net: re-order fields in be_error_recovert to avoid hole
be2net: move rss_flags field in rss_info to ensure proper alignment
drivers/net/ethernet/emulex/benet/be.h | 39 +++++++----------------------
drivers/net/ethernet/emulex/benet/be_main.c | 6 +++--
2 files changed, 13 insertions(+), 32 deletions(-)
--
2.16.4
^ permalink raw reply
* [PATCH net-next v2 3/8] be2net: remove desc field from be_eq_obj
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
In-Reply-To: <20180710205948.10574-1-cera@cera.cz>
The event queue description (be_eq_obj.desc) field is used only to format
string for IRQ name and it is not really needed to hold this value.
Remove it and use local variable to format string for IRQ name.
Signed-off-by: Ivan Vecera <cera@cera.cz>
---
drivers/net/ethernet/emulex/benet/be.h | 1 -
drivers/net/ethernet/emulex/benet/be_main.c | 6 ++++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index a4604dea4560..e71e5e592626 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -185,7 +185,6 @@ static inline void queue_tail_inc(struct be_queue_info *q)
struct be_eq_obj {
struct be_queue_info q;
- char desc[32];
u8 idx; /* array index */
u8 msix_idx;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 8f755009ff38..05e4c0bb25f4 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -3403,9 +3403,11 @@ static int be_msix_register(struct be_adapter *adapter)
int status, i, vec;
for_all_evt_queues(adapter, eqo, i) {
- sprintf(eqo->desc, "%s-q%d", netdev->name, i);
+ char irq_name[IFNAMSIZ+4];
+
+ snprintf(irq_name, sizeof(irq_name), "%s-q%d", netdev->name, i);
vec = be_msix_vec_get(adapter, eqo);
- status = request_irq(vec, be_msix, 0, eqo->desc, eqo);
+ status = request_irq(vec, be_msix, 0, irq_name, eqo);
if (status)
goto err_msix;
--
2.16.4
^ permalink raw reply related
* [PATCH net-next v2 6/8] be2net: remove unused tx_jiffies field from be_tx_stats
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
In-Reply-To: <20180710205948.10574-1-cera@cera.cz>
Signed-off-by: Ivan Vecera <cera@cera.cz>
---
drivers/net/ethernet/emulex/benet/be.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 91ca8d132e87..d521364e17cf 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -217,7 +217,6 @@ struct be_tx_stats {
u64 tx_vxlan_offload_pkts;
u64 tx_reqs;
u64 tx_compl;
- ulong tx_jiffies;
u32 tx_stops;
u32 tx_drv_drops; /* pkts dropped by driver */
/* the error counters are described in be_ethtool.c */
--
2.16.4
^ permalink raw reply related
* [PATCH net-next v2 5/8] be2net: move txcp field in be_tx_obj to eliminate holes in the struct
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
In-Reply-To: <20180710205948.10574-1-cera@cera.cz>
Before patch:
struct be_tx_obj {
u32 db_offset; /* 0 4 */
/* XXX 4 bytes hole, try to pack */
struct be_queue_info q; /* 8 56 */
/* --- cacheline 1 boundary (64 bytes) --- */
struct be_queue_info cq; /* 64 56 */
struct be_tx_compl_info txcp; /* 120 4 */
/* XXX 4 bytes hole, try to pack */
/* --- cacheline 2 boundary (128 bytes) --- */
struct sk_buff * sent_skb_list[2048]; /* 128 16384 */
...
}:
After patch:
struct be_tx_obj {
u32 db_offset; /* 0 4 */
struct be_tx_compl_info txcp; /* 4 4 */
struct be_queue_info q; /* 8 56 */
/* --- cacheline 1 boundary (64 bytes) --- */
struct be_queue_info cq; /* 64 56 */
struct sk_buff * sent_skb_list[2048]; /* 120 16384 */
...
};
Signed-off-by: Ivan Vecera <cera@cera.cz>
---
drivers/net/ethernet/emulex/benet/be.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 716b4bc410f5..91ca8d132e87 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -240,9 +240,9 @@ struct be_tx_compl_info {
struct be_tx_obj {
u32 db_offset;
+ struct be_tx_compl_info txcp;
struct be_queue_info q;
struct be_queue_info cq;
- struct be_tx_compl_info txcp;
/* Remember the skbs that were transmitted */
struct sk_buff *sent_skb_list[TX_Q_LEN];
struct be_tx_stats stats;
--
2.16.4
^ permalink raw reply related
* [PATCH net-next v2 7/8] be2net: re-order fields in be_error_recovert to avoid hole
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
In-Reply-To: <20180710205948.10574-1-cera@cera.cz>
- Unionize two u8 fields where only one of them is used depending on NIC
chipset.
- Move recovery_supported field after that union
These changes eliminate 7-bytes hole in the struct and makes it smaller
by 8 bytes.
Signed-off-by: Ivan Vecera <cera@cera.cz>
---
drivers/net/ethernet/emulex/benet/be.h | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index d521364e17cf..4f805be43180 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -522,11 +522,13 @@ enum {
};
struct be_error_recovery {
- /* Lancer error recovery variables */
- u8 recovery_retries;
+ union {
+ u8 recovery_retries; /* used for Lancer */
+ u8 recovery_state; /* used for BEx and Skyhawk */
+ };
/* BEx/Skyhawk error recovery variables */
- u8 recovery_state;
+ bool recovery_supported;
u16 ue_to_reset_time; /* Time after UE, to soft reset
* the chip - PF0 only
*/
@@ -534,7 +536,6 @@ struct be_error_recovery {
* of SLIPORT_SEMAPHORE reg
*/
u16 last_err_code;
- bool recovery_supported;
unsigned long probe_time;
unsigned long last_recovery_time;
--
2.16.4
^ permalink raw reply related
* [PATCH net-next v2 2/8] be2net: remove unused old custom busy-poll fields
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
In-Reply-To: <20180710205948.10574-1-cera@cera.cz>
The commit fb6113e688e0 ("be2net: get rid of custom busy poll code")
replaced custom busy-poll code by the generic one but left several
macros and fields in struct be_eq_obj that are currently unused.
Remove this stuff.
Fixes: fb6113e688e0 ("be2net: get rid of custom busy poll code")
Signed-off-by: Ivan Vecera <cera@cera.cz>
---
drivers/net/ethernet/emulex/benet/be.h | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 6cf9d106c989..a4604dea4560 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -193,19 +193,6 @@ struct be_eq_obj {
struct napi_struct napi;
struct be_adapter *adapter;
cpumask_var_t affinity_mask;
-
-#ifdef CONFIG_NET_RX_BUSY_POLL
-#define BE_EQ_IDLE 0
-#define BE_EQ_NAPI 1 /* napi owns this EQ */
-#define BE_EQ_POLL 2 /* poll owns this EQ */
-#define BE_EQ_LOCKED (BE_EQ_NAPI | BE_EQ_POLL)
-#define BE_EQ_NAPI_YIELD 4 /* napi yielded this EQ */
-#define BE_EQ_POLL_YIELD 8 /* poll yielded this EQ */
-#define BE_EQ_YIELD (BE_EQ_NAPI_YIELD | BE_EQ_POLL_YIELD)
-#define BE_EQ_USER_PEND (BE_EQ_POLL | BE_EQ_POLL_YIELD)
- unsigned int state;
- spinlock_t lock; /* lock to serialize napi and busy-poll */
-#endif /* CONFIG_NET_RX_BUSY_POLL */
} ____cacheline_aligned_in_smp;
struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */
--
2.16.4
^ permalink raw reply related
* [PATCH net-next v2 8/8] be2net: move rss_flags field in rss_info to ensure proper alignment
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
In-Reply-To: <20180710205948.10574-1-cera@cera.cz>
The current position of .rss_flags field in struct rss_info causes
that fields .rsstable and .rssqueue (both 128 bytes long) crosses
cache-line boundaries. Moving it at the end properly align all fields.
Before patch:
struct rss_info {
u64 rss_flags; /* 0 8 */
u8 rsstable[128]; /* 8 128 */
/* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
u8 rss_queue[128]; /* 136 128 */
/* --- cacheline 4 boundary (256 bytes) was 8 bytes ago --- */
u8 rss_hkey[40]; /* 264 40 */
};
After patch:
struct rss_info {
u8 rsstable[128]; /* 0 128 */
/* --- cacheline 2 boundary (128 bytes) --- */
u8 rss_queue[128]; /* 128 128 */
/* --- cacheline 4 boundary (256 bytes) --- */
u8 rss_hkey[40]; /* 256 40 */
u64 rss_flags; /* 296 8 */
};
Signed-off-by: Ivan Vecera <cera@cera.cz>
---
drivers/net/ethernet/emulex/benet/be.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 4f805be43180..7005949dc17b 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -436,10 +436,10 @@ struct be_port_resources {
#define be_is_os2bmc_enabled(adapter) (adapter->flags & BE_FLAGS_OS2BMC)
struct rss_info {
- u64 rss_flags;
u8 rsstable[RSS_INDIR_TABLE_LEN];
u8 rss_queue[RSS_INDIR_TABLE_LEN];
u8 rss_hkey[RSS_HASH_KEY_LEN];
+ u64 rss_flags;
};
#define BE_INVALID_DIE_TEMP 0xFF
--
2.16.4
^ permalink raw reply related
* [PATCH net-next v2 1/8] be2net: remove unused old AIC info
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
In-Reply-To: <20180710205948.10574-1-cera@cera.cz>
The commit 2632bafd74ae ("be2net: fix adaptive interrupt coalescing")
introduced a separate struct be_aic_obj to hold AIC information but
unfortunately left the old stuff in be_eq_obj. So remove it.
Fixes: 2632bafd74ae ("be2net: fix adaptive interrupt coalescing")
Signed-off-by: Ivan Vecera <cera@cera.cz>
---
drivers/net/ethernet/emulex/benet/be.h | 7 -------
1 file changed, 7 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 382891f81e09..6cf9d106c989 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -187,13 +187,6 @@ struct be_eq_obj {
struct be_queue_info q;
char desc[32];
- /* Adaptive interrupt coalescing (AIC) info */
- bool enable_aic;
- u32 min_eqd; /* in usecs */
- u32 max_eqd; /* in usecs */
- u32 eqd; /* configured val when aic is off */
- u32 cur_eqd; /* in usecs */
-
u8 idx; /* array index */
u8 msix_idx;
u16 spurious_intr;
--
2.16.4
^ permalink raw reply related
* [PATCH net-next v2 4/8] be2net: reorder fields in be_eq_obj structure
From: Ivan Vecera @ 2018-07-10 20:59 UTC (permalink / raw)
To: netdev; +Cc: sathya.perla, sriharsha.basavapatna
In-Reply-To: <20180710205948.10574-1-cera@cera.cz>
Re-order fields in struct be_eq_obj to ensure that .napi field begins
at start of cache-line. Also the .adapter field is moved to the first
cache-line next to .q field and 3 fields (idx,msi_idx,spurious_intr)
and the 4-bytes hole to 3rd cache-line.
Signed-off-by: Ivan Vecera <cera@cera.cz>
---
drivers/net/ethernet/emulex/benet/be.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index e71e5e592626..716b4bc410f5 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -186,11 +186,11 @@ static inline void queue_tail_inc(struct be_queue_info *q)
struct be_eq_obj {
struct be_queue_info q;
+ struct be_adapter *adapter;
+ struct napi_struct napi;
u8 idx; /* array index */
u8 msix_idx;
u16 spurious_intr;
- struct napi_struct napi;
- struct be_adapter *adapter;
cpumask_var_t affinity_mask;
} ____cacheline_aligned_in_smp;
--
2.16.4
^ permalink raw reply related
* [PATCH v2 iproute2-next 19/31] tc/tbf: implement JSON output format
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_tbf.c | 48 ++++++++++++++++++++++++++----------------------
1 file changed, 26 insertions(+), 22 deletions(-)
diff --git a/tc/q_tbf.c b/tc/q_tbf.c
index b9465b20d2be..2695b4fb00e6 100644
--- a/tc/q_tbf.c
+++ b/tc/q_tbf.c
@@ -266,10 +266,6 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
double latency;
__u64 rate64 = 0, prate64 = 0;
- SPRINT_BUF(b1);
- SPRINT_BUF(b2);
- SPRINT_BUF(b3);
-
if (opt == NULL)
return 0;
@@ -285,53 +281,61 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
if (tb[TCA_TBF_RATE64] &&
RTA_PAYLOAD(tb[TCA_TBF_RATE64]) >= sizeof(rate64))
rate64 = rta_getattr_u64(tb[TCA_TBF_RATE64]);
- fprintf(f, "rate %s ", sprint_rate(rate64, b1));
+
+ print_rate("rate", "rate %s ", rate64);
buffer = tc_calc_xmitsize(rate64, qopt->buffer);
+ print_size("burst", "burst %s", buffer);
if (show_details) {
- fprintf(f, "burst %s/%u mpu %s ", sprint_size(buffer, b1),
- 1<<qopt->rate.cell_log, sprint_size(qopt->rate.mpu, b2));
- } else {
- fprintf(f, "burst %s ", sprint_size(buffer, b1));
+ print_uint(PRINT_ANY, "cell_log", "/%u",
+ 1 << qopt->rate.cell_log);
+ print_size("mpu", " mpu %s ", qopt->rate.mpu);
}
+
if (show_raw)
- fprintf(f, "[%08x] ", qopt->buffer);
+ print_0xhex(PRINT_FP, NULL, "[%08x] ", qopt->buffer);
+
prate64 = qopt->peakrate.rate;
if (tb[TCA_TBF_PRATE64] &&
RTA_PAYLOAD(tb[TCA_TBF_PRATE64]) >= sizeof(prate64))
prate64 = rta_getattr_u64(tb[TCA_TBF_PRATE64]);
+
if (prate64) {
- fprintf(f, "peakrate %s ", sprint_rate(prate64, b1));
+ print_rate("peakrate", "peakrate %s ", prate64);
if (qopt->mtu || qopt->peakrate.mpu) {
mtu = tc_calc_xmitsize(prate64, qopt->mtu);
if (show_details) {
- fprintf(f, "mtu %s/%u mpu %s ", sprint_size(mtu, b1),
- 1<<qopt->peakrate.cell_log, sprint_size(qopt->peakrate.mpu, b2));
+ print_size("mtu", "mtu %s", mtu);
+ print_uint(PRINT_FP, NULL, "/%u",
+ 1 << qopt->peakrate.cell_log);
+ print_size("peakrate", " mpu %s ", qopt->peakrate.mpu);
} else {
- fprintf(f, "minburst %s ", sprint_size(mtu, b1));
+ print_size("minburst", "minburst %s ", mtu);
}
if (show_raw)
- fprintf(f, "[%08x] ", qopt->mtu);
+ print_0xhex(PRINT_FP, NULL, "[%08x] ", qopt->mtu);
}
}
latency = TIME_UNITS_PER_SEC*(qopt->limit/(double)rate64) - tc_core_tick2time(qopt->buffer);
if (prate64) {
- double lat2 = TIME_UNITS_PER_SEC*(qopt->limit/(double)prate64) - tc_core_tick2time(qopt->mtu);
+ double lat2 = TIME_UNITS_PER_SEC*(qopt->limit/(double)prate64)
+ - tc_core_tick2time(qopt->mtu);
if (lat2 > latency)
latency = lat2;
}
+
if (latency >= 0.0)
- fprintf(f, "lat %s ", sprint_time(latency, b1));
+ print_time("latency", "lat %s ", latency);
if (show_raw || latency < 0.0)
- fprintf(f, "limit %s ", sprint_size(qopt->limit, b1));
+ print_size("limit", "limit %s ", qopt->limit);
+
+ if (qopt->rate.overhead)
+ print_uint(PRINT_ANY, "overhead", "overhead %u", qopt->rate.overhead);
- if (qopt->rate.overhead) {
- fprintf(f, "overhead %d", qopt->rate.overhead);
- }
linklayer = (qopt->rate.linklayer & TC_LINKLAYER_MASK);
if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
- fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b3));
+ print_linklayer("linklayer", "linklayer %s ", linklayer);
return 0;
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 28/31] tc/atm: convert to JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_atm.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)
diff --git a/tc/q_atm.c b/tc/q_atm.c
index f8215f06507a..d5ab7a06b28f 100644
--- a/tc/q_atm.c
+++ b/tc/q_atm.c
@@ -194,37 +194,45 @@ static int atm_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
fprintf(stderr, "ATM: address too short\n");
else {
if (atm2text(buffer, MAX_ATM_ADDR_LEN,
- RTA_DATA(tb[TCA_ATM_ADDR]), A2T_PRETTY | A2T_NAME) <
- 0) fprintf(stderr, "atm2text error\n");
- fprintf(f, "pvc %s ", buffer);
+ RTA_DATA(tb[TCA_ATM_ADDR]), A2T_PRETTY | A2T_NAME) < 0)
+ fprintf(stderr, "atm2text error\n");
+ else
+ print_string(PRINT_ANY, "pvc",
+ "pvc %s ", buffer);
}
}
+
if (tb[TCA_ATM_HDR]) {
int i;
const __u8 *hdr = RTA_DATA(tb[TCA_ATM_HDR]);
- fprintf(f, "hdr");
- for (i = 0; i < RTA_PAYLOAD(tb[TCA_ATM_HDR]); i++)
- fprintf(f, "%c%02x", i ? '.' : ' ', hdr[i]);
- if (!i) fprintf(f, " .");
- fprintf(f, " ");
+ open_json_array(PRINT_ANY, "hdr");
+ for (i = 0; i < RTA_PAYLOAD(tb[TCA_ATM_HDR]); i++) {
+ print_string(PRINT_FP, NULL, "%s",
+ i ? "." : " ");
+ print_0xhex(PRINT_ANY, NULL, "%02x", hdr[i]);
+ }
+
+ print_string(PRINT_FP, NULL, "%s ", i ? "" : " .");
}
+
if (tb[TCA_ATM_EXCESS]) {
__u32 excess;
if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS]) < sizeof(excess))
fprintf(stderr, "ATM: excess class ID too short\n");
else {
- excess = rta_getattr_u32(tb[TCA_ATM_EXCESS]);
- if (!excess) fprintf(f, "excess clp ");
- else {
- char buf[64];
+ char buf[64];
+ excess = rta_getattr_u32(tb[TCA_ATM_EXCESS]);
+ if (!excess)
+ strcpy(buf, "clp");
+ else
print_tc_classid(buf, sizeof(buf), excess);
- fprintf(f, "excess %s ", buf);
- }
+ print_string(PRINT_ANY, "excess", "excess %s ", buf);
}
}
+
if (tb[TCA_ATM_STATE]) {
static const char *map[] = { ATM_VS2TXT_MAP };
int state;
@@ -233,7 +241,7 @@ static int atm_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
fprintf(stderr, "ATM: state field too short\n");
else {
state = rta_getattr_u32(tb[TCA_ATM_STATE]);
- fprintf(f, "%s ", map[state]);
+ print_string(PRINT_ANY, "state", "%s ", map[state]);
}
}
return 0;
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 10/31] tc/mqprio: implement JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Output queue options in JSON if requested.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_mqprio.c | 134 +++++++++++++++++++++++++++-----------------------
1 file changed, 72 insertions(+), 62 deletions(-)
diff --git a/tc/q_mqprio.c b/tc/q_mqprio.c
index 207d6441d8fa..3d78f9cec996 100644
--- a/tc/q_mqprio.c
+++ b/tc/q_mqprio.c
@@ -213,15 +213,37 @@ static int mqprio_parse_opt(struct qdisc_util *qu, int argc,
return 0;
}
+static void print_rate_table(const struct tc_mqprio_qopt *qopt,
+ const struct rtattr *tbl,
+ const char *key, unsigned short type)
+{
+ __u64 rate64[TC_QOPT_MAX_QUEUE] = { 0 };
+ unsigned int rem = RTA_PAYLOAD(tbl);
+ const struct rtattr *r;
+ int i = 0;
+
+ for (r = RTA_DATA(tbl); RTA_OK(r, rem); r = RTA_NEXT(r, rem)) {
+ if (r->rta_type != type) {
+ fprintf(stderr, "invalid rate table response\n");
+ return;
+ }
+ if (i == TC_QOPT_MAX_QUEUE)
+ break;
+ rate64[i++] = rta_getattr_u64(r);
+ }
+
+ print_string(PRINT_FP, NULL, " %s:", key);
+ open_json_array(PRINT_JSON, key);
+ for (i = 0; i < qopt->num_tc; i++)
+ print_rate(NULL, "%s ", rate64[i]);
+ close_json_array(PRINT_JSON, "");
+}
+
static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
- int i;
struct tc_mqprio_qopt *qopt;
- __u64 min_rate64[TC_QOPT_MAX_QUEUE] = {0};
- __u64 max_rate64[TC_QOPT_MAX_QUEUE] = {0};
- int len;
-
- SPRINT_BUF(b1);
+ struct rtattr *tb[TCA_MQPRIO_MAX + 1];
+ int i, len;
if (opt == NULL)
return 0;
@@ -234,71 +256,59 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
qopt = RTA_DATA(opt);
- fprintf(f, " tc %u map ", qopt->num_tc);
- for (i = 0; i <= TC_PRIO_MAX; i++)
- fprintf(f, "%u ", qopt->prio_tc_map[i]);
- fprintf(f, "\n queues:");
- for (i = 0; i < qopt->num_tc; i++)
- fprintf(f, "(%u:%u) ", qopt->offset[i],
- qopt->offset[i] + qopt->count[i] - 1);
+ print_uint(PRINT_ANY, "num_tc",
+ " tc %u map ", qopt->num_tc);
- if (len > 0) {
- struct rtattr *tb[TCA_MQPRIO_MAX + 1];
-
- parse_rtattr(tb, TCA_MQPRIO_MAX,
- RTA_DATA(opt) + RTA_ALIGN(sizeof(*qopt)),
- len);
+ open_json_array(PRINT_JSON, "priomap");
+ for (i = 0; i <= TC_PRIO_MAX; i++)
+ print_uint(PRINT_ANY, NULL, "%u ", qopt->prio_tc_map[i]);
+ close_json_array(PRINT_JSON, "");
+
+ print_string(PRINT_FP, NULL, "%s queues:", _SL_);
+ open_json_array(PRINT_JSON, "queues");
+ for (i = 0; i < qopt->num_tc; i++) {
+ open_json_object(NULL);
+ print_uint(PRINT_ANY, "offset", "(%u", qopt->offset[i]);
+ print_uint(PRINT_ANY, "length", ":%u) ",
+ qopt->offset[i] + qopt->count[i] - 1);
+ close_json_object();
+ }
+ close_json_array(PRINT_JSON, NULL);
- if (tb[TCA_MQPRIO_MODE]) {
- __u16 *mode = RTA_DATA(tb[TCA_MQPRIO_MODE]);
+ if (len == 0)
+ return 0;
- if (*mode == TC_MQPRIO_MODE_CHANNEL)
- fprintf(f, "\n mode:channel");
- } else {
- fprintf(f, "\n mode:dcb");
- }
+ parse_rtattr(tb, TCA_MQPRIO_MAX,
+ RTA_DATA(opt) + RTA_ALIGN(sizeof(*qopt)),
+ len);
- if (tb[TCA_MQPRIO_SHAPER]) {
- __u16 *shaper = RTA_DATA(tb[TCA_MQPRIO_SHAPER]);
+ if (tb[TCA_MQPRIO_MODE]) {
+ __u16 mode = rta_getattr_u16(tb[TCA_MQPRIO_MODE]);
- if (*shaper == TC_MQPRIO_SHAPER_BW_RATE)
- fprintf(f, "\n shaper:bw_rlimit");
- } else {
- fprintf(f, "\n shaper:dcb");
- }
+ print_string(PRINT_FP, NULL, "%s ", _SL_);
+ print_string(PRINT_ANY, "mode", "mode:%s",
+ mode == TC_MQPRIO_MODE_CHANNEL ? "channel" :
+ mode == TC_MQPRIO_MODE_DCB ? "dcb" :
+ "unknown");
+ }
- if (tb[TCA_MQPRIO_MIN_RATE64]) {
- struct rtattr *r;
- int rem = RTA_PAYLOAD(tb[TCA_MQPRIO_MIN_RATE64]);
- __u64 *min = min_rate64;
+ if (tb[TCA_MQPRIO_SHAPER]) {
+ __u16 shaper = rta_getattr_u16(tb[TCA_MQPRIO_SHAPER]);
- for (r = RTA_DATA(tb[TCA_MQPRIO_MIN_RATE64]);
- RTA_OK(r, rem); r = RTA_NEXT(r, rem)) {
- if (r->rta_type != TCA_MQPRIO_MIN_RATE64)
- return -1;
- *(min++) = rta_getattr_u64(r);
- }
- fprintf(f, " min_rate:");
- for (i = 0; i < qopt->num_tc; i++)
- fprintf(f, "%s ", sprint_rate(min_rate64[i], b1));
- }
+ print_string(PRINT_FP, NULL, "%s ", _SL_);
+ print_string(PRINT_ANY, "shaper", "shaper:%s",
+ shaper == TC_MQPRIO_SHAPER_BW_RATE ? "bw_rlimit" :
+ shaper == TC_MQPRIO_SHAPER_DCB ? "dcb" :
+ "unknown");
+ }
- if (tb[TCA_MQPRIO_MAX_RATE64]) {
- struct rtattr *r;
- int rem = RTA_PAYLOAD(tb[TCA_MQPRIO_MAX_RATE64]);
- __u64 *max = max_rate64;
+ if (tb[TCA_MQPRIO_MIN_RATE64])
+ print_rate_table(qopt, tb[TCA_MQPRIO_MIN_RATE64],
+ "min_rate", TCA_MQPRIO_MIN_RATE64);
- for (r = RTA_DATA(tb[TCA_MQPRIO_MAX_RATE64]);
- RTA_OK(r, rem); r = RTA_NEXT(r, rem)) {
- if (r->rta_type != TCA_MQPRIO_MAX_RATE64)
- return -1;
- *(max++) = rta_getattr_u64(r);
- }
- fprintf(f, " max_rate:");
- for (i = 0; i < qopt->num_tc; i++)
- fprintf(f, "%s ", sprint_rate(max_rate64[i], b1));
- }
- }
+ if (tb[TCA_MQPRIO_MAX_RATE64])
+ print_rate_table(qopt, tb[TCA_MQPRIO_MAX_RATE64],
+ "max_rate", TCA_MQPRIO_MAX_RATE64);
return 0;
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 15/31] tc/multiq: implement JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_multiq.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tc/q_multiq.c b/tc/q_multiq.c
index 8ad9e0b2fa3c..fd2d301bb0c6 100644
--- a/tc/q_multiq.c
+++ b/tc/q_multiq.c
@@ -70,7 +70,8 @@ static int multiq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
qopt = RTA_DATA(opt);
- fprintf(f, "bands %u/%u ", qopt->bands, qopt->max_bands);
+ print_uint(PRINT_ANY, "bands", "bands %u", qopt->bands);
+ print_uint(PRINT_ANY, "max_bands", "/%u ", qopt->max_bands);
return 0;
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 11/31] tc/drr: implement JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_drr.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/tc/q_drr.c b/tc/q_drr.c
index f9c90f3035f3..882cd4a37ec7 100644
--- a/tc/q_drr.c
+++ b/tc/q_drr.c
@@ -84,16 +84,14 @@ static int drr_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
struct rtattr *tb[TCA_DRR_MAX + 1];
- SPRINT_BUF(b1);
-
if (opt == NULL)
return 0;
parse_rtattr_nested(tb, TCA_DRR_MAX, opt);
if (tb[TCA_DRR_QUANTUM])
- fprintf(f, "quantum %s ",
- sprint_size(rta_getattr_u32(tb[TCA_DRR_QUANTUM]), b1));
+ print_size("quantum", "quantum %s ",
+ rta_getattr_u32(tb[TCA_DRR_QUANTUM]));
return 0;
}
@@ -101,15 +99,13 @@ static int drr_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstat
{
struct tc_drr_stats *x;
- SPRINT_BUF(b1);
-
if (xstats == NULL)
return 0;
if (RTA_PAYLOAD(xstats) < sizeof(*x))
return -1;
x = RTA_DATA(xstats);
- fprintf(f, " deficit %s ", sprint_size(x->deficit, b1));
+ print_size("deficit", " deficit %s ", x->deficit);
return 0;
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 26/31] tc/cbs: convert to JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_cbs.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tc/q_cbs.c b/tc/q_cbs.c
index a2ffb1db3852..1518a79cd733 100644
--- a/tc/q_cbs.c
+++ b/tc/q_cbs.c
@@ -125,11 +125,11 @@ static int cbs_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
if (RTA_PAYLOAD(tb[TCA_CBS_PARMS]) < sizeof(*qopt))
return -1;
- fprintf(f, "hicredit %d ", qopt->hicredit);
- fprintf(f, "locredit %d ", qopt->locredit);
- fprintf(f, "sendslope %d ", qopt->sendslope);
- fprintf(f, "idleslope %d ", qopt->idleslope);
- fprintf(f, "offload %d ", qopt->offload);
+ print_uint(PRINT_ANY, "hicredit", "hicredit %u ", qopt->hicredit);
+ print_uint(PRINT_ANY, "locredit", "locredit %u", qopt->locredit);
+ print_uint(PRINT_ANY, "sendslope", "sendslope %u", qopt->sendslope);
+ print_uint(PRINT_ANY, "idleslope", "idleslope %u", qopt->idleslope);
+ print_uint(PRINT_ANY, "offload", "offload %u", qopt->offload);
return 0;
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 16/31] tc/util: allow signed value for time
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
The codel algorithm wants a signed value for time when
outputting values. Allow it for other uses as well.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/tc_util.c | 6 +++---
tc/tc_util.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/tc/tc_util.c b/tc/tc_util.c
index 43a67fd13f94..3789b38773a7 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -370,7 +370,7 @@ int get_time(unsigned int *time, const char *str)
return 0;
}
-char *sprint_time(__u32 time, char *buf)
+char *sprint_time(__s32 time, char *buf)
{
const size_t len = SPRINT_BSIZE - 1;
double tmp = time;
@@ -380,12 +380,12 @@ char *sprint_time(__u32 time, char *buf)
else if (tmp >= TIME_UNITS_PER_SEC/1000)
snprintf(buf, len, "%.1fms", tmp/(TIME_UNITS_PER_SEC/1000));
else
- snprintf(buf, len, "%uus", time);
+ snprintf(buf, len, "%dus", time);
return buf;
}
-void print_time(const char *key, const char *fmt, __u32 tm)
+void print_time(const char *key, const char *fmt, __s32 tm)
{
double secs = (double)tm / TIME_UNITS_PER_SEC;
SPRINT_BUF(b1);
diff --git a/tc/tc_util.h b/tc/tc_util.h
index e83bb7dbcc76..23d11520eb50 100644
--- a/tc/tc_util.h
+++ b/tc/tc_util.h
@@ -97,7 +97,7 @@ char *sprint_rate(__u64 rate, char *buf);
char *sprint_size(__u32 size, char *buf);
char *sprint_qdisc_handle(__u32 h, char *buf);
char *sprint_tc_classid(__u32 h, char *buf);
-char *sprint_time(__u32 time, char *buf);
+char *sprint_time(__s32 time, char *buf);
char *sprint_ticks(__u32 ticks, char *buf);
char *sprint_linklayer(unsigned int linklayer, char *buf);
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 14/31] tc/sfb: implement JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_sfb.c | 56 +++++++++++++++++++++++++++++++++---------------------
1 file changed, 34 insertions(+), 22 deletions(-)
diff --git a/tc/q_sfb.c b/tc/q_sfb.c
index 7f48c6e0ef39..d58ce71f83ce 100644
--- a/tc/q_sfb.c
+++ b/tc/q_sfb.c
@@ -153,14 +153,20 @@ static int sfb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
if (RTA_PAYLOAD(tb[TCA_SFB_PARMS]) < sizeof(*qopt))
return -1;
- fprintf(f,
- "limit %d max %d target %d\n"
- " increment %.5f decrement %.5f penalty rate %d burst %d (%ums %ums)",
- qopt->limit, qopt->max, qopt->bin_size,
- (double)qopt->increment / SFB_MAX_PROB,
- (double)qopt->decrement / SFB_MAX_PROB,
- qopt->penalty_rate, qopt->penalty_burst,
- qopt->rehash_interval, qopt->warmup_time);
+ print_uint(PRINT_ANY, "limit", "limit %u", qopt->limit);
+ print_uint(PRINT_ANY, "max", " max %u", qopt->max);
+ print_uint(PRINT_ANY, "target", " target %u", qopt->bin_size);
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+
+ print_float(PRINT_ANY, "increment", " increment %.5f",
+ (double)qopt->increment / SFB_MAX_PROB);
+ print_float(PRINT_ANY, "decrement", " decrement %.5f",
+ (double)qopt->decrement / SFB_MAX_PROB);
+ print_uint(PRINT_ANY, "penalty_rate", " penalty rate %u",
+ qopt->penalty_rate);
+ print_uint(PRINT_ANY, "penalty_burst", " burst %u", qopt->penalty_burst);
+ print_uint(PRINT_ANY, "rehash", " (%ums", qopt->rehash_interval);
+ print_uint(PRINT_ANY, "warmup", " %ums)", qopt->warmup_time);
return 0;
}
@@ -168,24 +174,30 @@ static int sfb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
static int sfb_print_xstats(struct qdisc_util *qu, FILE *f,
struct rtattr *xstats)
{
- struct tc_sfb_xstats *st;
+ struct tc_sfb_xstats *st;
- if (xstats == NULL)
- return 0;
+ if (xstats == NULL)
+ return 0;
- if (RTA_PAYLOAD(xstats) < sizeof(*st))
- return -1;
+ if (RTA_PAYLOAD(xstats) < sizeof(*st))
+ return -1;
- st = RTA_DATA(xstats);
- fprintf(f,
- " earlydrop %u penaltydrop %u bucketdrop %u queuedrop %u childdrop %u marked %u\n"
- " maxqlen %u maxprob %.5f avgprob %.5f ",
- st->earlydrop, st->penaltydrop, st->bucketdrop, st->queuedrop, st->childdrop,
- st->marked,
- st->maxqlen, (double)st->maxprob / SFB_MAX_PROB,
- (double)st->avgprob / SFB_MAX_PROB);
+ st = RTA_DATA(xstats);
+ print_uint(PRINT_ANY, "earlydrop", " earlydrop %u", st->earlydrop);
+ print_uint(PRINT_ANY, "penaltydrop", "penaltydrop %u", st->penaltydrop);
+ print_uint(PRINT_ANY, "bucketdrop", "bucketdrop %u", st->bucketdrop);
+ print_uint(PRINT_ANY, "queuedrop", "queuedrop %u", st->queuedrop);
+ print_uint(PRINT_ANY, "childdrop", "childdrop %u", st->childdrop);
+ print_uint(PRINT_ANY, "marked", "marked %u", st->marked);
+ print_uint(PRINT_ANY, "maxqlen", " maxqlen %u", st->maxqlen);
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+
+ print_float(PRINT_ANY, "maxprob", " maxprob %.5f",
+ (double)st->maxprob / SFB_MAX_PROB);
+ print_float(PRINT_ANY, "avgprob", " avgprob %.5f",
+ (double)st->avgprob / SFB_MAX_PROB);
- return 0;
+ return 0;
}
struct qdisc_util sfb_qdisc_util = {
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 03/31] tc: convert stats print to json
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Convert compatiablity statistics to print in JSON.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/tc_util.c | 32 ++++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)
diff --git a/tc/tc_util.c b/tc/tc_util.c
index e8e1241d083d..05b6c97563b3 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -887,25 +887,37 @@ void print_tcstats_attr(FILE *fp, struct rtattr *tb[],
/* handle case where kernel returns more/less than we know about */
memcpy(&st, RTA_DATA(tb[TCA_STATS]), MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st)));
- fprintf(fp, "%sSent %llu bytes %u pkts (dropped %u, overlimits %u) ",
- prefix, (unsigned long long)st.bytes, st.packets, st.drops,
- st.overlimits);
+ print_string(PRINT_FP, NULL, "%sSent ", prefix);
+ print_u64(PRINT_ANY, "bytes", "%llu bytes ", (unsigned long long)st.bytes);
+ print_uint(PRINT_ANY, "packets", "%u pkts ", st.packets);
+ print_uint(PRINT_ANY, "dropped", "(dropped %u, ", st.drops);
+ print_uint(PRINT_ANY, "overlimits", "overlimits %u) ", st.overlimits);
if (st.bps || st.pps || st.qlen || st.backlog) {
- fprintf(fp, "\n%s", prefix);
+ print_string(PRINT_FP, "%s%s", _SL_, prefix);
+
if (st.bps || st.pps) {
- fprintf(fp, "rate ");
+ print_string(PRINT_FP, NULL, "%s", "rate ");
+ print_uint(PRINT_JSON, "rate", NULL, st.bps);
if (st.bps)
- fprintf(fp, "%s ", sprint_rate(st.bps, b1));
+ print_string(PRINT_FP, NULL, "%s ",
+ sprint_rate(st.bps, b1));
+
+ print_uint(PRINT_JSON, "pps", NULL, st.pps);
if (st.pps)
- fprintf(fp, "%upps ", st.pps);
+ print_uint(PRINT_FP, NULL, "%upps ", st.pps);
}
if (st.qlen || st.backlog) {
- fprintf(fp, "backlog ");
+ print_string(PRINT_FP, NULL, "%s", "backlog ");
+
+ print_uint(PRINT_JSON, "backlog", NULL, st.backlog);
+ print_uint(PRINT_JSON, "qlen", NULL, st.qlen);
if (st.backlog)
- fprintf(fp, "%s ", sprint_size(st.backlog, b1));
+ print_string(PRINT_FP, NULL,
+ "%s ", sprint_size(st.backlog, b1));
if (st.qlen)
- fprintf(fp, "%up ", st.qlen);
+ print_uint(PRINT_FP, NULL,
+ "%up ", st.qlen);
}
}
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 21/31] tc/hhf: implement JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_hhf.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/tc/q_hhf.c b/tc/q_hhf.c
index 21186a92c017..daea6bbcdd65 100644
--- a/tc/q_hhf.c
+++ b/tc/q_hhf.c
@@ -127,8 +127,6 @@ static int hhf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
unsigned int evict_timeout;
unsigned int non_hh_weight;
- SPRINT_BUF(b1);
-
if (opt == NULL)
return 0;
@@ -137,37 +135,38 @@ static int hhf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
if (tb[TCA_HHF_BACKLOG_LIMIT] &&
RTA_PAYLOAD(tb[TCA_HHF_BACKLOG_LIMIT]) >= sizeof(__u32)) {
limit = rta_getattr_u32(tb[TCA_HHF_BACKLOG_LIMIT]);
- fprintf(f, "limit %up ", limit);
+ print_uint(PRINT_ANY, "limit", "limit %up ", limit);
}
if (tb[TCA_HHF_QUANTUM] &&
RTA_PAYLOAD(tb[TCA_HHF_QUANTUM]) >= sizeof(__u32)) {
quantum = rta_getattr_u32(tb[TCA_HHF_QUANTUM]);
- fprintf(f, "quantum %u ", quantum);
+ print_uint(PRINT_ANY, "quantum", "quantum %u ", quantum);
}
if (tb[TCA_HHF_HH_FLOWS_LIMIT] &&
RTA_PAYLOAD(tb[TCA_HHF_HH_FLOWS_LIMIT]) >= sizeof(__u32)) {
hh_limit = rta_getattr_u32(tb[TCA_HHF_HH_FLOWS_LIMIT]);
- fprintf(f, "hh_limit %u ", hh_limit);
+ print_uint(PRINT_ANY, "hh_limit", "hh_limit %u ", hh_limit);
}
if (tb[TCA_HHF_RESET_TIMEOUT] &&
RTA_PAYLOAD(tb[TCA_HHF_RESET_TIMEOUT]) >= sizeof(__u32)) {
reset_timeout = rta_getattr_u32(tb[TCA_HHF_RESET_TIMEOUT]);
- fprintf(f, "reset_timeout %s ", sprint_time(reset_timeout, b1));
+ print_time("reset_timeout", "reset_timeout %s ", reset_timeout);
}
if (tb[TCA_HHF_ADMIT_BYTES] &&
RTA_PAYLOAD(tb[TCA_HHF_ADMIT_BYTES]) >= sizeof(__u32)) {
admit_bytes = rta_getattr_u32(tb[TCA_HHF_ADMIT_BYTES]);
- fprintf(f, "admit_bytes %u ", admit_bytes);
+ print_uint(PRINT_ANY, "admit_bytes", "admit_bytes %u ", admit_bytes);
}
if (tb[TCA_HHF_EVICT_TIMEOUT] &&
RTA_PAYLOAD(tb[TCA_HHF_EVICT_TIMEOUT]) >= sizeof(__u32)) {
evict_timeout = rta_getattr_u32(tb[TCA_HHF_EVICT_TIMEOUT]);
- fprintf(f, "evict_timeout %s ", sprint_time(evict_timeout, b1));
+ print_time("evict_timeout", "evict_timeout %s ", evict_timeout);
}
if (tb[TCA_HHF_NON_HH_WEIGHT] &&
RTA_PAYLOAD(tb[TCA_HHF_NON_HH_WEIGHT]) >= sizeof(__u32)) {
non_hh_weight = rta_getattr_u32(tb[TCA_HHF_NON_HH_WEIGHT]);
- fprintf(f, "non_hh_weight %u ", non_hh_weight);
+ print_uint(PRINT_ANY, "non_hh_weight",
+ "non_hh_weight %u ", non_hh_weight);
}
return 0;
}
@@ -185,9 +184,10 @@ static int hhf_print_xstats(struct qdisc_util *qu, FILE *f,
st = RTA_DATA(xstats);
- fprintf(f, " drop_overlimit %u hh_overlimit %u tot_hh %u cur_hh %u",
- st->drop_overlimit, st->hh_overlimit,
- st->hh_tot_count, st->hh_cur_count);
+ print_uint(PRINT_ANY, "drop_overlimit", "drop_overlimit %u", st->drop_overlimit);
+ print_uint(PRINT_ANY, "hh_overlimit", "hh_overlimit %u", st->hh_overlimit);
+ print_uint(PRINT_ANY, "tot_count", "tot_hh %u", st->hh_tot_count);
+ print_uint(PRINT_ANY, "cur_count", "cur_hh %u", st->hh_cur_count);
return 0;
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 22/31] tc/pie: implement JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_pie.c | 33 ++++++++++++++++++---------------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/tc/q_pie.c b/tc/q_pie.c
index f7924ef5e76c..086785588d64 100644
--- a/tc/q_pie.c
+++ b/tc/q_pie.c
@@ -135,8 +135,6 @@ static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
unsigned int ecn;
unsigned int bytemode;
- SPRINT_BUF(b1);
-
if (opt == NULL)
return 0;
@@ -145,40 +143,40 @@ static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
if (tb[TCA_PIE_LIMIT] &&
RTA_PAYLOAD(tb[TCA_PIE_LIMIT]) >= sizeof(__u32)) {
limit = rta_getattr_u32(tb[TCA_PIE_LIMIT]);
- fprintf(f, "limit %up ", limit);
+ print_uint(PRINT_ANY, "limit", "limit %up ", limit);
}
if (tb[TCA_PIE_TARGET] &&
RTA_PAYLOAD(tb[TCA_PIE_TARGET]) >= sizeof(__u32)) {
target = rta_getattr_u32(tb[TCA_PIE_TARGET]);
- fprintf(f, "target %s ", sprint_time(target, b1));
+ print_time("target", "target %s ", target);
}
if (tb[TCA_PIE_TUPDATE] &&
RTA_PAYLOAD(tb[TCA_PIE_TUPDATE]) >= sizeof(__u32)) {
tupdate = rta_getattr_u32(tb[TCA_PIE_TUPDATE]);
- fprintf(f, "tupdate %s ", sprint_time(tupdate, b1));
+ print_time("tupdate", "tupdate %s ", tupdate);
}
if (tb[TCA_PIE_ALPHA] &&
RTA_PAYLOAD(tb[TCA_PIE_ALPHA]) >= sizeof(__u32)) {
alpha = rta_getattr_u32(tb[TCA_PIE_ALPHA]);
- fprintf(f, "alpha %u ", alpha);
+ print_uint(PRINT_ANY, "alpha", "alpha %u ", alpha);
}
if (tb[TCA_PIE_BETA] &&
RTA_PAYLOAD(tb[TCA_PIE_BETA]) >= sizeof(__u32)) {
beta = rta_getattr_u32(tb[TCA_PIE_BETA]);
- fprintf(f, "beta %u ", beta);
+ print_uint(PRINT_ANY, "beta", "beta %u ", beta);
}
if (tb[TCA_PIE_ECN] && RTA_PAYLOAD(tb[TCA_PIE_ECN]) >= sizeof(__u32)) {
ecn = rta_getattr_u32(tb[TCA_PIE_ECN]);
if (ecn)
- fprintf(f, "ecn ");
+ print_null(PRINT_ANY, "ecn", "ecn ", NULL);
}
if (tb[TCA_PIE_BYTEMODE] &&
RTA_PAYLOAD(tb[TCA_PIE_BYTEMODE]) >= sizeof(__u32)) {
bytemode = rta_getattr_u32(tb[TCA_PIE_BYTEMODE]);
if (bytemode)
- fprintf(f, "bytemode ");
+ print_null(PRINT_ANY, "bytemode", "bytemode ", NULL);
}
return 0;
@@ -197,12 +195,17 @@ static int pie_print_xstats(struct qdisc_util *qu, FILE *f,
st = RTA_DATA(xstats);
/*prob is returned as a fracion of maximum integer value */
- fprintf(f, "prob %f delay %uus avg_dq_rate %u\n",
- (double)st->prob / (double)0xffffffff, st->delay,
- st->avg_dq_rate);
- fprintf(f, "pkts_in %u overlimit %u dropped %u maxq %u ecn_mark %u\n",
- st->packets_in, st->overlimit, st->dropped, st->maxq,
- st->ecn_mark);
+ print_float(PRINT_ANY, "prob", "prob %f",
+ (double)st->prob / (double)0xffffffff);
+ print_uint(PRINT_ANY, "delay", " delay %uus", st->delay);
+ print_uint(PRINT_ANY, "avg_dq_rate", " avg_dq_rate %u", st->avg_dq_rate);
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+
+ print_uint(PRINT_ANY, "packets_in", "pkts_in %u", st->packets_in);
+ print_uint(PRINT_ANY, "overlimit", " overlimit %u", st->overlimit);
+ print_uint(PRINT_ANY, "dropped", " dropped %u", st->dropped);
+ print_uint(PRINT_ANY, "maxq", " maxq %u", st->maxq);
+ print_uint(PRINT_ANY, "ecn_mark", " ecn_mark %u", st->ecn_mark);
return 0;
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 06/31] tc/util: add print helpers for JSON
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Add a helper to print rate, time and size in numeric or pretty format
based on JSON flag.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/tc_util.c | 83 +++++++++++++++++++++++++++++++++-------------------
tc/tc_util.h | 6 ++++
2 files changed, 59 insertions(+), 30 deletions(-)
diff --git a/tc/tc_util.c b/tc/tc_util.c
index 29bdbbff4a6e..43a67fd13f94 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -330,6 +330,19 @@ char *sprint_rate(__u64 rate, char *buf)
return buf;
}
+/*
+ * print rate as numeric in JSON
+ * or in human format otherwise.
+ */
+void print_rate(const char *key, const char *fmt, __u64 rate)
+{
+ SPRINT_BUF(b1);
+
+ print_u64(PRINT_JSON, key, NULL, rate);
+ print_string(PRINT_FP, NULL, fmt,
+ sprint_rate(rate, b1));
+}
+
int get_time(unsigned int *time, const char *str)
{
double t;
@@ -372,11 +385,27 @@ char *sprint_time(__u32 time, char *buf)
return buf;
}
+void print_time(const char *key, const char *fmt, __u32 tm)
+{
+ double secs = (double)tm / TIME_UNITS_PER_SEC;
+ SPRINT_BUF(b1);
+
+ print_float(PRINT_JSON, key, NULL, secs);
+ print_string(PRINT_FP, NULL, fmt,
+ sprint_time(tm, b1));
+}
+
+
char *sprint_ticks(__u32 ticks, char *buf)
{
return sprint_time(tc_core_tick2time(ticks), buf);
}
+void print_ticks(const char *key, const char *fmt, __u32 ticks)
+{
+ print_time(key, fmt, tc_core_tick2time(ticks));
+}
+
int get_size(unsigned int *size, const char *str)
{
double sz;
@@ -462,6 +491,15 @@ char *sprint_size(__u32 sz, char *buf)
return buf;
}
+void print_size(const char *key, const char *fmt, __u32 sz)
+{
+ SPRINT_BUF(b1);
+
+ print_uint(PRINT_JSON, key, NULL, sz);
+ print_string(PRINT_FP, NULL, fmt,
+ sprint_size(sz, b1));
+}
+
void print_qdisc_handle(char *buf, int len, __u32 h)
{
snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16);
@@ -766,6 +804,14 @@ char *sprint_linklayer(unsigned int linklayer, char *buf)
return buf;
}
+void print_linklayer(const char *key, const char *fmt, unsigned int linklayer)
+{
+ SPRINT_BUF(b1);
+
+ sprint_linklayer(linklayer, b1);
+ print_string(PRINT_ANY, key, fmt, b1);
+}
+
void print_tm(FILE *f, const struct tcf_t *tm)
{
int hz = get_user_hz();
@@ -790,7 +836,6 @@ void print_tm(FILE *f, const struct tcf_t *tm)
void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
const char *prefix, struct rtattr **xstats)
{
- SPRINT_BUF(b1);
struct rtattr *tbs[TCA_STATS_MAX + 1];
parse_rtattr_nested(tbs, TCA_STATS_MAX, rta);
@@ -821,21 +866,15 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST64]),
sizeof(re)));
print_string(PRINT_FP, NULL, "\n%s", prefix);
- print_lluint(PRINT_JSON, "rate", NULL, re.bps);
- print_string(PRINT_FP, NULL, "rate %s",
- sprint_rate(re.bps, b1));
+ print_rate("rate", "rate %s", re.bps);
print_lluint(PRINT_ANY, "pps", " %llupps", re.pps);
} else if (tbs[TCA_STATS_RATE_EST]) {
struct gnet_stats_rate_est re = {0};
memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST]),
MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));
- fprintf(fp, "\n%srate %s %upps ",
- prefix, sprint_rate(re.bps, b1), re.pps);
print_string(PRINT_FP, NULL, "\n%s", prefix);
- print_uint(PRINT_JSON, "rate", NULL, re.bps);
- print_string(PRINT_FP, NULL, "rate %s",
- sprint_rate(re.bps, b1));
+ print_rate("rate", "rate %s", re.bps);
print_uint(PRINT_ANY, "pps", " %upps", re.pps);
}
@@ -845,9 +884,7 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
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%s", prefix);
- print_uint(PRINT_JSON, "backlog", NULL, q.backlog);
- print_string(PRINT_FP, NULL, "backlog %s",
- sprint_size(q.backlog, b1));
+ print_size("backlog", "backlog %s", q.backlog);
print_uint(PRINT_ANY, "qlen", " %up", q.qlen);
print_uint(PRINT_FP, NULL, " requeues %u", q.requeues);
}
@@ -859,8 +896,6 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
void print_tcstats_attr(FILE *fp, struct rtattr *tb[],
const char *prefix, struct rtattr **xstats)
{
- SPRINT_BUF(b1);
-
if (tb[TCA_STATS2]) {
print_tcstats2_attr(fp, tb[TCA_STATS2], prefix, xstats);
if (xstats && NULL == *xstats)
@@ -885,26 +920,14 @@ void print_tcstats_attr(FILE *fp, struct rtattr *tb[],
if (st.bps || st.pps) {
print_string(PRINT_FP, NULL, "%s", "rate ");
- print_uint(PRINT_JSON, "rate", NULL, st.bps);
- if (st.bps)
- print_string(PRINT_FP, NULL, "%s ",
- sprint_rate(st.bps, b1));
-
- print_uint(PRINT_JSON, "pps", NULL, st.pps);
- if (st.pps)
- print_uint(PRINT_FP, NULL, "%upps ", st.pps);
+ print_rate("rate", "%s ", st.bps);
+ print_uint(PRINT_JSON, "pps", "%upps ", st.pps);
}
if (st.qlen || st.backlog) {
print_string(PRINT_FP, NULL, "%s", "backlog ");
- print_uint(PRINT_JSON, "backlog", NULL, st.backlog);
- print_uint(PRINT_JSON, "qlen", NULL, st.qlen);
- if (st.backlog)
- print_string(PRINT_FP, NULL,
- "%s ", sprint_size(st.backlog, b1));
- if (st.qlen)
- print_uint(PRINT_FP, NULL,
- "%up ", st.qlen);
+ print_size("backlog", "%s ", st.backlog);
+ print_uint(PRINT_ANY, "qlen", "%up ", st.qlen);
}
}
}
diff --git a/tc/tc_util.h b/tc/tc_util.h
index 1690ad262351..e83bb7dbcc76 100644
--- a/tc/tc_util.h
+++ b/tc/tc_util.h
@@ -87,6 +87,12 @@ int get_linklayer(unsigned int *val, const char *arg);
void print_qdisc_handle(char *buf, int len, __u32 h);
void print_devname(enum output_type type, int ifindex);
+void print_rate(const char *key, const char *fmt, __u64 rate);
+void print_size(const char *key, const char *fmt, __u32 sz);
+void print_time(const char *key, const char *fmt, __s32 tm);
+void print_ticks(const char *key, const char *fmt, __u32 ticks);
+void print_linklayer(const char *key, const char *fmt, unsigned int linklayer);
+
char *sprint_rate(__u64 rate, char *buf);
char *sprint_size(__u32 size, char *buf);
char *sprint_qdisc_handle(__u32 h, char *buf);
--
2.18.0
^ permalink raw reply related
* [PATCH v2 iproute2-next 29/31] tc/hfsc: convert to JSON output
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger
In-Reply-To: <20180710210558.20278-1-stephen@networkplumber.org>
From: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_hfsc.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/tc/q_hfsc.c b/tc/q_hfsc.c
index f34b1b2fe2a9..e2f366b8a189 100644
--- a/tc/q_hfsc.c
+++ b/tc/q_hfsc.c
@@ -113,7 +113,8 @@ hfsc_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
qopt = RTA_DATA(opt);
if (qopt->defcls != 0)
- fprintf(f, "default %x ", qopt->defcls);
+ print_0xhex(PRINT_ANY, "default",
+ "default %x ", qopt->defcls);
return 0;
}
@@ -129,13 +130,12 @@ hfsc_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
return -1;
st = RTA_DATA(xstats);
- fprintf(f, " period %u ", st->period);
+ print_uint(PRINT_ANY, "period", " period %u ", st->period);
if (st->work != 0)
- fprintf(f, "work %llu bytes ", (unsigned long long) st->work);
+ print_u64(PRINT_ANY, "work", "work %llu bytes ", st->work);
if (st->rtwork != 0)
- fprintf(f, "rtwork %llu bytes ", (unsigned long long) st->rtwork);
- fprintf(f, "level %u ", st->level);
- fprintf(f, "\n");
+ print_u64(PRINT_ANY, "rtwork", "rtwork %llu bytes ", st->rtwork);
+ print_uint(PRINT_ANY, "level", "level %u ", st->level);
return 0;
}
@@ -214,14 +214,14 @@ hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
}
static void
-hfsc_print_sc(FILE *f, char *name, struct tc_service_curve *sc)
+hfsc_print_sc(FILE *f, const char *name, const struct tc_service_curve *sc)
{
- SPRINT_BUF(b1);
-
- fprintf(f, "%s ", name);
- fprintf(f, "m1 %s ", sprint_rate(sc->m1, b1));
- fprintf(f, "d %s ", sprint_time(tc_core_ktime2time(sc->d), b1));
- fprintf(f, "m2 %s ", sprint_rate(sc->m2, b1));
+ print_string(PRINT_FP, NULL, "%s ", name);
+ open_json_object(name);
+ print_rate("m1", "m1 %s ", sc->m1);
+ print_time("d", "d %s ", tc_core_ktime2time(sc->d));
+ print_rate("m2", "m2 %s ", sc->m2);
+ close_json_object();
}
static int
--
2.18.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox