162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/seq_file.h>
462306a36Sopenharmony_ci#include <net/ip.h>
562306a36Sopenharmony_ci#include <net/mptcp.h>
662306a36Sopenharmony_ci#include <net/snmp.h>
762306a36Sopenharmony_ci#include <net/net_namespace.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "mib.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistatic const struct snmp_mib mptcp_snmp_list[] = {
1262306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPCapableSYNRX", MPTCP_MIB_MPCAPABLEPASSIVE),
1362306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPCapableSYNTX", MPTCP_MIB_MPCAPABLEACTIVE),
1462306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPCapableSYNACKRX", MPTCP_MIB_MPCAPABLEACTIVEACK),
1562306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPCapableACKRX", MPTCP_MIB_MPCAPABLEPASSIVEACK),
1662306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPCapableFallbackACK", MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK),
1762306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPCapableFallbackSYNACK", MPTCP_MIB_MPCAPABLEACTIVEFALLBACK),
1862306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPFallbackTokenInit", MPTCP_MIB_TOKENFALLBACKINIT),
1962306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPTCPRetrans", MPTCP_MIB_RETRANSSEGS),
2062306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinNoTokenFound", MPTCP_MIB_JOINNOTOKEN),
2162306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinSynRx", MPTCP_MIB_JOINSYNRX),
2262306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinSynAckRx", MPTCP_MIB_JOINSYNACKRX),
2362306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinSynAckHMacFailure", MPTCP_MIB_JOINSYNACKMAC),
2462306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX),
2562306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC),
2662306a36Sopenharmony_ci	SNMP_MIB_ITEM("DSSNotMatching", MPTCP_MIB_DSSNOMATCH),
2762306a36Sopenharmony_ci	SNMP_MIB_ITEM("InfiniteMapTx", MPTCP_MIB_INFINITEMAPTX),
2862306a36Sopenharmony_ci	SNMP_MIB_ITEM("InfiniteMapRx", MPTCP_MIB_INFINITEMAPRX),
2962306a36Sopenharmony_ci	SNMP_MIB_ITEM("DSSNoMatchTCP", MPTCP_MIB_DSSTCPMISMATCH),
3062306a36Sopenharmony_ci	SNMP_MIB_ITEM("DataCsumErr", MPTCP_MIB_DATACSUMERR),
3162306a36Sopenharmony_ci	SNMP_MIB_ITEM("OFOQueueTail", MPTCP_MIB_OFOQUEUETAIL),
3262306a36Sopenharmony_ci	SNMP_MIB_ITEM("OFOQueue", MPTCP_MIB_OFOQUEUE),
3362306a36Sopenharmony_ci	SNMP_MIB_ITEM("OFOMerge", MPTCP_MIB_OFOMERGE),
3462306a36Sopenharmony_ci	SNMP_MIB_ITEM("NoDSSInWindow", MPTCP_MIB_NODSSWINDOW),
3562306a36Sopenharmony_ci	SNMP_MIB_ITEM("DuplicateData", MPTCP_MIB_DUPDATA),
3662306a36Sopenharmony_ci	SNMP_MIB_ITEM("AddAddr", MPTCP_MIB_ADDADDR),
3762306a36Sopenharmony_ci	SNMP_MIB_ITEM("AddAddrTx", MPTCP_MIB_ADDADDRTX),
3862306a36Sopenharmony_ci	SNMP_MIB_ITEM("AddAddrTxDrop", MPTCP_MIB_ADDADDRTXDROP),
3962306a36Sopenharmony_ci	SNMP_MIB_ITEM("EchoAdd", MPTCP_MIB_ECHOADD),
4062306a36Sopenharmony_ci	SNMP_MIB_ITEM("EchoAddTx", MPTCP_MIB_ECHOADDTX),
4162306a36Sopenharmony_ci	SNMP_MIB_ITEM("EchoAddTxDrop", MPTCP_MIB_ECHOADDTXDROP),
4262306a36Sopenharmony_ci	SNMP_MIB_ITEM("PortAdd", MPTCP_MIB_PORTADD),
4362306a36Sopenharmony_ci	SNMP_MIB_ITEM("AddAddrDrop", MPTCP_MIB_ADDADDRDROP),
4462306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinPortSynRx", MPTCP_MIB_JOINPORTSYNRX),
4562306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinPortSynAckRx", MPTCP_MIB_JOINPORTSYNACKRX),
4662306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPJoinPortAckRx", MPTCP_MIB_JOINPORTACKRX),
4762306a36Sopenharmony_ci	SNMP_MIB_ITEM("MismatchPortSynRx", MPTCP_MIB_MISMATCHPORTSYNRX),
4862306a36Sopenharmony_ci	SNMP_MIB_ITEM("MismatchPortAckRx", MPTCP_MIB_MISMATCHPORTACKRX),
4962306a36Sopenharmony_ci	SNMP_MIB_ITEM("RmAddr", MPTCP_MIB_RMADDR),
5062306a36Sopenharmony_ci	SNMP_MIB_ITEM("RmAddrDrop", MPTCP_MIB_RMADDRDROP),
5162306a36Sopenharmony_ci	SNMP_MIB_ITEM("RmAddrTx", MPTCP_MIB_RMADDRTX),
5262306a36Sopenharmony_ci	SNMP_MIB_ITEM("RmAddrTxDrop", MPTCP_MIB_RMADDRTXDROP),
5362306a36Sopenharmony_ci	SNMP_MIB_ITEM("RmSubflow", MPTCP_MIB_RMSUBFLOW),
5462306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPPrioTx", MPTCP_MIB_MPPRIOTX),
5562306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPPrioRx", MPTCP_MIB_MPPRIORX),
5662306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPFailTx", MPTCP_MIB_MPFAILTX),
5762306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPFailRx", MPTCP_MIB_MPFAILRX),
5862306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPFastcloseTx", MPTCP_MIB_MPFASTCLOSETX),
5962306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPFastcloseRx", MPTCP_MIB_MPFASTCLOSERX),
6062306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPRstTx", MPTCP_MIB_MPRSTTX),
6162306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPRstRx", MPTCP_MIB_MPRSTRX),
6262306a36Sopenharmony_ci	SNMP_MIB_ITEM("RcvPruned", MPTCP_MIB_RCVPRUNED),
6362306a36Sopenharmony_ci	SNMP_MIB_ITEM("SubflowStale", MPTCP_MIB_SUBFLOWSTALE),
6462306a36Sopenharmony_ci	SNMP_MIB_ITEM("SubflowRecover", MPTCP_MIB_SUBFLOWRECOVER),
6562306a36Sopenharmony_ci	SNMP_MIB_ITEM("SndWndShared", MPTCP_MIB_SNDWNDSHARED),
6662306a36Sopenharmony_ci	SNMP_MIB_ITEM("RcvWndShared", MPTCP_MIB_RCVWNDSHARED),
6762306a36Sopenharmony_ci	SNMP_MIB_ITEM("RcvWndConflictUpdate", MPTCP_MIB_RCVWNDCONFLICTUPDATE),
6862306a36Sopenharmony_ci	SNMP_MIB_ITEM("RcvWndConflict", MPTCP_MIB_RCVWNDCONFLICT),
6962306a36Sopenharmony_ci	SNMP_MIB_ITEM("MPCurrEstab", MPTCP_MIB_CURRESTAB),
7062306a36Sopenharmony_ci	SNMP_MIB_SENTINEL
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* mptcp_mib_alloc - allocate percpu mib counters
7462306a36Sopenharmony_ci *
7562306a36Sopenharmony_ci * These are allocated when the first mptcp socket is created so
7662306a36Sopenharmony_ci * we do not waste percpu memory if mptcp isn't in use.
7762306a36Sopenharmony_ci */
7862306a36Sopenharmony_cibool mptcp_mib_alloc(struct net *net)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	struct mptcp_mib __percpu *mib = alloc_percpu(struct mptcp_mib);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	if (!mib)
8362306a36Sopenharmony_ci		return false;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	if (cmpxchg(&net->mib.mptcp_statistics, NULL, mib))
8662306a36Sopenharmony_ci		free_percpu(mib);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	return true;
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_civoid mptcp_seq_show(struct seq_file *seq)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	unsigned long sum[ARRAY_SIZE(mptcp_snmp_list) - 1];
9462306a36Sopenharmony_ci	struct net *net = seq->private;
9562306a36Sopenharmony_ci	int i;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	seq_puts(seq, "MPTcpExt:");
9862306a36Sopenharmony_ci	for (i = 0; mptcp_snmp_list[i].name; i++)
9962306a36Sopenharmony_ci		seq_printf(seq, " %s", mptcp_snmp_list[i].name);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	seq_puts(seq, "\nMPTcpExt:");
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	memset(sum, 0, sizeof(sum));
10462306a36Sopenharmony_ci	if (net->mib.mptcp_statistics)
10562306a36Sopenharmony_ci		snmp_get_cpu_field_batch(sum, mptcp_snmp_list,
10662306a36Sopenharmony_ci					 net->mib.mptcp_statistics);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	for (i = 0; mptcp_snmp_list[i].name; i++)
10962306a36Sopenharmony_ci		seq_printf(seq, " %lu", sum[i]);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	seq_putc(seq, '\n');
11262306a36Sopenharmony_ci}
113