Copyright 2019 The Prometheus Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

package procfs

import (
	
	
	
	
	
	

	
)
A NetSockstat contains the output of /proc/net/sockstat{,6} for IPv4 or IPv6, respectively.
Used is non-nil for IPv4 sockstat results, but nil for IPv6.
A NetSockstatProtocol contains statistics about a given socket protocol. Pointer fields indicate that the value may or may not be present on any given protocol.
NetSockstat retrieves IPv4 socket statistics.
func ( FS) () (*NetSockstat, error) {
	return readSockstat(.proc.Path("net", "sockstat"))
}
NetSockstat6 retrieves IPv6 socket statistics. If IPv6 is disabled on this kernel, the returned error can be checked with os.IsNotExist.
func ( FS) () (*NetSockstat, error) {
	return readSockstat(.proc.Path("net", "sockstat6"))
}
readSockstat opens and parses a NetSockstat from the input file.
This file is small and can be read with one syscall.
	,  := util.ReadFileNoStat()
Do not wrap this error so the caller can detect os.IsNotExist and similar conditions.
		return nil, 
	}

	,  := parseSockstat(bytes.NewReader())
	if  != nil {
		return nil, fmt.Errorf("failed to read sockstats from %q: %v", , )
	}

	return , nil
}
parseSockstat reads the contents of a sockstat file and parses a NetSockstat.
Expect a minimum of a protocol and one key/value pair.
		 := strings.Split(.Text(), " ")
		if len() < 3 {
			return nil, fmt.Errorf("malformed sockstat line: %q", .Text())
		}
The remaining fields are key/value pairs.
		,  := parseSockstatKVs([1:])
		if  != nil {
			return nil, fmt.Errorf("error parsing sockstat key/value pairs from %q: %v", .Text(), )
		}
The first field is the protocol. We must trim its colon suffix.
		 := strings.TrimSuffix([0], ":")
		switch  {
Special case: IPv4 has a sockets "used" key/value pair that we embed at the top level of the structure.
			 := ["used"]
			.Used = &
Parse all other lines as individual protocols.
			 := parseSockstatProtocol()
			.Protocol = 
			.Protocols = append(.Protocols, )
		}
	}

	if  := .Err();  != nil {
		return nil, 
	}

	return &, nil
}
parseSockstatKVs parses a string slice into a map of key/value pairs.
func ( []string) (map[string]int, error) {
	if len()%2 != 0 {
		return nil, errors.New("odd number of fields in key/value pairs")
	}
Iterate two values at a time to gather key/value pairs.
	 := make(map[string]int, len()/2)
	for  := 0;  < len();  += 2 {
		 := util.NewValueParser([+1])
		[[]] = .Int()

		if  := .Err();  != nil {
			return nil, 
		}
	}

	return , nil
}
parseSockstatProtocol parses a NetSockstatProtocol from the input kvs map.
Capture the range variable to ensure we get unique pointers for each of the optional fields.
		 := 
		switch  {
		case "inuse":
			.InUse = 
		case "orphan":
			.Orphan = &
		case "tw":
			.TW = &
		case "alloc":
			.Alloc = &
		case "mem":
			.Mem = &
		case "memory":
			.Memory = &
		}
	}

	return