1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
4 | * operating system. INET is implemented using the BSD Socket |
5 | * interface as the means of communication with the user level. |
6 | * |
7 | * This file implements the various access functions for the |
8 | * PROC file system. It is mainly used for debugging and |
9 | * statistics. |
10 | * |
11 | * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de> |
13 | * Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de> |
14 | * Erik Schoenfelder, <schoenfr@ibr.cs.tu-bs.de> |
15 | * |
16 | * Fixes: |
17 | * Alan Cox : UDP sockets show the rxqueue/txqueue |
18 | * using hint flag for the netinfo. |
19 | * Pauline Middelink : identd support |
20 | * Alan Cox : Make /proc safer. |
21 | * Erik Schoenfelder : /proc/net/snmp |
22 | * Alan Cox : Handle dead sockets properly. |
23 | * Gerhard Koerting : Show both timers |
24 | * Alan Cox : Allow inode to be NULL (kernel socket) |
25 | * Andi Kleen : Add support for open_requests and |
26 | * split functions for more readibility. |
27 | * Andi Kleen : Add support for /proc/net/netstat |
28 | * Arnaldo C. Melo : Convert to seq_file |
29 | */ |
30 | #include <linux/types.h> |
31 | #include <net/net_namespace.h> |
32 | #include <net/icmp.h> |
33 | #include <net/protocol.h> |
34 | #include <net/tcp.h> |
35 | #include <net/mptcp.h> |
36 | #include <net/proto_memory.h> |
37 | #include <net/udp.h> |
38 | #include <net/udplite.h> |
39 | #include <linux/bottom_half.h> |
40 | #include <linux/inetdevice.h> |
41 | #include <linux/proc_fs.h> |
42 | #include <linux/seq_file.h> |
43 | #include <linux/export.h> |
44 | #include <net/sock.h> |
45 | #include <net/raw.h> |
46 | |
47 | #define TCPUDP_MIB_MAX MAX_T(u32, UDP_MIB_MAX, TCP_MIB_MAX) |
48 | |
49 | /* |
50 | * Report socket allocation statistics [mea@utu.fi] |
51 | */ |
52 | static int sockstat_seq_show(struct seq_file *seq, void *v) |
53 | { |
54 | struct net *net = seq->private; |
55 | int orphans, sockets; |
56 | |
57 | orphans = tcp_orphan_count_sum(); |
58 | sockets = proto_sockets_allocated_sum_positive(prot: &tcp_prot); |
59 | |
60 | socket_seq_show(seq); |
61 | seq_printf(m: seq, fmt: "TCP: inuse %d orphan %d tw %d alloc %d mem %ld\n" , |
62 | sock_prot_inuse_get(net, proto: &tcp_prot), orphans, |
63 | refcount_read(r: &net->ipv4.tcp_death_row.tw_refcount) - 1, |
64 | sockets, proto_memory_allocated(prot: &tcp_prot)); |
65 | seq_printf(m: seq, fmt: "UDP: inuse %d mem %ld\n" , |
66 | sock_prot_inuse_get(net, proto: &udp_prot), |
67 | proto_memory_allocated(prot: &udp_prot)); |
68 | seq_printf(m: seq, fmt: "UDPLITE: inuse %d\n" , |
69 | sock_prot_inuse_get(net, proto: &udplite_prot)); |
70 | seq_printf(m: seq, fmt: "RAW: inuse %d\n" , |
71 | sock_prot_inuse_get(net, proto: &raw_prot)); |
72 | seq_printf(m: seq, fmt: "FRAG: inuse %u memory %lu\n" , |
73 | atomic_read(v: &net->ipv4.fqdir->rhashtable.nelems), |
74 | frag_mem_limit(fqdir: net->ipv4.fqdir)); |
75 | return 0; |
76 | } |
77 | |
78 | /* snmp items */ |
79 | static const struct snmp_mib snmp4_ipstats_list[] = { |
80 | SNMP_MIB_ITEM("InReceives" , IPSTATS_MIB_INPKTS), |
81 | SNMP_MIB_ITEM("InHdrErrors" , IPSTATS_MIB_INHDRERRORS), |
82 | SNMP_MIB_ITEM("InAddrErrors" , IPSTATS_MIB_INADDRERRORS), |
83 | SNMP_MIB_ITEM("ForwDatagrams" , IPSTATS_MIB_OUTFORWDATAGRAMS), |
84 | SNMP_MIB_ITEM("InUnknownProtos" , IPSTATS_MIB_INUNKNOWNPROTOS), |
85 | SNMP_MIB_ITEM("InDiscards" , IPSTATS_MIB_INDISCARDS), |
86 | SNMP_MIB_ITEM("InDelivers" , IPSTATS_MIB_INDELIVERS), |
87 | SNMP_MIB_ITEM("OutRequests" , IPSTATS_MIB_OUTREQUESTS), |
88 | SNMP_MIB_ITEM("OutDiscards" , IPSTATS_MIB_OUTDISCARDS), |
89 | SNMP_MIB_ITEM("OutNoRoutes" , IPSTATS_MIB_OUTNOROUTES), |
90 | SNMP_MIB_ITEM("ReasmTimeout" , IPSTATS_MIB_REASMTIMEOUT), |
91 | SNMP_MIB_ITEM("ReasmReqds" , IPSTATS_MIB_REASMREQDS), |
92 | SNMP_MIB_ITEM("ReasmOKs" , IPSTATS_MIB_REASMOKS), |
93 | SNMP_MIB_ITEM("ReasmFails" , IPSTATS_MIB_REASMFAILS), |
94 | SNMP_MIB_ITEM("FragOKs" , IPSTATS_MIB_FRAGOKS), |
95 | SNMP_MIB_ITEM("FragFails" , IPSTATS_MIB_FRAGFAILS), |
96 | SNMP_MIB_ITEM("FragCreates" , IPSTATS_MIB_FRAGCREATES), |
97 | SNMP_MIB_ITEM("OutTransmits" , IPSTATS_MIB_OUTPKTS), |
98 | SNMP_MIB_SENTINEL |
99 | }; |
100 | |
101 | /* Following items are displayed in /proc/net/netstat */ |
102 | static const struct snmp_mib snmp4_ipextstats_list[] = { |
103 | SNMP_MIB_ITEM("InNoRoutes" , IPSTATS_MIB_INNOROUTES), |
104 | SNMP_MIB_ITEM("InTruncatedPkts" , IPSTATS_MIB_INTRUNCATEDPKTS), |
105 | SNMP_MIB_ITEM("InMcastPkts" , IPSTATS_MIB_INMCASTPKTS), |
106 | SNMP_MIB_ITEM("OutMcastPkts" , IPSTATS_MIB_OUTMCASTPKTS), |
107 | SNMP_MIB_ITEM("InBcastPkts" , IPSTATS_MIB_INBCASTPKTS), |
108 | SNMP_MIB_ITEM("OutBcastPkts" , IPSTATS_MIB_OUTBCASTPKTS), |
109 | SNMP_MIB_ITEM("InOctets" , IPSTATS_MIB_INOCTETS), |
110 | SNMP_MIB_ITEM("OutOctets" , IPSTATS_MIB_OUTOCTETS), |
111 | SNMP_MIB_ITEM("InMcastOctets" , IPSTATS_MIB_INMCASTOCTETS), |
112 | SNMP_MIB_ITEM("OutMcastOctets" , IPSTATS_MIB_OUTMCASTOCTETS), |
113 | SNMP_MIB_ITEM("InBcastOctets" , IPSTATS_MIB_INBCASTOCTETS), |
114 | SNMP_MIB_ITEM("OutBcastOctets" , IPSTATS_MIB_OUTBCASTOCTETS), |
115 | /* Non RFC4293 fields */ |
116 | SNMP_MIB_ITEM("InCsumErrors" , IPSTATS_MIB_CSUMERRORS), |
117 | SNMP_MIB_ITEM("InNoECTPkts" , IPSTATS_MIB_NOECTPKTS), |
118 | SNMP_MIB_ITEM("InECT1Pkts" , IPSTATS_MIB_ECT1PKTS), |
119 | SNMP_MIB_ITEM("InECT0Pkts" , IPSTATS_MIB_ECT0PKTS), |
120 | SNMP_MIB_ITEM("InCEPkts" , IPSTATS_MIB_CEPKTS), |
121 | SNMP_MIB_ITEM("ReasmOverlaps" , IPSTATS_MIB_REASM_OVERLAPS), |
122 | SNMP_MIB_SENTINEL |
123 | }; |
124 | |
125 | static const struct { |
126 | const char *name; |
127 | int index; |
128 | } icmpmibmap[] = { |
129 | { "DestUnreachs" , ICMP_DEST_UNREACH }, |
130 | { "TimeExcds" , ICMP_TIME_EXCEEDED }, |
131 | { "ParmProbs" , ICMP_PARAMETERPROB }, |
132 | { "SrcQuenchs" , ICMP_SOURCE_QUENCH }, |
133 | { "Redirects" , ICMP_REDIRECT }, |
134 | { "Echos" , ICMP_ECHO }, |
135 | { "EchoReps" , ICMP_ECHOREPLY }, |
136 | { "Timestamps" , ICMP_TIMESTAMP }, |
137 | { "TimestampReps" , ICMP_TIMESTAMPREPLY }, |
138 | { "AddrMasks" , ICMP_ADDRESS }, |
139 | { "AddrMaskReps" , ICMP_ADDRESSREPLY }, |
140 | { NULL, 0 } |
141 | }; |
142 | |
143 | |
144 | static const struct snmp_mib snmp4_tcp_list[] = { |
145 | SNMP_MIB_ITEM("RtoAlgorithm" , TCP_MIB_RTOALGORITHM), |
146 | SNMP_MIB_ITEM("RtoMin" , TCP_MIB_RTOMIN), |
147 | SNMP_MIB_ITEM("RtoMax" , TCP_MIB_RTOMAX), |
148 | SNMP_MIB_ITEM("MaxConn" , TCP_MIB_MAXCONN), |
149 | SNMP_MIB_ITEM("ActiveOpens" , TCP_MIB_ACTIVEOPENS), |
150 | SNMP_MIB_ITEM("PassiveOpens" , TCP_MIB_PASSIVEOPENS), |
151 | SNMP_MIB_ITEM("AttemptFails" , TCP_MIB_ATTEMPTFAILS), |
152 | SNMP_MIB_ITEM("EstabResets" , TCP_MIB_ESTABRESETS), |
153 | SNMP_MIB_ITEM("CurrEstab" , TCP_MIB_CURRESTAB), |
154 | SNMP_MIB_ITEM("InSegs" , TCP_MIB_INSEGS), |
155 | SNMP_MIB_ITEM("OutSegs" , TCP_MIB_OUTSEGS), |
156 | SNMP_MIB_ITEM("RetransSegs" , TCP_MIB_RETRANSSEGS), |
157 | SNMP_MIB_ITEM("InErrs" , TCP_MIB_INERRS), |
158 | SNMP_MIB_ITEM("OutRsts" , TCP_MIB_OUTRSTS), |
159 | SNMP_MIB_ITEM("InCsumErrors" , TCP_MIB_CSUMERRORS), |
160 | SNMP_MIB_SENTINEL |
161 | }; |
162 | |
163 | static const struct snmp_mib snmp4_udp_list[] = { |
164 | SNMP_MIB_ITEM("InDatagrams" , UDP_MIB_INDATAGRAMS), |
165 | SNMP_MIB_ITEM("NoPorts" , UDP_MIB_NOPORTS), |
166 | SNMP_MIB_ITEM("InErrors" , UDP_MIB_INERRORS), |
167 | SNMP_MIB_ITEM("OutDatagrams" , UDP_MIB_OUTDATAGRAMS), |
168 | SNMP_MIB_ITEM("RcvbufErrors" , UDP_MIB_RCVBUFERRORS), |
169 | SNMP_MIB_ITEM("SndbufErrors" , UDP_MIB_SNDBUFERRORS), |
170 | SNMP_MIB_ITEM("InCsumErrors" , UDP_MIB_CSUMERRORS), |
171 | SNMP_MIB_ITEM("IgnoredMulti" , UDP_MIB_IGNOREDMULTI), |
172 | SNMP_MIB_ITEM("MemErrors" , UDP_MIB_MEMERRORS), |
173 | SNMP_MIB_SENTINEL |
174 | }; |
175 | |
176 | static const struct snmp_mib snmp4_net_list[] = { |
177 | SNMP_MIB_ITEM("SyncookiesSent" , LINUX_MIB_SYNCOOKIESSENT), |
178 | SNMP_MIB_ITEM("SyncookiesRecv" , LINUX_MIB_SYNCOOKIESRECV), |
179 | SNMP_MIB_ITEM("SyncookiesFailed" , LINUX_MIB_SYNCOOKIESFAILED), |
180 | SNMP_MIB_ITEM("EmbryonicRsts" , LINUX_MIB_EMBRYONICRSTS), |
181 | SNMP_MIB_ITEM("PruneCalled" , LINUX_MIB_PRUNECALLED), |
182 | SNMP_MIB_ITEM("RcvPruned" , LINUX_MIB_RCVPRUNED), |
183 | SNMP_MIB_ITEM("OfoPruned" , LINUX_MIB_OFOPRUNED), |
184 | SNMP_MIB_ITEM("OutOfWindowIcmps" , LINUX_MIB_OUTOFWINDOWICMPS), |
185 | SNMP_MIB_ITEM("LockDroppedIcmps" , LINUX_MIB_LOCKDROPPEDICMPS), |
186 | SNMP_MIB_ITEM("ArpFilter" , LINUX_MIB_ARPFILTER), |
187 | SNMP_MIB_ITEM("TW" , LINUX_MIB_TIMEWAITED), |
188 | SNMP_MIB_ITEM("TWRecycled" , LINUX_MIB_TIMEWAITRECYCLED), |
189 | SNMP_MIB_ITEM("TWKilled" , LINUX_MIB_TIMEWAITKILLED), |
190 | SNMP_MIB_ITEM("PAWSActive" , LINUX_MIB_PAWSACTIVEREJECTED), |
191 | SNMP_MIB_ITEM("PAWSEstab" , LINUX_MIB_PAWSESTABREJECTED), |
192 | SNMP_MIB_ITEM("TSEcrRejected" , LINUX_MIB_TSECRREJECTED), |
193 | SNMP_MIB_ITEM("PAWSOldAck" , LINUX_MIB_PAWS_OLD_ACK), |
194 | SNMP_MIB_ITEM("PAWSTimewait" , LINUX_MIB_PAWS_TW_REJECTED), |
195 | SNMP_MIB_ITEM("DelayedACKs" , LINUX_MIB_DELAYEDACKS), |
196 | SNMP_MIB_ITEM("DelayedACKLocked" , LINUX_MIB_DELAYEDACKLOCKED), |
197 | SNMP_MIB_ITEM("DelayedACKLost" , LINUX_MIB_DELAYEDACKLOST), |
198 | SNMP_MIB_ITEM("ListenOverflows" , LINUX_MIB_LISTENOVERFLOWS), |
199 | SNMP_MIB_ITEM("ListenDrops" , LINUX_MIB_LISTENDROPS), |
200 | SNMP_MIB_ITEM("TCPHPHits" , LINUX_MIB_TCPHPHITS), |
201 | SNMP_MIB_ITEM("TCPPureAcks" , LINUX_MIB_TCPPUREACKS), |
202 | SNMP_MIB_ITEM("TCPHPAcks" , LINUX_MIB_TCPHPACKS), |
203 | SNMP_MIB_ITEM("TCPRenoRecovery" , LINUX_MIB_TCPRENORECOVERY), |
204 | SNMP_MIB_ITEM("TCPSackRecovery" , LINUX_MIB_TCPSACKRECOVERY), |
205 | SNMP_MIB_ITEM("TCPSACKReneging" , LINUX_MIB_TCPSACKRENEGING), |
206 | SNMP_MIB_ITEM("TCPSACKReorder" , LINUX_MIB_TCPSACKREORDER), |
207 | SNMP_MIB_ITEM("TCPRenoReorder" , LINUX_MIB_TCPRENOREORDER), |
208 | SNMP_MIB_ITEM("TCPTSReorder" , LINUX_MIB_TCPTSREORDER), |
209 | SNMP_MIB_ITEM("TCPFullUndo" , LINUX_MIB_TCPFULLUNDO), |
210 | SNMP_MIB_ITEM("TCPPartialUndo" , LINUX_MIB_TCPPARTIALUNDO), |
211 | SNMP_MIB_ITEM("TCPDSACKUndo" , LINUX_MIB_TCPDSACKUNDO), |
212 | SNMP_MIB_ITEM("TCPLossUndo" , LINUX_MIB_TCPLOSSUNDO), |
213 | SNMP_MIB_ITEM("TCPLostRetransmit" , LINUX_MIB_TCPLOSTRETRANSMIT), |
214 | SNMP_MIB_ITEM("TCPRenoFailures" , LINUX_MIB_TCPRENOFAILURES), |
215 | SNMP_MIB_ITEM("TCPSackFailures" , LINUX_MIB_TCPSACKFAILURES), |
216 | SNMP_MIB_ITEM("TCPLossFailures" , LINUX_MIB_TCPLOSSFAILURES), |
217 | SNMP_MIB_ITEM("TCPFastRetrans" , LINUX_MIB_TCPFASTRETRANS), |
218 | SNMP_MIB_ITEM("TCPSlowStartRetrans" , LINUX_MIB_TCPSLOWSTARTRETRANS), |
219 | SNMP_MIB_ITEM("TCPTimeouts" , LINUX_MIB_TCPTIMEOUTS), |
220 | SNMP_MIB_ITEM("TCPLossProbes" , LINUX_MIB_TCPLOSSPROBES), |
221 | SNMP_MIB_ITEM("TCPLossProbeRecovery" , LINUX_MIB_TCPLOSSPROBERECOVERY), |
222 | SNMP_MIB_ITEM("TCPRenoRecoveryFail" , LINUX_MIB_TCPRENORECOVERYFAIL), |
223 | SNMP_MIB_ITEM("TCPSackRecoveryFail" , LINUX_MIB_TCPSACKRECOVERYFAIL), |
224 | SNMP_MIB_ITEM("TCPRcvCollapsed" , LINUX_MIB_TCPRCVCOLLAPSED), |
225 | SNMP_MIB_ITEM("TCPBacklogCoalesce" , LINUX_MIB_TCPBACKLOGCOALESCE), |
226 | SNMP_MIB_ITEM("TCPDSACKOldSent" , LINUX_MIB_TCPDSACKOLDSENT), |
227 | SNMP_MIB_ITEM("TCPDSACKOfoSent" , LINUX_MIB_TCPDSACKOFOSENT), |
228 | SNMP_MIB_ITEM("TCPDSACKRecv" , LINUX_MIB_TCPDSACKRECV), |
229 | SNMP_MIB_ITEM("TCPDSACKOfoRecv" , LINUX_MIB_TCPDSACKOFORECV), |
230 | SNMP_MIB_ITEM("TCPAbortOnData" , LINUX_MIB_TCPABORTONDATA), |
231 | SNMP_MIB_ITEM("TCPAbortOnClose" , LINUX_MIB_TCPABORTONCLOSE), |
232 | SNMP_MIB_ITEM("TCPAbortOnMemory" , LINUX_MIB_TCPABORTONMEMORY), |
233 | SNMP_MIB_ITEM("TCPAbortOnTimeout" , LINUX_MIB_TCPABORTONTIMEOUT), |
234 | SNMP_MIB_ITEM("TCPAbortOnLinger" , LINUX_MIB_TCPABORTONLINGER), |
235 | SNMP_MIB_ITEM("TCPAbortFailed" , LINUX_MIB_TCPABORTFAILED), |
236 | SNMP_MIB_ITEM("TCPMemoryPressures" , LINUX_MIB_TCPMEMORYPRESSURES), |
237 | SNMP_MIB_ITEM("TCPMemoryPressuresChrono" , LINUX_MIB_TCPMEMORYPRESSURESCHRONO), |
238 | SNMP_MIB_ITEM("TCPSACKDiscard" , LINUX_MIB_TCPSACKDISCARD), |
239 | SNMP_MIB_ITEM("TCPDSACKIgnoredOld" , LINUX_MIB_TCPDSACKIGNOREDOLD), |
240 | SNMP_MIB_ITEM("TCPDSACKIgnoredNoUndo" , LINUX_MIB_TCPDSACKIGNOREDNOUNDO), |
241 | SNMP_MIB_ITEM("TCPSpuriousRTOs" , LINUX_MIB_TCPSPURIOUSRTOS), |
242 | SNMP_MIB_ITEM("TCPMD5NotFound" , LINUX_MIB_TCPMD5NOTFOUND), |
243 | SNMP_MIB_ITEM("TCPMD5Unexpected" , LINUX_MIB_TCPMD5UNEXPECTED), |
244 | SNMP_MIB_ITEM("TCPMD5Failure" , LINUX_MIB_TCPMD5FAILURE), |
245 | SNMP_MIB_ITEM("TCPSackShifted" , LINUX_MIB_SACKSHIFTED), |
246 | SNMP_MIB_ITEM("TCPSackMerged" , LINUX_MIB_SACKMERGED), |
247 | SNMP_MIB_ITEM("TCPSackShiftFallback" , LINUX_MIB_SACKSHIFTFALLBACK), |
248 | SNMP_MIB_ITEM("TCPBacklogDrop" , LINUX_MIB_TCPBACKLOGDROP), |
249 | SNMP_MIB_ITEM("PFMemallocDrop" , LINUX_MIB_PFMEMALLOCDROP), |
250 | SNMP_MIB_ITEM("TCPMinTTLDrop" , LINUX_MIB_TCPMINTTLDROP), |
251 | SNMP_MIB_ITEM("TCPDeferAcceptDrop" , LINUX_MIB_TCPDEFERACCEPTDROP), |
252 | SNMP_MIB_ITEM("IPReversePathFilter" , LINUX_MIB_IPRPFILTER), |
253 | SNMP_MIB_ITEM("TCPTimeWaitOverflow" , LINUX_MIB_TCPTIMEWAITOVERFLOW), |
254 | SNMP_MIB_ITEM("TCPReqQFullDoCookies" , LINUX_MIB_TCPREQQFULLDOCOOKIES), |
255 | SNMP_MIB_ITEM("TCPReqQFullDrop" , LINUX_MIB_TCPREQQFULLDROP), |
256 | SNMP_MIB_ITEM("TCPRetransFail" , LINUX_MIB_TCPRETRANSFAIL), |
257 | SNMP_MIB_ITEM("TCPRcvCoalesce" , LINUX_MIB_TCPRCVCOALESCE), |
258 | SNMP_MIB_ITEM("TCPOFOQueue" , LINUX_MIB_TCPOFOQUEUE), |
259 | SNMP_MIB_ITEM("TCPOFODrop" , LINUX_MIB_TCPOFODROP), |
260 | SNMP_MIB_ITEM("TCPOFOMerge" , LINUX_MIB_TCPOFOMERGE), |
261 | SNMP_MIB_ITEM("TCPChallengeACK" , LINUX_MIB_TCPCHALLENGEACK), |
262 | SNMP_MIB_ITEM("TCPSYNChallenge" , LINUX_MIB_TCPSYNCHALLENGE), |
263 | SNMP_MIB_ITEM("TCPFastOpenActive" , LINUX_MIB_TCPFASTOPENACTIVE), |
264 | SNMP_MIB_ITEM("TCPFastOpenActiveFail" , LINUX_MIB_TCPFASTOPENACTIVEFAIL), |
265 | SNMP_MIB_ITEM("TCPFastOpenPassive" , LINUX_MIB_TCPFASTOPENPASSIVE), |
266 | SNMP_MIB_ITEM("TCPFastOpenPassiveFail" , LINUX_MIB_TCPFASTOPENPASSIVEFAIL), |
267 | SNMP_MIB_ITEM("TCPFastOpenListenOverflow" , LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), |
268 | SNMP_MIB_ITEM("TCPFastOpenCookieReqd" , LINUX_MIB_TCPFASTOPENCOOKIEREQD), |
269 | SNMP_MIB_ITEM("TCPFastOpenBlackhole" , LINUX_MIB_TCPFASTOPENBLACKHOLE), |
270 | SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues" , LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES), |
271 | SNMP_MIB_ITEM("BusyPollRxPackets" , LINUX_MIB_BUSYPOLLRXPACKETS), |
272 | SNMP_MIB_ITEM("TCPAutoCorking" , LINUX_MIB_TCPAUTOCORKING), |
273 | SNMP_MIB_ITEM("TCPFromZeroWindowAdv" , LINUX_MIB_TCPFROMZEROWINDOWADV), |
274 | SNMP_MIB_ITEM("TCPToZeroWindowAdv" , LINUX_MIB_TCPTOZEROWINDOWADV), |
275 | SNMP_MIB_ITEM("TCPWantZeroWindowAdv" , LINUX_MIB_TCPWANTZEROWINDOWADV), |
276 | SNMP_MIB_ITEM("TCPSynRetrans" , LINUX_MIB_TCPSYNRETRANS), |
277 | SNMP_MIB_ITEM("TCPOrigDataSent" , LINUX_MIB_TCPORIGDATASENT), |
278 | SNMP_MIB_ITEM("TCPHystartTrainDetect" , LINUX_MIB_TCPHYSTARTTRAINDETECT), |
279 | SNMP_MIB_ITEM("TCPHystartTrainCwnd" , LINUX_MIB_TCPHYSTARTTRAINCWND), |
280 | SNMP_MIB_ITEM("TCPHystartDelayDetect" , LINUX_MIB_TCPHYSTARTDELAYDETECT), |
281 | SNMP_MIB_ITEM("TCPHystartDelayCwnd" , LINUX_MIB_TCPHYSTARTDELAYCWND), |
282 | SNMP_MIB_ITEM("TCPACKSkippedSynRecv" , LINUX_MIB_TCPACKSKIPPEDSYNRECV), |
283 | SNMP_MIB_ITEM("TCPACKSkippedPAWS" , LINUX_MIB_TCPACKSKIPPEDPAWS), |
284 | SNMP_MIB_ITEM("TCPACKSkippedSeq" , LINUX_MIB_TCPACKSKIPPEDSEQ), |
285 | SNMP_MIB_ITEM("TCPACKSkippedFinWait2" , LINUX_MIB_TCPACKSKIPPEDFINWAIT2), |
286 | SNMP_MIB_ITEM("TCPACKSkippedTimeWait" , LINUX_MIB_TCPACKSKIPPEDTIMEWAIT), |
287 | SNMP_MIB_ITEM("TCPACKSkippedChallenge" , LINUX_MIB_TCPACKSKIPPEDCHALLENGE), |
288 | SNMP_MIB_ITEM("TCPWinProbe" , LINUX_MIB_TCPWINPROBE), |
289 | SNMP_MIB_ITEM("TCPKeepAlive" , LINUX_MIB_TCPKEEPALIVE), |
290 | SNMP_MIB_ITEM("TCPMTUPFail" , LINUX_MIB_TCPMTUPFAIL), |
291 | SNMP_MIB_ITEM("TCPMTUPSuccess" , LINUX_MIB_TCPMTUPSUCCESS), |
292 | SNMP_MIB_ITEM("TCPDelivered" , LINUX_MIB_TCPDELIVERED), |
293 | SNMP_MIB_ITEM("TCPDeliveredCE" , LINUX_MIB_TCPDELIVEREDCE), |
294 | SNMP_MIB_ITEM("TCPAckCompressed" , LINUX_MIB_TCPACKCOMPRESSED), |
295 | SNMP_MIB_ITEM("TCPZeroWindowDrop" , LINUX_MIB_TCPZEROWINDOWDROP), |
296 | SNMP_MIB_ITEM("TCPRcvQDrop" , LINUX_MIB_TCPRCVQDROP), |
297 | SNMP_MIB_ITEM("TCPWqueueTooBig" , LINUX_MIB_TCPWQUEUETOOBIG), |
298 | SNMP_MIB_ITEM("TCPFastOpenPassiveAltKey" , LINUX_MIB_TCPFASTOPENPASSIVEALTKEY), |
299 | SNMP_MIB_ITEM("TcpTimeoutRehash" , LINUX_MIB_TCPTIMEOUTREHASH), |
300 | SNMP_MIB_ITEM("TcpDuplicateDataRehash" , LINUX_MIB_TCPDUPLICATEDATAREHASH), |
301 | SNMP_MIB_ITEM("TCPDSACKRecvSegs" , LINUX_MIB_TCPDSACKRECVSEGS), |
302 | SNMP_MIB_ITEM("TCPDSACKIgnoredDubious" , LINUX_MIB_TCPDSACKIGNOREDDUBIOUS), |
303 | SNMP_MIB_ITEM("TCPMigrateReqSuccess" , LINUX_MIB_TCPMIGRATEREQSUCCESS), |
304 | SNMP_MIB_ITEM("TCPMigrateReqFailure" , LINUX_MIB_TCPMIGRATEREQFAILURE), |
305 | SNMP_MIB_ITEM("TCPPLBRehash" , LINUX_MIB_TCPPLBREHASH), |
306 | SNMP_MIB_ITEM("TCPAORequired" , LINUX_MIB_TCPAOREQUIRED), |
307 | SNMP_MIB_ITEM("TCPAOBad" , LINUX_MIB_TCPAOBAD), |
308 | SNMP_MIB_ITEM("TCPAOKeyNotFound" , LINUX_MIB_TCPAOKEYNOTFOUND), |
309 | SNMP_MIB_ITEM("TCPAOGood" , LINUX_MIB_TCPAOGOOD), |
310 | SNMP_MIB_ITEM("TCPAODroppedIcmps" , LINUX_MIB_TCPAODROPPEDICMPS), |
311 | SNMP_MIB_SENTINEL |
312 | }; |
313 | |
314 | static void icmpmsg_put_line(struct seq_file *seq, unsigned long *vals, |
315 | unsigned short *type, int count) |
316 | { |
317 | int j; |
318 | |
319 | if (count) { |
320 | seq_puts(m: seq, s: "\nIcmpMsg:" ); |
321 | for (j = 0; j < count; ++j) |
322 | seq_printf(m: seq, fmt: " %sType%u" , |
323 | type[j] & 0x100 ? "Out" : "In" , |
324 | type[j] & 0xff); |
325 | seq_puts(m: seq, s: "\nIcmpMsg:" ); |
326 | for (j = 0; j < count; ++j) |
327 | seq_printf(m: seq, fmt: " %lu" , vals[j]); |
328 | } |
329 | } |
330 | |
331 | static void icmpmsg_put(struct seq_file *seq) |
332 | { |
333 | #define PERLINE 16 |
334 | |
335 | int i, count; |
336 | unsigned short type[PERLINE]; |
337 | unsigned long vals[PERLINE], val; |
338 | struct net *net = seq->private; |
339 | |
340 | count = 0; |
341 | for (i = 0; i < ICMPMSG_MIB_MAX; i++) { |
342 | val = atomic_long_read(v: &net->mib.icmpmsg_statistics->mibs[i]); |
343 | if (val) { |
344 | type[count] = i; |
345 | vals[count++] = val; |
346 | } |
347 | if (count == PERLINE) { |
348 | icmpmsg_put_line(seq, vals, type, count); |
349 | count = 0; |
350 | } |
351 | } |
352 | icmpmsg_put_line(seq, vals, type, count); |
353 | |
354 | #undef PERLINE |
355 | } |
356 | |
357 | static void icmp_put(struct seq_file *seq) |
358 | { |
359 | int i; |
360 | struct net *net = seq->private; |
361 | atomic_long_t *ptr = net->mib.icmpmsg_statistics->mibs; |
362 | |
363 | seq_puts(m: seq, s: "\nIcmp: InMsgs InErrors InCsumErrors" ); |
364 | for (i = 0; icmpmibmap[i].name; i++) |
365 | seq_printf(m: seq, fmt: " In%s" , icmpmibmap[i].name); |
366 | seq_puts(m: seq, s: " OutMsgs OutErrors OutRateLimitGlobal OutRateLimitHost" ); |
367 | for (i = 0; icmpmibmap[i].name; i++) |
368 | seq_printf(m: seq, fmt: " Out%s" , icmpmibmap[i].name); |
369 | seq_printf(m: seq, fmt: "\nIcmp: %lu %lu %lu" , |
370 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_INMSGS), |
371 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_INERRORS), |
372 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_CSUMERRORS)); |
373 | for (i = 0; icmpmibmap[i].name; i++) |
374 | seq_printf(m: seq, fmt: " %lu" , |
375 | atomic_long_read(v: ptr + icmpmibmap[i].index)); |
376 | seq_printf(m: seq, fmt: " %lu %lu %lu %lu" , |
377 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_OUTMSGS), |
378 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_OUTERRORS), |
379 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_RATELIMITGLOBAL), |
380 | snmp_fold_field(mib: net->mib.icmp_statistics, offt: ICMP_MIB_RATELIMITHOST)); |
381 | for (i = 0; icmpmibmap[i].name; i++) |
382 | seq_printf(m: seq, fmt: " %lu" , |
383 | atomic_long_read(v: ptr + (icmpmibmap[i].index | 0x100))); |
384 | } |
385 | |
386 | /* |
387 | * Called from the PROCfs module. This outputs /proc/net/snmp. |
388 | */ |
389 | static int snmp_seq_show_ipstats(struct seq_file *seq, void *v) |
390 | { |
391 | struct net *net = seq->private; |
392 | u64 buff64[IPSTATS_MIB_MAX]; |
393 | int i; |
394 | |
395 | memset(buff64, 0, IPSTATS_MIB_MAX * sizeof(u64)); |
396 | |
397 | seq_puts(m: seq, s: "Ip: Forwarding DefaultTTL" ); |
398 | for (i = 0; snmp4_ipstats_list[i].name; i++) |
399 | seq_printf(m: seq, fmt: " %s" , snmp4_ipstats_list[i].name); |
400 | |
401 | seq_printf(m: seq, fmt: "\nIp: %d %d" , |
402 | IPV4_DEVCONF_ALL_RO(net, FORWARDING) ? 1 : 2, |
403 | READ_ONCE(net->ipv4.sysctl_ip_default_ttl)); |
404 | |
405 | BUILD_BUG_ON(offsetof(struct ipstats_mib, mibs) != 0); |
406 | snmp_get_cpu_field64_batch(buff64, snmp4_ipstats_list, |
407 | net->mib.ip_statistics, |
408 | offsetof(struct ipstats_mib, syncp)); |
409 | for (i = 0; snmp4_ipstats_list[i].name; i++) |
410 | seq_printf(m: seq, fmt: " %llu" , buff64[i]); |
411 | |
412 | return 0; |
413 | } |
414 | |
415 | static int snmp_seq_show_tcp_udp(struct seq_file *seq, void *v) |
416 | { |
417 | unsigned long buff[TCPUDP_MIB_MAX]; |
418 | struct net *net = seq->private; |
419 | int i; |
420 | |
421 | memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); |
422 | |
423 | seq_puts(m: seq, s: "\nTcp:" ); |
424 | for (i = 0; snmp4_tcp_list[i].name; i++) |
425 | seq_printf(m: seq, fmt: " %s" , snmp4_tcp_list[i].name); |
426 | |
427 | seq_puts(m: seq, s: "\nTcp:" ); |
428 | snmp_get_cpu_field_batch(buff, snmp4_tcp_list, |
429 | net->mib.tcp_statistics); |
430 | for (i = 0; snmp4_tcp_list[i].name; i++) { |
431 | /* MaxConn field is signed, RFC 2012 */ |
432 | if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN) |
433 | seq_printf(m: seq, fmt: " %ld" , buff[i]); |
434 | else |
435 | seq_printf(m: seq, fmt: " %lu" , buff[i]); |
436 | } |
437 | |
438 | memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); |
439 | |
440 | snmp_get_cpu_field_batch(buff, snmp4_udp_list, |
441 | net->mib.udp_statistics); |
442 | seq_puts(m: seq, s: "\nUdp:" ); |
443 | for (i = 0; snmp4_udp_list[i].name; i++) |
444 | seq_printf(m: seq, fmt: " %s" , snmp4_udp_list[i].name); |
445 | seq_puts(m: seq, s: "\nUdp:" ); |
446 | for (i = 0; snmp4_udp_list[i].name; i++) |
447 | seq_printf(m: seq, fmt: " %lu" , buff[i]); |
448 | |
449 | memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); |
450 | |
451 | /* the UDP and UDP-Lite MIBs are the same */ |
452 | seq_puts(m: seq, s: "\nUdpLite:" ); |
453 | snmp_get_cpu_field_batch(buff, snmp4_udp_list, |
454 | net->mib.udplite_statistics); |
455 | for (i = 0; snmp4_udp_list[i].name; i++) |
456 | seq_printf(m: seq, fmt: " %s" , snmp4_udp_list[i].name); |
457 | seq_puts(m: seq, s: "\nUdpLite:" ); |
458 | for (i = 0; snmp4_udp_list[i].name; i++) |
459 | seq_printf(m: seq, fmt: " %lu" , buff[i]); |
460 | |
461 | seq_putc(m: seq, c: '\n'); |
462 | return 0; |
463 | } |
464 | |
465 | static int snmp_seq_show(struct seq_file *seq, void *v) |
466 | { |
467 | snmp_seq_show_ipstats(seq, v); |
468 | |
469 | icmp_put(seq); /* RFC 2011 compatibility */ |
470 | icmpmsg_put(seq); |
471 | |
472 | snmp_seq_show_tcp_udp(seq, v); |
473 | |
474 | return 0; |
475 | } |
476 | |
477 | /* |
478 | * Output /proc/net/netstat |
479 | */ |
480 | static int netstat_seq_show(struct seq_file *seq, void *v) |
481 | { |
482 | const int ip_cnt = ARRAY_SIZE(snmp4_ipextstats_list) - 1; |
483 | const int tcp_cnt = ARRAY_SIZE(snmp4_net_list) - 1; |
484 | struct net *net = seq->private; |
485 | unsigned long *buff; |
486 | int i; |
487 | |
488 | seq_puts(m: seq, s: "TcpExt:" ); |
489 | for (i = 0; i < tcp_cnt; i++) |
490 | seq_printf(m: seq, fmt: " %s" , snmp4_net_list[i].name); |
491 | |
492 | seq_puts(m: seq, s: "\nTcpExt:" ); |
493 | buff = kzalloc(max(tcp_cnt * sizeof(long), ip_cnt * sizeof(u64)), |
494 | GFP_KERNEL); |
495 | if (buff) { |
496 | snmp_get_cpu_field_batch(buff, snmp4_net_list, |
497 | net->mib.net_statistics); |
498 | for (i = 0; i < tcp_cnt; i++) |
499 | seq_printf(m: seq, fmt: " %lu" , buff[i]); |
500 | } else { |
501 | for (i = 0; i < tcp_cnt; i++) |
502 | seq_printf(m: seq, fmt: " %lu" , |
503 | snmp_fold_field(mib: net->mib.net_statistics, |
504 | offt: snmp4_net_list[i].entry)); |
505 | } |
506 | seq_puts(m: seq, s: "\nIpExt:" ); |
507 | for (i = 0; i < ip_cnt; i++) |
508 | seq_printf(m: seq, fmt: " %s" , snmp4_ipextstats_list[i].name); |
509 | |
510 | seq_puts(m: seq, s: "\nIpExt:" ); |
511 | if (buff) { |
512 | u64 *buff64 = (u64 *)buff; |
513 | |
514 | memset(buff64, 0, ip_cnt * sizeof(u64)); |
515 | snmp_get_cpu_field64_batch(buff64, snmp4_ipextstats_list, |
516 | net->mib.ip_statistics, |
517 | offsetof(struct ipstats_mib, syncp)); |
518 | for (i = 0; i < ip_cnt; i++) |
519 | seq_printf(m: seq, fmt: " %llu" , buff64[i]); |
520 | } else { |
521 | for (i = 0; i < ip_cnt; i++) |
522 | seq_printf(m: seq, fmt: " %llu" , |
523 | snmp_fold_field64(mib: net->mib.ip_statistics, |
524 | offt: snmp4_ipextstats_list[i].entry, |
525 | offsetof(struct ipstats_mib, syncp))); |
526 | } |
527 | kfree(objp: buff); |
528 | seq_putc(m: seq, c: '\n'); |
529 | mptcp_seq_show(seq); |
530 | return 0; |
531 | } |
532 | |
533 | static __net_init int ip_proc_init_net(struct net *net) |
534 | { |
535 | if (!proc_create_net_single(name: "sockstat" , mode: 0444, parent: net->proc_net, |
536 | show: sockstat_seq_show, NULL)) |
537 | goto out_sockstat; |
538 | if (!proc_create_net_single(name: "netstat" , mode: 0444, parent: net->proc_net, |
539 | show: netstat_seq_show, NULL)) |
540 | goto out_netstat; |
541 | if (!proc_create_net_single(name: "snmp" , mode: 0444, parent: net->proc_net, show: snmp_seq_show, |
542 | NULL)) |
543 | goto out_snmp; |
544 | |
545 | return 0; |
546 | |
547 | out_snmp: |
548 | remove_proc_entry("netstat" , net->proc_net); |
549 | out_netstat: |
550 | remove_proc_entry("sockstat" , net->proc_net); |
551 | out_sockstat: |
552 | return -ENOMEM; |
553 | } |
554 | |
555 | static __net_exit void ip_proc_exit_net(struct net *net) |
556 | { |
557 | remove_proc_entry("snmp" , net->proc_net); |
558 | remove_proc_entry("netstat" , net->proc_net); |
559 | remove_proc_entry("sockstat" , net->proc_net); |
560 | } |
561 | |
562 | static __net_initdata struct pernet_operations ip_proc_ops = { |
563 | .init = ip_proc_init_net, |
564 | .exit = ip_proc_exit_net, |
565 | }; |
566 | |
567 | int __init ip_misc_proc_init(void) |
568 | { |
569 | return register_pernet_subsys(&ip_proc_ops); |
570 | } |
571 | |