-
Notifications
You must be signed in to change notification settings - Fork 616
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
changed method for retrieving Windows network statistics
Currently, we are running a Powershell method (Get-NetAdapterStatistics) to retrieve the network statistics in case of awsvpc network mode. However, this can cause CPU spikes on smaller instance types. Therefore, we are switching the method to use native Win32 API for retrieving the same. GetIfTable2Ex is used for the same. Reference: https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-getiftable2ex In this refactor, we have abstracted the details of Win32 API in a new package which is used in Windows workflow.
- Loading branch information
Harsh Rawat
committed
Oct 12, 2022
1 parent
bd4ecb1
commit 13adf28
Showing
10 changed files
with
295 additions
and
174 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"). You may | ||
// not use this file except in compliance with the License. A copy of the | ||
// License is located at | ||
// | ||
// http://aws.amazon.com/apache2.0/ | ||
// | ||
// or in the "license" file accompanying this file. This file 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 statsretriever | ||
|
||
import dockerstats "github.com/docker/docker/api/types" | ||
|
||
//go:generate mockgen -destination=mock/$GOFILE -copyright_file=../../../scripts/copyright_file github.com/aws/amazon-ecs-agent/agent/stats/statsretriever StatsRetriever | ||
|
||
// StatsRetriever defines methods for retrieving network stats. | ||
type StatsRetriever interface { | ||
// GetNetworkAdapterStatisticsPerContainer returns the network stats for the queried device averaged per container. | ||
GetNetworkAdapterStatisticsPerContainer(int, int) (*dockerstats.NetworkStats, error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"). You may | ||
// not use this file except in compliance with the License. A copy of the | ||
// License is located at | ||
// | ||
// http://aws.amazon.com/apache2.0/ | ||
// | ||
// or in the "license" file accompanying this file. This file 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 statsretriever | ||
|
||
import ( | ||
"syscall" | ||
"unsafe" | ||
|
||
log "github.com/cihub/seelog" | ||
dockerstats "github.com/docker/docker/api/types" | ||
"github.com/pkg/errors" | ||
"golang.org/x/sys/windows" | ||
) | ||
|
||
type retriever struct { | ||
// funcGetIfEntry2Ex is the system call for GetIfEntry2Ex Win32 API. | ||
funcGetIfEntry2Ex func(a ...uintptr) (r1 uintptr, r2 uintptr, lastErr error) | ||
} | ||
|
||
// NewStatsRetriever returns an instance of StatsRetriever interface. | ||
func NewStatsRetriever() StatsRetriever { | ||
log.Debugf("Initializing stats retriever for Windows") | ||
obj := &retriever{} | ||
|
||
// We would be using GetIfEntry2Ex Win32 APIs from IP Helper. | ||
moduleIPHelper := windows.NewLazySystemDLL("iphlpapi.dll") | ||
procGetIfEntry2Ex := moduleIPHelper.NewProc("GetIfEntry2Ex") | ||
|
||
obj.funcGetIfEntry2Ex = procGetIfEntry2Ex.Call | ||
return obj | ||
} | ||
|
||
// GetNetworkAdapterStatisticsPerContainer returns the network stats for the queried device averaged per container. | ||
func (retriever *retriever) GetNetworkAdapterStatisticsPerContainer(ifIndex int, numberOfContainers int) (*dockerstats.NetworkStats, error) { | ||
iface, err := retriever.getIfRowForDevice(ifIndex) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
stats := &dockerstats.NetworkStats{} | ||
stats.RxBytes = iface.inOctets / uint64(numberOfContainers) | ||
stats.RxPackets = (iface.inNUcastPkts + iface.inUcastPkts) / uint64(numberOfContainers) | ||
stats.RxErrors = iface.inErrors / uint64(numberOfContainers) | ||
stats.RxDropped = iface.inDiscards / uint64(numberOfContainers) | ||
stats.TxBytes = iface.outOctets / uint64(numberOfContainers) | ||
stats.TxPackets = (iface.outNUcastPkts + iface.outUcastPkts) / uint64(numberOfContainers) | ||
stats.TxErrors = iface.outErrors / uint64(numberOfContainers) | ||
stats.TxDropped = iface.outDiscards / uint64(numberOfContainers) | ||
|
||
return stats, nil | ||
} | ||
|
||
// getIfRowForDevice return the MIB_IF_ROW2 object for the queried device. | ||
// This method would internally invoke the GetIfEntry2Ex Windows API to get the interface row. | ||
func (retriever *retriever) getIfRowForDevice(ifIndex int) (*mibIfRow2, error) { | ||
row := &mibIfRow2{ | ||
interfaceIndex: uint32(ifIndex), | ||
} | ||
|
||
// GetIfEntry2Ex function retrieves the MIB-II interface for the given interface index.. | ||
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-getifentry2ex | ||
retVal, _, _ := retriever.funcGetIfEntry2Ex(uintptr(0), uintptr(unsafe.Pointer(row))) | ||
if retVal != 0 { | ||
return nil, errors.Errorf("error occured while calling GetIfEntry2Ex: %s", syscall.Errno(retVal)) | ||
} | ||
|
||
return row, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"). You may | ||
// not use this file except in compliance with the License. A copy of the | ||
// License is located at | ||
// | ||
// http://aws.amazon.com/apache2.0/ | ||
// | ||
// or in the "license" file accompanying this file. This file 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 statsretriever | ||
|
||
import "golang.org/x/sys/windows" | ||
|
||
const ( | ||
ifMaxStringSize = 256 | ||
ifMaxPhysAddressLength = 32 | ||
) | ||
|
||
// mibIfRow2 structure stores information about a particular interface. | ||
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_if_row2 | ||
type mibIfRow2 struct { | ||
interfaceLUID uint64 | ||
interfaceIndex uint32 | ||
interfaceGUID windows.GUID | ||
alias [ifMaxStringSize + 1]uint16 | ||
description [ifMaxStringSize + 1]uint16 | ||
physicalAddressLength uint32 | ||
physicalAddress [ifMaxPhysAddressLength]byte | ||
permanentPhysicalAddress [ifMaxPhysAddressLength]byte | ||
mtu uint32 | ||
ifType uint32 | ||
tunnelType uint32 | ||
mediaType uint32 | ||
physicalMediumType uint32 | ||
accessType uint32 | ||
directionType uint32 | ||
interfaceAndOperStatusFlags uint8 | ||
operStatus uint32 | ||
adminStatus uint32 | ||
mediaConnectState uint32 | ||
networkGUID windows.GUID | ||
connectionType uint32 | ||
transmitLinkSpeed uint64 | ||
receiveLinkSpeed uint64 | ||
inOctets uint64 | ||
inUcastPkts uint64 | ||
inNUcastPkts uint64 | ||
inDiscards uint64 | ||
inErrors uint64 | ||
inUnknownProtos uint64 | ||
inUcastOctets uint64 | ||
inMulticastOctets uint64 | ||
inBroadcastOctets uint64 | ||
outOctets uint64 | ||
outUcastPkts uint64 | ||
outNUcastPkts uint64 | ||
outDiscards uint64 | ||
outErrors uint64 | ||
outUcastOctets uint64 | ||
outMulticastOctets uint64 | ||
outBroadcastOctets uint64 | ||
outQLen uint64 | ||
} |
Oops, something went wrong.