2017-11-28 14:47:11 +00:00
/ *
2021-02-23 10:05:13 +02:00
Copyright 2017 - 2021 The Kubernetes Authors .
2017-11-28 14:47:11 +00:00
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 network
import (
"bytes"
"fmt"
"io/ioutil"
"strconv"
"strings"
2018-06-21 19:02:30 +03:00
2021-02-23 10:05:13 +02:00
"k8s.io/klog/v2"
2018-11-28 14:30:03 +02:00
"sigs.k8s.io/node-feature-discovery/source"
2017-11-28 14:47:11 +00:00
)
2020-05-19 21:07:23 +03:00
// Linux net iface flags (we only specify the first few)
const (
flagUp = 1 << iota
_ // flagBroadcast
_ // flagDebug
flagLoopback
)
const sysfsBaseDir = "class/net"
2017-11-28 14:47:11 +00:00
// Source implements FeatureSource.
type Source struct { }
2018-03-05 17:51:47 +02:00
// Name returns an identifier string for this feature source.
2017-11-28 14:47:11 +00:00
func ( s Source ) Name ( ) string { return "network" }
2020-04-21 22:03:37 +03:00
// NewConfig method of the FeatureSource interface
func ( s * Source ) NewConfig ( ) source . Config { return nil }
// GetConfig method of the FeatureSource interface
func ( s * Source ) GetConfig ( ) source . Config { return nil }
// SetConfig method of the FeatureSource interface
func ( s * Source ) SetConfig ( source . Config ) { }
2018-03-05 17:51:47 +02:00
// Discover returns feature names sriov-configured and sriov if SR-IOV capable NICs are present and/or SR-IOV virtual functions are configured on the node
2018-06-21 19:02:30 +03:00
func ( s Source ) Discover ( ) ( source . Features , error ) {
features := source . Features { }
2020-05-19 21:07:23 +03:00
netInterfaces , err := ioutil . ReadDir ( source . SysfsDir . Path ( sysfsBaseDir ) )
2017-11-28 14:47:11 +00:00
if err != nil {
2020-05-19 21:07:23 +03:00
return nil , fmt . Errorf ( "failed to list network interfaces: %s" , err . Error ( ) )
2017-11-28 14:47:11 +00:00
}
2020-05-19 21:07:23 +03:00
2017-11-28 14:47:11 +00:00
// iterating through network interfaces to obtain their respective number of virtual functions
for _ , netInterface := range netInterfaces {
2020-05-19 21:07:23 +03:00
name := netInterface . Name ( )
flags , err := readIfFlags ( name )
if err != nil {
2021-02-23 10:05:13 +02:00
klog . Error ( err )
2020-05-19 21:07:23 +03:00
continue
}
if flags & flagUp != 0 && flags & flagLoopback == 0 {
totalBytes , err := ioutil . ReadFile ( source . SysfsDir . Path ( sysfsBaseDir , name , "device/sriov_totalvfs" ) )
2017-11-28 14:47:11 +00:00
if err != nil {
2021-02-23 10:05:13 +02:00
klog . V ( 1 ) . Infof ( "SR-IOV not supported for network interface: %s: %v" , name , err )
2017-11-28 14:47:11 +00:00
continue
}
total := bytes . TrimSpace ( totalBytes )
t , err := strconv . Atoi ( string ( total ) )
if err != nil {
2021-02-25 12:12:06 -05:00
klog . Errorf ( "error in obtaining maximum supported number of virtual functions for network interface: %s: %v" , name , err )
2017-11-28 14:47:11 +00:00
continue
}
if t > 0 {
2021-02-23 10:05:13 +02:00
klog . V ( 1 ) . Infof ( "SR-IOV capability is detected on the network interface: %s" , name )
klog . V ( 1 ) . Infof ( "%d maximum supported number of virtual functions on network interface: %s" , t , name )
2018-06-21 19:02:30 +03:00
features [ "sriov.capable" ] = true
2020-05-19 21:07:23 +03:00
numBytes , err := ioutil . ReadFile ( source . SysfsDir . Path ( sysfsBaseDir , name , "device/sriov_numvfs" ) )
2017-11-28 14:47:11 +00:00
if err != nil {
2021-02-23 10:05:13 +02:00
klog . V ( 1 ) . Infof ( "SR-IOV not configured for network interface: %s: %s" , name , err )
2017-11-28 14:47:11 +00:00
continue
}
num := bytes . TrimSpace ( numBytes )
n , err := strconv . Atoi ( string ( num ) )
if err != nil {
2021-02-25 12:12:06 -05:00
klog . Errorf ( "error in obtaining the configured number of virtual functions for network interface: %s: %v" , name , err )
2017-11-28 14:47:11 +00:00
continue
}
if n > 0 {
2021-02-23 10:05:13 +02:00
klog . V ( 1 ) . Infof ( "%d virtual functions configured on network interface: %s" , n , name )
2018-06-21 19:02:30 +03:00
features [ "sriov.configured" ] = true
2017-11-28 14:47:11 +00:00
break
} else if n == 0 {
2021-02-23 10:05:13 +02:00
klog . V ( 1 ) . Infof ( "SR-IOV not configured on network interface: %s" , name )
2017-11-28 14:47:11 +00:00
}
}
}
}
return features , nil
}
2020-05-19 21:07:23 +03:00
func readIfFlags ( name string ) ( uint64 , error ) {
raw , err := ioutil . ReadFile ( source . SysfsDir . Path ( sysfsBaseDir , name , "flags" ) )
if err != nil {
return 0 , fmt . Errorf ( "failed to read flags for interface %q: %v" , name , err )
}
flags , err := strconv . ParseUint ( strings . TrimSpace ( string ( raw ) ) , 0 , 64 )
if err != nil {
return 0 , fmt . Errorf ( "failed to parse flags for interface %q: %v" , name , err )
}
return flags , nil
}