Merge pull request #1190 from dgibson/pcipath

Clean up PCI path handling
This commit is contained in:
David Gibson 2021-02-19 12:23:27 +11:00 committed by GitHub
commit a060b9a21b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 701 additions and 221 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
**/*.bk **/*.bk
**/*~
**/*.orig **/*.orig
**/*.rej **/*.rej
**/target **/target

View File

@ -29,10 +29,8 @@ message Interface {
uint64 mtu = 4; uint64 mtu = 4;
string hwAddr = 5; string hwAddr = 5;
// pciAddr is the PCI address in the format "bridgeAddr/deviceAddr". // PCI path for the device (see the pci::Path (Rust) or types.PciPath (Go) type for format details)
// Here, bridgeAddr is the address at which the bridge is attached on the root bus, string pciPath = 6;
// while deviceAddr is the address at which the network device is attached on the bridge.
string pciAddr = 6;
// Type defines the type of interface described by this structure. // Type defines the type of interface described by this structure.
// The expected values are the one that are defined by the netlink // The expected values are the one that are defined by the netlink

View File

@ -9,11 +9,13 @@ use std::collections::HashMap;
use std::fs; use std::fs;
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::path::Path; use std::path::Path;
use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use crate::linux_abi::*; use crate::linux_abi::*;
use crate::mount::{DRIVER_BLK_TYPE, DRIVER_MMIO_BLK_TYPE, DRIVER_NVDIMM_TYPE, DRIVER_SCSI_TYPE}; use crate::mount::{DRIVER_BLK_TYPE, DRIVER_MMIO_BLK_TYPE, DRIVER_NVDIMM_TYPE, DRIVER_SCSI_TYPE};
use crate::pci;
use crate::sandbox::Sandbox; use crate::sandbox::Sandbox;
use crate::{AGENT_CONFIG, GLOBAL_DEVICE_WATCHER}; use crate::{AGENT_CONFIG, GLOBAL_DEVICE_WATCHER};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -45,58 +47,44 @@ pub fn online_device(path: &str) -> Result<()> {
Ok(()) Ok(())
} }
// get_pci_device_address fetches the complete PCI address in sysfs, based on the PCI // pciPathToSysfs fetches the sysfs path for a PCI path, relative to
// identifier provided. This should be in the format: "bridgeAddr/deviceAddr". // the syfs path for the PCI host bridge, based on the PCI path
// Here, bridgeAddr is the address at which the bridge is attached on the root bus, // provided.
// while deviceAddr is the address at which the device is attached on the bridge. fn pcipath_to_sysfs(root_bus_sysfs: &str, pcipath: &pci::Path) -> Result<String> {
fn get_pci_device_address(pci_id: &str) -> Result<String> { let mut bus = "0000:00".to_string();
let tokens: Vec<&str> = pci_id.split('/').collect(); let mut relpath = String::new();
if tokens.len() != 2 { for i in 0..pcipath.len() {
return Err(anyhow!( let bdf = format!("{}:{}.0", bus, pcipath[i]);
"PCI Identifier for device should be of format [bridgeAddr/deviceAddr], got {}",
pci_id relpath = format!("{}/{}", relpath, bdf);
));
if i == pcipath.len() - 1 {
// Final device need not be a bridge
break;
} }
let bridge_id = tokens[0];
let device_id = tokens[1];
// Deduce the complete bridge address based on the bridge address identifier passed
// and the fact that bridges are attached on the main bus with function 0.
let pci_bridge_addr = format!("0000:00:{}.0", bridge_id);
// Find out the bus exposed by bridge // Find out the bus exposed by bridge
let bridge_bus_path = format!("{}/{}/pci_bus/", SYSFS_PCI_BUS_PREFIX, pci_bridge_addr); let bridgebuspath = format!("{}{}/pci_bus", root_bus_sysfs, relpath);
let mut files: Vec<_> = fs::read_dir(&bridgebuspath)?.collect();
let files_slice: Vec<_> = fs::read_dir(&bridge_bus_path) if files.len() != 1 {
.unwrap()
.map(|res| res.unwrap().path())
.collect();
let bus_num = files_slice.len();
if bus_num != 1 {
return Err(anyhow!( return Err(anyhow!(
"Expected an entry for bus in {}, got {} entries instead", "Expected exactly one PCI bus in {}, got {} instead",
bridge_bus_path, bridgebuspath,
bus_num files.len()
)); ));
} }
let bus = files_slice[0].file_name().unwrap().to_str().unwrap(); // unwrap is safe, because of the length test above
let busfile = files.pop().unwrap()?;
bus = busfile
.file_name()
.into_string()
.map_err(|e| anyhow!("Bad filename under {}: {:?}", &bridgebuspath, e))?;
}
// Device address is based on the bus of the bridge to which it is attached. Ok(relpath)
// We do not pass devices as multifunction, hence the trailing 0 in the address.
let pci_device_addr = format!("{}:{}.0", bus, device_id);
let bridge_device_pci_addr = format!("{}/{}", pci_bridge_addr, pci_device_addr);
info!(
sl!(),
"Fetched PCI address for device PCIAddr:{}\n", bridge_device_pci_addr
);
Ok(bridge_device_pci_addr)
} }
async fn get_device_name(sandbox: &Arc<Mutex<Sandbox>>, dev_addr: &str) -> Result<String> { async fn get_device_name(sandbox: &Arc<Mutex<Sandbox>>, dev_addr: &str) -> Result<String> {
@ -155,11 +143,15 @@ pub async fn get_scsi_device_name(
get_device_name(sandbox, &dev_sub_path).await get_device_name(sandbox, &dev_sub_path).await
} }
pub async fn get_pci_device_name(sandbox: &Arc<Mutex<Sandbox>>, pci_id: &str) -> Result<String> { pub async fn get_pci_device_name(
let pci_addr = get_pci_device_address(pci_id)?; sandbox: &Arc<Mutex<Sandbox>>,
pcipath: &pci::Path,
) -> Result<String> {
let root_bus_sysfs = format!("{}{}", SYSFS_DIR, create_pci_root_bus_path());
let sysfs_rel_path = pcipath_to_sysfs(&root_bus_sysfs, pcipath)?;
rescan_pci_bus()?; rescan_pci_bus()?;
get_device_name(sandbox, &pci_addr).await get_device_name(sandbox, &sysfs_rel_path).await
} }
pub async fn get_pmem_device_name( pub async fn get_pmem_device_name(
@ -294,9 +286,7 @@ async fn virtiommio_blk_device_handler(
update_spec_device_list(device, spec, devidx) update_spec_device_list(device, spec, devidx)
} }
// device.Id should be the PCI address in the format "bridgeAddr/deviceAddr". // device.Id should be a PCI path string
// Here, bridgeAddr is the address at which the brige is attached on the root bus,
// while deviceAddr is the address at which the device is attached on the bridge.
async fn virtio_blk_device_handler( async fn virtio_blk_device_handler(
device: &Device, device: &Device,
spec: &mut Spec, spec: &mut Spec,
@ -305,10 +295,12 @@ async fn virtio_blk_device_handler(
) -> Result<()> { ) -> Result<()> {
let mut dev = device.clone(); let mut dev = device.clone();
// When "Id (PCIAddr)" is not set, we allow to use the predicted "VmPath" passed from kata-runtime // When "Id (PCI path)" is not set, we allow to use the predicted
// Note this is a special code path for cloud-hypervisor when BDF information is not available // "VmPath" passed from kata-runtime Note this is a special code
// path for cloud-hypervisor when BDF information is not available
if device.id != "" { if device.id != "" {
dev.vm_path = get_pci_device_name(sandbox, &device.id).await?; let pcipath = pci::Path::from_str(&device.id)?;
dev.vm_path = get_pci_device_name(sandbox, &pcipath).await?;
} }
update_spec_device_list(&dev, spec, devidx) update_spec_device_list(&dev, spec, devidx)
@ -443,6 +435,7 @@ pub fn update_device_cgroup(spec: &mut Spec) -> Result<()> {
mod tests { mod tests {
use super::*; use super::*;
use oci::Linux; use oci::Linux;
use tempfile::tempdir;
#[test] #[test]
fn test_update_device_cgroup() { fn test_update_device_cgroup() {
@ -722,4 +715,68 @@ mod tests {
assert_eq!(Some(host_major), specresources.devices[1].major); assert_eq!(Some(host_major), specresources.devices[1].major);
assert_eq!(Some(host_minor), specresources.devices[1].minor); assert_eq!(Some(host_minor), specresources.devices[1].minor);
} }
#[test]
fn test_pcipath_to_sysfs() {
let testdir = tempdir().expect("failed to create tmpdir");
let rootbuspath = testdir.path().to_str().unwrap();
let path2 = pci::Path::from_str("02").unwrap();
let path23 = pci::Path::from_str("02/03").unwrap();
let path234 = pci::Path::from_str("02/03/04").unwrap();
let relpath = pcipath_to_sysfs(rootbuspath, &path2);
assert_eq!(relpath.unwrap(), "/0000:00:02.0");
let relpath = pcipath_to_sysfs(rootbuspath, &path23);
assert!(relpath.is_err());
let relpath = pcipath_to_sysfs(rootbuspath, &path234);
assert!(relpath.is_err());
// Create mock sysfs files for the device at 0000:00:02.0
let bridge2path = format!("{}{}", rootbuspath, "/0000:00:02.0");
fs::create_dir_all(&bridge2path).unwrap();
let relpath = pcipath_to_sysfs(rootbuspath, &path2);
assert_eq!(relpath.unwrap(), "/0000:00:02.0");
let relpath = pcipath_to_sysfs(rootbuspath, &path23);
assert!(relpath.is_err());
let relpath = pcipath_to_sysfs(rootbuspath, &path234);
assert!(relpath.is_err());
// Create mock sysfs files to indicate that 0000:00:02.0 is a bridge to bus 01
let bridge2bus = "0000:01";
let bus2path = format!("{}/pci_bus/{}", bridge2path, bridge2bus);
fs::create_dir_all(bus2path).unwrap();
let relpath = pcipath_to_sysfs(rootbuspath, &path2);
assert_eq!(relpath.unwrap(), "/0000:00:02.0");
let relpath = pcipath_to_sysfs(rootbuspath, &path23);
assert_eq!(relpath.unwrap(), "/0000:00:02.0/0000:01:03.0");
let relpath = pcipath_to_sysfs(rootbuspath, &path234);
assert!(relpath.is_err());
// Create mock sysfs files for a bridge at 0000:01:03.0 to bus 02
let bridge3path = format!("{}/0000:01:03.0", bridge2path);
let bridge3bus = "0000:02";
let bus3path = format!("{}/pci_bus/{}", bridge3path, bridge3bus);
fs::create_dir_all(bus3path).unwrap();
let relpath = pcipath_to_sysfs(rootbuspath, &path2);
assert_eq!(relpath.unwrap(), "/0000:00:02.0");
let relpath = pcipath_to_sysfs(rootbuspath, &path23);
assert_eq!(relpath.unwrap(), "/0000:00:02.0/0000:01:03.0");
let relpath = pcipath_to_sysfs(rootbuspath, &path234);
assert_eq!(relpath.unwrap(), "/0000:00:02.0/0000:01:03.0/0000:02:04.0");
}
} }

View File

@ -9,7 +9,6 @@
use std::fs; use std::fs;
pub const SYSFS_DIR: &str = "/sys"; pub const SYSFS_DIR: &str = "/sys";
pub const SYSFS_PCI_BUS_PREFIX: &str = "/sys/bus/pci/devices";
pub const SYSFS_PCI_BUS_RESCAN_FILE: &str = "/sys/bus/pci/rescan"; pub const SYSFS_PCI_BUS_RESCAN_FILE: &str = "/sys/bus/pci/rescan";
#[cfg(any( #[cfg(any(
target_arch = "powerpc64", target_arch = "powerpc64",

View File

@ -49,6 +49,7 @@ mod mount;
mod namespace; mod namespace;
mod netlink; mod netlink;
mod network; mod network;
mod pci;
pub mod random; pub mod random;
mod sandbox; mod sandbox;
#[cfg(test)] #[cfg(test)]

View File

@ -12,6 +12,7 @@ use std::os::unix::fs::PermissionsExt;
use std::path::Path; use std::path::Path;
use std::ptr::null; use std::ptr::null;
use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -26,6 +27,7 @@ use crate::device::{
get_pci_device_name, get_pmem_device_name, get_scsi_device_name, online_device, get_pci_device_name, get_pmem_device_name, get_scsi_device_name, online_device,
}; };
use crate::linux_abi::*; use crate::linux_abi::*;
use crate::pci;
use crate::protocols::agent::Storage; use crate::protocols::agent::Storage;
use crate::Sandbox; use crate::Sandbox;
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
@ -310,8 +312,8 @@ async fn virtio_blk_storage_handler(
sandbox: Arc<Mutex<Sandbox>>, sandbox: Arc<Mutex<Sandbox>>,
) -> Result<String> { ) -> Result<String> {
let mut storage = storage.clone(); let mut storage = storage.clone();
// If hot-plugged, get the device node path based on the PCI address else // If hot-plugged, get the device node path based on the PCI path
// use the virt path provided in Storage Source // otherwise use the virt path provided in Storage Source
if storage.source.starts_with("/dev") { if storage.source.starts_with("/dev") {
let metadata = fs::metadata(&storage.source) let metadata = fs::metadata(&storage.source)
.context(format!("get metadata on file {:?}", &storage.source))?; .context(format!("get metadata on file {:?}", &storage.source))?;
@ -321,7 +323,8 @@ async fn virtio_blk_storage_handler(
return Err(anyhow!("Invalid device {}", &storage.source)); return Err(anyhow!("Invalid device {}", &storage.source));
} }
} else { } else {
let dev_path = get_pci_device_name(&sandbox, &storage.source).await?; let pcipath = pci::Path::from_str(&storage.source)?;
let dev_path = get_pci_device_name(&sandbox, &pcipath).await?;
storage.source = dev_path; storage.source = dev_path;
} }

168
src/agent/src/pci.rs Normal file
View File

@ -0,0 +1,168 @@
// Copyright Red Hat.
//
// SPDX-License-Identifier: Apache-2.0
//
use std::convert::TryInto;
use std::fmt;
use std::ops::Deref;
use std::str::FromStr;
use anyhow::anyhow;
// The PCI spec reserves 5 bits for slot number (a.k.a. device
// number), giving slots 0..31
const SLOT_BITS: u8 = 5;
const SLOT_MAX: u8 = (1 << SLOT_BITS) - 1;
// Represents a PCI function's slot number (a.k.a. device number),
// giving its location on a single bus
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Slot(u8);
impl Slot {
pub fn new<T: TryInto<u8> + fmt::Display + Copy>(v: T) -> anyhow::Result<Self> {
if let Ok(v8) = v.try_into() {
if v8 <= SLOT_MAX {
return Ok(Slot(v8));
}
}
Err(anyhow!(
"PCI slot {} should be in range [0..{:#x}]",
v,
SLOT_MAX
))
}
}
impl FromStr for Slot {
type Err = anyhow::Error;
fn from_str(s: &str) -> anyhow::Result<Self> {
let v = isize::from_str_radix(s, 16)?;
Slot::new(v)
}
}
impl fmt::Display for Slot {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{:02x}", self.0)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Path(Vec<Slot>);
impl Path {
pub fn new(slots: Vec<Slot>) -> anyhow::Result<Self> {
if slots.is_empty() {
return Err(anyhow!("PCI path must have at least one element"));
}
Ok(Path(slots))
}
}
// Let Path be treated as a slice of Slots
impl Deref for Path {
type Target = [Slot];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Display for Path {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let sslots: Vec<String> = self
.0
.iter()
.map(std::string::ToString::to_string)
.collect();
write!(f, "{}", sslots.join("/"))
}
}
impl FromStr for Path {
type Err = anyhow::Error;
fn from_str(s: &str) -> anyhow::Result<Self> {
let rslots: anyhow::Result<Vec<Slot>> = s.split('/').map(Slot::from_str).collect();
Path::new(rslots?)
}
}
#[cfg(test)]
mod tests {
use crate::pci::{Path, Slot};
use std::str::FromStr;
#[test]
fn test_slot() {
// Valid slots
let slot = Slot::new(0x00).unwrap();
assert_eq!(format!("{}", slot), "00");
let slot = Slot::from_str("00").unwrap();
assert_eq!(format!("{}", slot), "00");
let slot = Slot::new(31).unwrap();
let slot2 = Slot::from_str("1f").unwrap();
assert_eq!(slot, slot2);
// Bad slots
let slot = Slot::new(-1);
assert!(slot.is_err());
let slot = Slot::new(32);
assert!(slot.is_err());
let slot = Slot::from_str("20");
assert!(slot.is_err());
let slot = Slot::from_str("xy");
assert!(slot.is_err());
let slot = Slot::from_str("00/");
assert!(slot.is_err());
let slot = Slot::from_str("");
assert!(slot.is_err());
}
#[test]
fn test_path() {
let slot3 = Slot::new(0x03).unwrap();
let slot4 = Slot::new(0x04).unwrap();
let slot5 = Slot::new(0x05).unwrap();
// Valid paths
let pcipath = Path::new(vec![slot3]).unwrap();
assert_eq!(format!("{}", pcipath), "03");
let pcipath2 = Path::from_str("03").unwrap();
assert_eq!(pcipath, pcipath2);
assert_eq!(pcipath.len(), 1);
assert_eq!(pcipath[0], slot3);
let pcipath = Path::new(vec![slot3, slot4]).unwrap();
assert_eq!(format!("{}", pcipath), "03/04");
let pcipath2 = Path::from_str("03/04").unwrap();
assert_eq!(pcipath, pcipath2);
assert_eq!(pcipath.len(), 2);
assert_eq!(pcipath[0], slot3);
assert_eq!(pcipath[1], slot4);
let pcipath = Path::new(vec![slot3, slot4, slot5]).unwrap();
assert_eq!(format!("{}", pcipath), "03/04/05");
let pcipath2 = Path::from_str("03/04/05").unwrap();
assert_eq!(pcipath, pcipath2);
assert_eq!(pcipath.len(), 3);
assert_eq!(pcipath[0], slot3);
assert_eq!(pcipath[1], slot4);
assert_eq!(pcipath[2], slot5);
// Bad paths
assert!(Path::new(vec!()).is_err());
assert!(Path::from_str("20").is_err());
assert!(Path::from_str("//").is_err());
assert!(Path::from_str("xyz").is_err());
}
}

View File

@ -28,6 +28,7 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/uuid" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/uuid"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// Since ACRN is using the store in a quite abnormal way, let's first draw it back from store to here // Since ACRN is using the store in a quite abnormal way, let's first draw it back from store to here
@ -550,8 +551,8 @@ func (a *Acrn) updateBlockDevice(drive *config.BlockDrive) error {
slot := AcrnBlkdDevSlot[drive.Index] slot := AcrnBlkdDevSlot[drive.Index]
//Explicitly set PCIAddr to NULL, so that VirtPath can be used //Explicitly set PCIPath to NULL, so that VirtPath can be used
drive.PCIAddr = "" drive.PCIPath = vcTypes.PciPath{}
args := []string{"blkrescan", a.acrnConfig.Name, fmt.Sprintf("%d,%s", slot, drive.File)} args := []string{"blkrescan", a.acrnConfig.Name, fmt.Sprintf("%d,%s", slot, drive.File)}

View File

@ -10,6 +10,7 @@ import (
"github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/ns"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// BridgedMacvlanEndpoint represents a macvlan endpoint that is bridged to the VM // BridgedMacvlanEndpoint represents a macvlan endpoint that is bridged to the VM
@ -17,7 +18,7 @@ type BridgedMacvlanEndpoint struct {
NetPair NetworkInterfacePair NetPair NetworkInterfacePair
EndpointProperties NetworkInfo EndpointProperties NetworkInfo
EndpointType EndpointType EndpointType EndpointType
PCIAddr string PCIPath vcTypes.PciPath
RxRateLimiter bool RxRateLimiter bool
TxRateLimiter bool TxRateLimiter bool
} }
@ -69,14 +70,14 @@ func (endpoint *BridgedMacvlanEndpoint) SetProperties(properties NetworkInfo) {
endpoint.EndpointProperties = properties endpoint.EndpointProperties = properties
} }
// PciAddr returns the PCI address of the endpoint. // PciPath returns the PCI path of the endpoint.
func (endpoint *BridgedMacvlanEndpoint) PciAddr() string { func (endpoint *BridgedMacvlanEndpoint) PciPath() vcTypes.PciPath {
return endpoint.PCIAddr return endpoint.PCIPath
} }
// SetPciAddr sets the PCI address of the endpoint. // SetPciPath sets the PCI path of the endpoint.
func (endpoint *BridgedMacvlanEndpoint) SetPciAddr(pciAddr string) { func (endpoint *BridgedMacvlanEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
endpoint.PCIAddr = pciAddr endpoint.PCIPath = pciPath
} }
// NetworkPair returns the network pair of the endpoint. // NetworkPair returns the network pair of the endpoint.

View File

@ -32,6 +32,7 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// //
@ -439,8 +440,8 @@ func (clh *cloudHypervisor) hotplugAddBlockDevice(drive *config.BlockDrive) erro
driveID := clhDriveIndexToID(drive.Index) driveID := clhDriveIndexToID(drive.Index)
//Explicitly set PCIAddr to NULL, so that VirtPath can be used //Explicitly set PCIPath to NULL, so that VirtPath can be used
drive.PCIAddr = "" drive.PCIPath = vcTypes.PciPath{}
if drive.Pmem { if drive.Pmem {
err = fmt.Errorf("pmem device hotplug not supported") err = fmt.Errorf("pmem device hotplug not supported")

View File

@ -16,6 +16,7 @@ import (
"github.com/go-ini/ini" "github.com/go-ini/ini"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// DeviceType indicates device type // DeviceType indicates device type
@ -156,8 +157,8 @@ type BlockDrive struct {
// MmioAddr is used to identify the slot at which the drive is attached (order?). // MmioAddr is used to identify the slot at which the drive is attached (order?).
MmioAddr string MmioAddr string
// PCIAddr is the PCI address used to identify the slot at which the drive is attached. // PCIPath is the PCI path used to identify the slot at which the drive is attached.
PCIAddr string PCIPath vcTypes.PciPath
// SCSI Address of the block device, in case the device is attached using SCSI driver // SCSI Address of the block device, in case the device is attached using SCSI driver
// SCSI address is in the format SCSI-Id:LUN // SCSI address is in the format SCSI-Id:LUN
@ -249,9 +250,10 @@ type VhostUserDeviceAttrs struct {
CacheSize uint32 CacheSize uint32
Cache string Cache string
// PCIAddr is the PCI address used to identify the slot at which the drive is attached. // PCIPath is the PCI path used to identify the slot at which
// It is only meaningful for vhost user block devices // the drive is attached. It is only meaningful for vhost
PCIAddr string // user block devices
PCIPath vcTypes.PciPath
// Block index of the device if assigned // Block index of the device if assigned
Index int Index int

View File

@ -170,7 +170,7 @@ func (device *BlockDevice) Save() persistapi.DeviceState {
ID: drive.ID, ID: drive.ID,
Index: drive.Index, Index: drive.Index,
MmioAddr: drive.MmioAddr, MmioAddr: drive.MmioAddr,
PCIAddr: drive.PCIAddr, PCIPath: drive.PCIPath,
SCSIAddr: drive.SCSIAddr, SCSIAddr: drive.SCSIAddr,
NvdimmID: drive.NvdimmID, NvdimmID: drive.NvdimmID,
VirtPath: drive.VirtPath, VirtPath: drive.VirtPath,
@ -196,7 +196,7 @@ func (device *BlockDevice) Load(ds persistapi.DeviceState) {
ID: bd.ID, ID: bd.ID,
Index: bd.Index, Index: bd.Index,
MmioAddr: bd.MmioAddr, MmioAddr: bd.MmioAddr,
PCIAddr: bd.PCIAddr, PCIPath: bd.PCIPath,
SCSIAddr: bd.SCSIAddr, SCSIAddr: bd.SCSIAddr,
NvdimmID: bd.NvdimmID, NvdimmID: bd.NvdimmID,
VirtPath: bd.VirtPath, VirtPath: bd.VirtPath,

View File

@ -164,7 +164,7 @@ func (device *VhostUserBlkDevice) Save() persistapi.DeviceState {
DevID: vAttr.DevID, DevID: vAttr.DevID,
SocketPath: vAttr.SocketPath, SocketPath: vAttr.SocketPath,
Type: string(vAttr.Type), Type: string(vAttr.Type),
PCIAddr: vAttr.PCIAddr, PCIPath: vAttr.PCIPath,
Index: vAttr.Index, Index: vAttr.Index,
} }
} }
@ -185,7 +185,7 @@ func (device *VhostUserBlkDevice) Load(ds persistapi.DeviceState) {
DevID: dev.DevID, DevID: dev.DevID,
SocketPath: dev.SocketPath, SocketPath: dev.SocketPath,
Type: config.DeviceType(dev.Type), Type: config.DeviceType(dev.Type),
PCIAddr: dev.PCIAddr, PCIPath: dev.PCIPath,
Index: dev.Index, Index: dev.Index,
} }
} }

View File

@ -9,6 +9,7 @@ import (
"fmt" "fmt"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// Endpoint represents a physical or virtual network interface. // Endpoint represents a physical or virtual network interface.
@ -17,11 +18,11 @@ type Endpoint interface {
Name() string Name() string
HardwareAddr() string HardwareAddr() string
Type() EndpointType Type() EndpointType
PciAddr() string PciPath() vcTypes.PciPath
NetworkPair() *NetworkInterfacePair NetworkPair() *NetworkInterfacePair
SetProperties(NetworkInfo) SetProperties(NetworkInfo)
SetPciAddr(string) SetPciPath(vcTypes.PciPath)
Attach(*Sandbox) error Attach(*Sandbox) error
Detach(netNsCreated bool, netNsPath string) error Detach(netNsCreated bool, netNsPath string) error
HotAttach(h hypervisor) error HotAttach(h hypervisor) error

View File

@ -10,6 +10,7 @@ import (
"github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/ns"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// IPVlanEndpoint represents a ipvlan endpoint that is bridged to the VM // IPVlanEndpoint represents a ipvlan endpoint that is bridged to the VM
@ -17,7 +18,7 @@ type IPVlanEndpoint struct {
NetPair NetworkInterfacePair NetPair NetworkInterfacePair
EndpointProperties NetworkInfo EndpointProperties NetworkInfo
EndpointType EndpointType EndpointType EndpointType
PCIAddr string PCIPath vcTypes.PciPath
RxRateLimiter bool RxRateLimiter bool
TxRateLimiter bool TxRateLimiter bool
} }
@ -72,14 +73,14 @@ func (endpoint *IPVlanEndpoint) SetProperties(properties NetworkInfo) {
endpoint.EndpointProperties = properties endpoint.EndpointProperties = properties
} }
// PciAddr returns the PCI address of the endpoint. // PciPath returns the PCI path of the endpoint.
func (endpoint *IPVlanEndpoint) PciAddr() string { func (endpoint *IPVlanEndpoint) PciPath() vcTypes.PciPath {
return endpoint.PCIAddr return endpoint.PCIPath
} }
// SetPciAddr sets the PCI address of the endpoint. // SetPciPath sets the PCI path of the endpoint.
func (endpoint *IPVlanEndpoint) SetPciAddr(pciAddr string) { func (endpoint *IPVlanEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
endpoint.PCIAddr = pciAddr endpoint.PCIPath = pciPath
} }
// NetworkPair returns the network pair of the endpoint. // NetworkPair returns the network pair of the endpoint.

View File

@ -1074,7 +1074,7 @@ func (k *kataAgent) appendBlockDevice(dev ContainerDevice, c *Container) *grpc.D
kataDevice.Id = d.DevNo kataDevice.Id = d.DevNo
case config.VirtioBlock: case config.VirtioBlock:
kataDevice.Type = kataBlkDevType kataDevice.Type = kataBlkDevType
kataDevice.Id = d.PCIAddr kataDevice.Id = d.PCIPath.String()
kataDevice.VmPath = d.VirtPath kataDevice.VmPath = d.VirtPath
case config.VirtioSCSI: case config.VirtioSCSI:
kataDevice.Type = kataSCSIDevType kataDevice.Type = kataSCSIDevType
@ -1099,7 +1099,7 @@ func (k *kataAgent) appendVhostUserBlkDevice(dev ContainerDevice, c *Container)
kataDevice := &grpc.Device{ kataDevice := &grpc.Device{
ContainerPath: dev.ContainerPath, ContainerPath: dev.ContainerPath,
Type: kataBlkDevType, Type: kataBlkDevType,
Id: d.PCIAddr, Id: d.PCIPath.String(),
} }
return kataDevice return kataDevice
@ -1178,10 +1178,10 @@ func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPat
rootfs.Source = blockDrive.DevNo rootfs.Source = blockDrive.DevNo
case sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioBlock: case sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioBlock:
rootfs.Driver = kataBlkDevType rootfs.Driver = kataBlkDevType
if blockDrive.PCIAddr == "" { if blockDrive.PCIPath.IsNil() {
rootfs.Source = blockDrive.VirtPath rootfs.Source = blockDrive.VirtPath
} else { } else {
rootfs.Source = blockDrive.PCIAddr rootfs.Source = blockDrive.PCIPath.String()
} }
case sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioSCSI: case sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioSCSI:
@ -1427,10 +1427,10 @@ func (k *kataAgent) handleDeviceBlockVolume(c *Container, m Mount, device api.De
vol.Source = blockDrive.DevNo vol.Source = blockDrive.DevNo
case c.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioBlock: case c.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioBlock:
vol.Driver = kataBlkDevType vol.Driver = kataBlkDevType
if blockDrive.PCIAddr == "" { if blockDrive.PCIPath.IsNil() {
vol.Source = blockDrive.VirtPath vol.Source = blockDrive.VirtPath
} else { } else {
vol.Source = blockDrive.PCIAddr vol.Source = blockDrive.PCIPath.String()
} }
case c.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioMmio: case c.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioMmio:
vol.Driver = kataMmioBlkDevType vol.Driver = kataMmioBlkDevType
@ -1467,7 +1467,7 @@ func (k *kataAgent) handleVhostUserBlkVolume(c *Container, m Mount, device api.D
} }
vol.Driver = kataBlkDevType vol.Driver = kataBlkDevType
vol.Source = d.PCIAddr vol.Source = d.PCIPath.String()
vol.Fstype = "bind" vol.Fstype = "bind"
vol.Options = []string{"bind"} vol.Options = []string{"bind"}
vol.MountPoint = m.Destination vol.MountPoint = m.Destination

View File

@ -32,6 +32,7 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/mock" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/mock"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
var ( var (
@ -39,7 +40,7 @@ var (
testBlockDeviceCtrPath = "testBlockDeviceCtrPath" testBlockDeviceCtrPath = "testBlockDeviceCtrPath"
testDevNo = "testDevNo" testDevNo = "testDevNo"
testNvdimmID = "testNvdimmID" testNvdimmID = "testNvdimmID"
testPCIAddr = "04/02" testPCIPath, _ = vcTypes.PciPathFromString("04/02")
testSCSIAddr = "testSCSIAddr" testSCSIAddr = "testSCSIAddr"
testVirtPath = "testVirtPath" testVirtPath = "testVirtPath"
) )
@ -271,13 +272,13 @@ func TestHandleDeviceBlockVolume(t *testing.T) {
inputMount: Mount{}, inputMount: Mount{},
inputDev: &drivers.BlockDevice{ inputDev: &drivers.BlockDevice{
BlockDrive: &config.BlockDrive{ BlockDrive: &config.BlockDrive{
PCIAddr: testPCIAddr, PCIPath: testPCIPath,
VirtPath: testVirtPath, VirtPath: testVirtPath,
}, },
}, },
resultVol: &pb.Storage{ resultVol: &pb.Storage{
Driver: kataBlkDevType, Driver: kataBlkDevType,
Source: testPCIAddr, Source: testPCIPath.String(),
}, },
}, },
{ {
@ -352,17 +353,19 @@ func TestHandleBlockVolume(t *testing.T) {
vDestination := "/VhostUserBlk/destination" vDestination := "/VhostUserBlk/destination"
bDestination := "/DeviceBlock/destination" bDestination := "/DeviceBlock/destination"
dDestination := "/DeviceDirectBlock/destination" dDestination := "/DeviceDirectBlock/destination"
vPCIAddr := "0001:01" vPCIPath, err := vcTypes.PciPathFromString("01/02")
bPCIAddr := "0002:01" assert.NoError(t, err)
dPCIAddr := "0003:01" bPCIPath, err := vcTypes.PciPathFromString("03/04")
assert.NoError(t, err)
dPCIPath, err := vcTypes.PciPathFromString("04/05")
vDev := drivers.NewVhostUserBlkDevice(&config.DeviceInfo{ID: vDevID}) vDev := drivers.NewVhostUserBlkDevice(&config.DeviceInfo{ID: vDevID})
bDev := drivers.NewBlockDevice(&config.DeviceInfo{ID: bDevID}) bDev := drivers.NewBlockDevice(&config.DeviceInfo{ID: bDevID})
dDev := drivers.NewBlockDevice(&config.DeviceInfo{ID: dDevID}) dDev := drivers.NewBlockDevice(&config.DeviceInfo{ID: dDevID})
vDev.VhostUserDeviceAttrs = &config.VhostUserDeviceAttrs{PCIAddr: vPCIAddr} vDev.VhostUserDeviceAttrs = &config.VhostUserDeviceAttrs{PCIPath: vPCIPath}
bDev.BlockDrive = &config.BlockDrive{PCIAddr: bPCIAddr} bDev.BlockDrive = &config.BlockDrive{PCIPath: bPCIPath}
dDev.BlockDrive = &config.BlockDrive{PCIAddr: dPCIAddr} dDev.BlockDrive = &config.BlockDrive{PCIPath: dPCIPath}
var devices []api.Device var devices []api.Device
devices = append(devices, vDev, bDev, dDev) devices = append(devices, vDev, bDev, dDev)
@ -411,21 +414,21 @@ func TestHandleBlockVolume(t *testing.T) {
Fstype: "bind", Fstype: "bind",
Options: []string{"bind"}, Options: []string{"bind"},
Driver: kataBlkDevType, Driver: kataBlkDevType,
Source: vPCIAddr, Source: vPCIPath.String(),
} }
bStorage := &pb.Storage{ bStorage := &pb.Storage{
MountPoint: bDestination, MountPoint: bDestination,
Fstype: "bind", Fstype: "bind",
Options: []string{"bind"}, Options: []string{"bind"},
Driver: kataBlkDevType, Driver: kataBlkDevType,
Source: bPCIAddr, Source: bPCIPath.String(),
} }
dStorage := &pb.Storage{ dStorage := &pb.Storage{
MountPoint: dDestination, MountPoint: dDestination,
Fstype: "ext4", Fstype: "ext4",
Options: []string{"ro"}, Options: []string{"ro"},
Driver: kataBlkDevType, Driver: kataBlkDevType,
Source: dPCIAddr, Source: dPCIPath.String(),
} }
assert.Equal(t, vStorage, volumeStorages[0], "Error while handle VhostUserBlk type block volume") assert.Equal(t, vStorage, volumeStorages[0], "Error while handle VhostUserBlk type block volume")
@ -462,7 +465,7 @@ func TestAppendDevices(t *testing.T) {
ID: id, ID: id,
}, },
BlockDrive: &config.BlockDrive{ BlockDrive: &config.BlockDrive{
PCIAddr: testPCIAddr, PCIPath: testPCIPath,
}, },
}, },
} }
@ -489,7 +492,7 @@ func TestAppendDevices(t *testing.T) {
{ {
Type: kataBlkDevType, Type: kataBlkDevType,
ContainerPath: testBlockDeviceCtrPath, ContainerPath: testBlockDeviceCtrPath,
Id: testPCIAddr, Id: testPCIPath.String(),
}, },
} }
updatedDevList := k.appendDevices(devList, c) updatedDevList := k.appendDevices(devList, c)
@ -509,7 +512,7 @@ func TestAppendVhostUserBlkDevices(t *testing.T) {
}, },
VhostUserDeviceAttrs: &config.VhostUserDeviceAttrs{ VhostUserDeviceAttrs: &config.VhostUserDeviceAttrs{
Type: config.VhostUserBlk, Type: config.VhostUserBlk,
PCIAddr: testPCIAddr, PCIPath: testPCIPath,
}, },
}, },
} }
@ -537,7 +540,7 @@ func TestAppendVhostUserBlkDevices(t *testing.T) {
{ {
Type: kataBlkDevType, Type: kataBlkDevType,
ContainerPath: testBlockDeviceCtrPath, ContainerPath: testBlockDeviceCtrPath,
Id: testPCIAddr, Id: testPCIPath.String(),
}, },
} }
updatedDevList := k.appendDevices(devList, c) updatedDevList := k.appendDevices(devList, c)

View File

@ -10,6 +10,7 @@ import (
"os" "os"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// MacvtapEndpoint represents a macvtap endpoint // MacvtapEndpoint represents a macvtap endpoint
@ -18,7 +19,7 @@ type MacvtapEndpoint struct {
EndpointType EndpointType EndpointType EndpointType
VMFds []*os.File VMFds []*os.File
VhostFds []*os.File VhostFds []*os.File
PCIAddr string PCIPath vcTypes.PciPath
RxRateLimiter bool RxRateLimiter bool
TxRateLimiter bool TxRateLimiter bool
} }
@ -93,14 +94,14 @@ func (endpoint *MacvtapEndpoint) HotDetach(h hypervisor, netNsCreated bool, netN
return fmt.Errorf("MacvtapEndpoint does not support Hot detach") return fmt.Errorf("MacvtapEndpoint does not support Hot detach")
} }
// PciAddr returns the PCI address of the endpoint. // PciPath returns the PCI path of the endpoint.
func (endpoint *MacvtapEndpoint) PciAddr() string { func (endpoint *MacvtapEndpoint) PciPath() vcTypes.PciPath {
return endpoint.PCIAddr return endpoint.PCIPath
} }
// SetPciAddr sets the PCI address of the endpoint. // SetPciPath sets the PCI path of the endpoint.
func (endpoint *MacvtapEndpoint) SetPciAddr(pciAddr string) { func (endpoint *MacvtapEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
endpoint.PCIAddr = pciAddr endpoint.PCIPath = pciPath
} }
// NetworkPair returns the network pair of the endpoint. // NetworkPair returns the network pair of the endpoint.
@ -113,7 +114,7 @@ func (endpoint *MacvtapEndpoint) save() persistapi.NetworkEndpoint {
Type: string(endpoint.Type()), Type: string(endpoint.Type()),
Macvtap: &persistapi.MacvtapEndpoint{ Macvtap: &persistapi.MacvtapEndpoint{
PCIAddr: endpoint.PCIAddr, PCIPath: endpoint.PCIPath,
}, },
} }
} }
@ -121,7 +122,7 @@ func (endpoint *MacvtapEndpoint) load(s persistapi.NetworkEndpoint) {
endpoint.EndpointType = MacvtapEndpointType endpoint.EndpointType = MacvtapEndpointType
if s.Macvtap != nil { if s.Macvtap != nil {
endpoint.PCIAddr = s.Macvtap.PCIAddr endpoint.PCIPath = s.Macvtap.PCIPath
} }
} }

View File

@ -984,7 +984,7 @@ func generateVCNetworkStructures(networkNS NetworkNamespace) ([]*pbTypes.Interfa
Mtu: uint64(endpoint.Properties().Iface.MTU), Mtu: uint64(endpoint.Properties().Iface.MTU),
RawFlags: noarp, RawFlags: noarp,
HwAddr: endpoint.HardwareAddr(), HwAddr: endpoint.HardwareAddr(),
PciAddr: endpoint.PciAddr(), PciPath: endpoint.PciPath().String(),
} }
ifaces = append(ifaces, &ifc) ifaces = append(ifaces, &ifc)

View File

@ -6,6 +6,8 @@
package persistapi package persistapi
import vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
// ============= sandbox level resources ============= // ============= sandbox level resources =============
// BlockDrive represents a block storage drive which may be used in case the storage // BlockDrive represents a block storage drive which may be used in case the storage
@ -26,8 +28,8 @@ type BlockDrive struct {
// MmioAddr is used to identify the slot at which the drive is attached (order?). // MmioAddr is used to identify the slot at which the drive is attached (order?).
MmioAddr string MmioAddr string
// PCIAddr is the PCI address used to identify the slot at which the drive is attached. // PCIPath is the PCI path used to identify the slot at which the drive is attached.
PCIAddr string PCIPath vcTypes.PciPath
// SCSI Address of the block device, in case the device is attached using SCSI driver // SCSI Address of the block device, in case the device is attached using SCSI driver
// SCSI address is in the format SCSI-Id:LUN // SCSI address is in the format SCSI-Id:LUN
@ -71,9 +73,9 @@ type VhostUserDeviceAttrs struct {
// MacAddress is only meaningful for vhost user net device // MacAddress is only meaningful for vhost user net device
MacAddress string MacAddress string
// PCIAddr is the PCI address used to identify the slot at which the drive is attached. // PCIPath is the PCI path used to identify the slot at which the drive is attached.
// It is only meaningful for vhost user block devices // It is only meaningful for vhost user block devices
PCIAddr string PCIPath vcTypes.PciPath
// Block index of the device if assigned // Block index of the device if assigned
Index int Index int

View File

@ -7,6 +7,7 @@
package persistapi package persistapi
import ( import (
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
) )
@ -48,7 +49,7 @@ type PhysicalEndpoint struct {
type MacvtapEndpoint struct { type MacvtapEndpoint struct {
// This is for showing information. // This is for showing information.
// Remove this field won't impact anything. // Remove this field won't impact anything.
PCIAddr string PCIPath vcTypes.PciPath
} }
type TapEndpoint struct { type TapEndpoint struct {
@ -75,7 +76,7 @@ type VhostUserEndpoint struct {
// This is for showing information. // This is for showing information.
// Remove these fields won't impact anything. // Remove these fields won't impact anything.
IfaceName string IfaceName string
PCIAddr string PCIPath vcTypes.PciPath
} }
// NetworkEndpoint contains network interface information // NetworkEndpoint contains network interface information

View File

@ -17,6 +17,7 @@ import (
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/cgroups" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/cgroups"
"github.com/safchain/ethtool" "github.com/safchain/ethtool"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// PhysicalEndpoint gathers a physical network interface and its properties // PhysicalEndpoint gathers a physical network interface and its properties
@ -28,7 +29,7 @@ type PhysicalEndpoint struct {
BDF string BDF string
Driver string Driver string
VendorDeviceID string VendorDeviceID string
PCIAddr string PCIPath vcTypes.PciPath
} }
// Properties returns the properties of the physical interface. // Properties returns the properties of the physical interface.
@ -51,14 +52,14 @@ func (endpoint *PhysicalEndpoint) Type() EndpointType {
return endpoint.EndpointType return endpoint.EndpointType
} }
// PciAddr returns the PCI address of the endpoint. // PciPath returns the PCI path of the endpoint.
func (endpoint *PhysicalEndpoint) PciAddr() string { func (endpoint *PhysicalEndpoint) PciPath() vcTypes.PciPath {
return endpoint.PCIAddr return endpoint.PCIPath
} }
// SetPciAddr sets the PCI address of the endpoint. // SetPciPath sets the PCI path of the endpoint.
func (endpoint *PhysicalEndpoint) SetPciAddr(pciAddr string) { func (endpoint *PhysicalEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
endpoint.PCIAddr = pciAddr endpoint.PCIPath = pciPath
} }
// SetProperties sets the properties of the physical endpoint. // SetProperties sets the properties of the physical endpoint.

View File

@ -96,10 +96,8 @@ type Interface struct {
IPAddresses []*IPAddress `protobuf:"bytes,3,rep,name=IPAddresses,proto3" json:"IPAddresses,omitempty"` IPAddresses []*IPAddress `protobuf:"bytes,3,rep,name=IPAddresses,proto3" json:"IPAddresses,omitempty"`
Mtu uint64 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"` Mtu uint64 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"`
HwAddr string `protobuf:"bytes,5,opt,name=hwAddr,proto3" json:"hwAddr,omitempty"` HwAddr string `protobuf:"bytes,5,opt,name=hwAddr,proto3" json:"hwAddr,omitempty"`
// pciAddr is the PCI address in the format "bridgeAddr/deviceAddr". // PCI path for the device (see the pci::Path (Rust) or types.PciPath (Go) type for format details)
// Here, bridgeAddr is the address at which the bridge is attached on the root bus, PciPath string `protobuf:"bytes,6,opt,name=pciPath,proto3" json:"pciPath,omitempty"`
// while deviceAddr is the address at which the network device is attached on the bridge.
PciAddr string `protobuf:"bytes,6,opt,name=pciAddr,proto3" json:"pciAddr,omitempty"`
// Type defines the type of interface described by this structure. // Type defines the type of interface described by this structure.
// The expected values are the one that are defined by the netlink // The expected values are the one that are defined by the netlink
// library, regarding each type of link. Here is a non exhaustive // library, regarding each type of link. Here is a non exhaustive
@ -242,37 +240,37 @@ func init() {
} }
var fileDescriptor_b0c68e5b9fabcd81 = []byte{ var fileDescriptor_b0c68e5b9fabcd81 = []byte{
// 470 bytes of a gzipped FileDescriptorProto // 472 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x31, 0x8f, 0xda, 0x30, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x31, 0x8f, 0xd3, 0x30,
0x14, 0xc7, 0x31, 0x21, 0x39, 0x62, 0x74, 0x2d, 0xb2, 0xaa, 0x93, 0xd5, 0x4a, 0x51, 0xc4, 0xd2, 0x18, 0x86, 0xeb, 0xa6, 0xc9, 0x35, 0xae, 0x0e, 0x2a, 0x0b, 0x9d, 0x2c, 0x90, 0xa2, 0xa8, 0x0b,
0xa8, 0x52, 0x89, 0x44, 0xab, 0xee, 0xd7, 0xe1, 0x24, 0x96, 0x8a, 0x7a, 0x6b, 0x97, 0xca, 0x18, 0x11, 0x12, 0x8d, 0x54, 0x10, 0xfb, 0x31, 0x9c, 0xd4, 0x05, 0x15, 0x6f, 0xb0, 0x20, 0xd7, 0x75,
0x13, 0x22, 0x92, 0x38, 0xb2, 0x1d, 0x10, 0xea, 0xd2, 0x2f, 0xd2, 0xef, 0x73, 0x63, 0xc7, 0x8e, 0xd3, 0xa8, 0x49, 0x1c, 0xd9, 0x4e, 0xab, 0x8a, 0x85, 0x3f, 0xc2, 0xff, 0xb9, 0x91, 0x91, 0xf1,
0x77, 0x7c, 0x92, 0xca, 0x76, 0x40, 0x29, 0xed, 0x72, 0x13, 0xff, 0xdf, 0x7b, 0x36, 0xef, 0xff, 0xae, 0xbf, 0x04, 0xd9, 0x4e, 0xab, 0x50, 0x58, 0x6e, 0xca, 0xfb, 0x7c, 0xb6, 0xf3, 0xbd, 0xdf,
0xfe, 0x18, 0xf8, 0x39, 0xcb, 0xf5, 0xa6, 0x59, 0x4e, 0x99, 0x28, 0xd3, 0x2d, 0xd5, 0xf4, 0x2d, 0x1b, 0x07, 0x7e, 0xce, 0x72, 0xbd, 0x69, 0x96, 0x53, 0x26, 0xca, 0x74, 0x4b, 0x35, 0x7d, 0xcb,
0x13, 0x95, 0xa6, 0x79, 0xc5, 0xa5, 0xfa, 0x87, 0x95, 0x64, 0x29, 0xcd, 0x78, 0xa5, 0xd3, 0x5a, 0x44, 0xa5, 0x69, 0x5e, 0x71, 0xa9, 0xfe, 0x61, 0x25, 0x59, 0x4a, 0x33, 0x5e, 0xe9, 0xb4, 0x96,
0x0a, 0x2d, 0x98, 0x28, 0x94, 0x53, 0x2a, 0xd5, 0x87, 0x9a, 0xab, 0xa9, 0x05, 0xe4, 0x5b, 0x98, 0x42, 0x0b, 0x26, 0x0a, 0xe5, 0x94, 0x4a, 0xf5, 0xa1, 0xe6, 0x6a, 0x6a, 0x01, 0xf9, 0x16, 0x26,
0x2c, 0x61, 0x38, 0x5f, 0xdc, 0xae, 0x56, 0x92, 0x2b, 0x85, 0x5e, 0xc3, 0x60, 0x4d, 0xcb, 0xbc, 0x4b, 0x18, 0xce, 0x17, 0xb7, 0xab, 0x95, 0xe4, 0x4a, 0xa1, 0xd7, 0x30, 0x58, 0xd3, 0x32, 0x2f,
0x38, 0x60, 0x10, 0x83, 0xe4, 0xd9, 0xec, 0xf9, 0xd4, 0xdd, 0x98, 0x2f, 0xee, 0x6c, 0x99, 0xb4, 0x0e, 0x18, 0xc4, 0x20, 0x79, 0x36, 0x7b, 0x3e, 0x75, 0x27, 0xe6, 0x8b, 0x3b, 0x5b, 0x26, 0xed,
0x6d, 0x84, 0xe1, 0x15, 0x75, 0x77, 0x70, 0x3f, 0x06, 0x49, 0x48, 0x4e, 0x88, 0x10, 0x1c, 0x94, 0x32, 0xc2, 0xf0, 0x8a, 0xba, 0x33, 0xb8, 0x1f, 0x83, 0x24, 0x24, 0x27, 0x44, 0x08, 0x0e, 0x4a,
0x54, 0x6d, 0xb1, 0x67, 0xcb, 0x56, 0x4f, 0x1e, 0x00, 0x0c, 0xe7, 0x95, 0xe6, 0x72, 0x4d, 0x19, 0xaa, 0xb6, 0xd8, 0xb3, 0x65, 0xab, 0x27, 0x0f, 0x00, 0x86, 0xf3, 0x4a, 0x73, 0xb9, 0xa6, 0x8c,
0x47, 0x37, 0x30, 0x58, 0xf1, 0x5d, 0xce, 0xb8, 0x1d, 0x12, 0x92, 0x96, 0xcc, 0xcd, 0x8a, 0x96, 0xa3, 0x1b, 0x18, 0xac, 0xf8, 0x2e, 0x67, 0xdc, 0x36, 0x09, 0x49, 0x4b, 0xe6, 0x64, 0x45, 0x4b,
0xbc, 0xfd, 0x42, 0xab, 0xd1, 0x0c, 0x8e, 0xce, 0xee, 0xb8, 0xc2, 0x5e, 0xec, 0x25, 0xa3, 0xd9, 0xde, 0xbe, 0xd0, 0x6a, 0x34, 0x83, 0xa3, 0xb3, 0x3b, 0xae, 0xb0, 0x17, 0x7b, 0xc9, 0x68, 0x36,
0xf8, 0xec, 0xaa, 0xed, 0x90, 0xee, 0x21, 0x34, 0x86, 0x5e, 0xa9, 0x1b, 0x3c, 0x88, 0x41, 0x32, 0x3e, 0xbb, 0x6a, 0x57, 0x48, 0x77, 0x13, 0x1a, 0x43, 0xaf, 0xd4, 0x0d, 0x1e, 0xc4, 0x20, 0x19,
0x20, 0x46, 0x9a, 0x89, 0x9b, 0xbd, 0x39, 0x80, 0x7d, 0x37, 0xd1, 0x91, 0xd9, 0xa2, 0x66, 0xb9, 0x10, 0x23, 0x4d, 0xc7, 0xcd, 0xde, 0x6c, 0xc0, 0xbe, 0xeb, 0xe8, 0xc8, 0x4c, 0x51, 0xb3, 0x7c,
0x6d, 0x04, 0x6e, 0x8b, 0x16, 0x8d, 0x17, 0x33, 0x03, 0x5f, 0x39, 0x2f, 0x46, 0xa3, 0x57, 0x30, 0x41, 0xf5, 0x06, 0x07, 0x6e, 0x8a, 0x16, 0x8d, 0x17, 0xd3, 0x03, 0x5f, 0x39, 0x2f, 0x46, 0xa3,
0x94, 0x74, 0xff, 0x6d, 0x5d, 0xd0, 0x4c, 0xe1, 0x61, 0x0c, 0x92, 0x6b, 0x32, 0x94, 0x74, 0x7f, 0x57, 0x30, 0x94, 0x74, 0xff, 0x6d, 0x5d, 0xd0, 0x4c, 0xe1, 0x61, 0x0c, 0x92, 0x6b, 0x32, 0x94,
0x67, 0x78, 0xf2, 0x1d, 0xfa, 0x44, 0x34, 0xda, 0x6e, 0xb1, 0xe2, 0x4a, 0xb7, 0xbb, 0x59, 0x6d, 0x74, 0x7f, 0x67, 0x78, 0xf2, 0x1d, 0xfa, 0x44, 0x34, 0xda, 0x4e, 0xb1, 0xe2, 0x4a, 0xb7, 0xb3,
0xe6, 0x64, 0x54, 0xf3, 0x3d, 0x3d, 0x9c, 0xd2, 0x6a, 0xb1, 0x93, 0x85, 0xf7, 0x57, 0x16, 0x37, 0x59, 0x6d, 0xfa, 0x64, 0x54, 0xf3, 0x3d, 0x3d, 0x9c, 0xd2, 0x6a, 0xb1, 0x93, 0x85, 0xf7, 0x57,
0x30, 0x50, 0xa2, 0x91, 0x8c, 0xdb, 0x35, 0x42, 0xd2, 0x12, 0x7a, 0x01, 0x7d, 0xc5, 0x44, 0xcd, 0x16, 0x37, 0x30, 0x50, 0xa2, 0x91, 0x8c, 0xdb, 0x31, 0x42, 0xd2, 0x12, 0x7a, 0x01, 0x7d, 0xc5,
0xed, 0x22, 0xd7, 0xc4, 0xc1, 0xe4, 0x27, 0x80, 0xa3, 0x5b, 0xb2, 0xf8, 0xc4, 0xf3, 0x6c, 0xb3, 0x44, 0xcd, 0xed, 0x20, 0xd7, 0xc4, 0xc1, 0xe4, 0x27, 0x80, 0xa3, 0x5b, 0xb2, 0xf8, 0xc4, 0xf3,
0x14, 0xd2, 0xa4, 0xa6, 0xc5, 0x39, 0x12, 0x6b, 0xe5, 0xbf, 0xa9, 0x75, 0x0e, 0x75, 0x9c, 0xf4, 0x6c, 0xb3, 0x14, 0xd2, 0xa4, 0xa6, 0xc5, 0x39, 0x12, 0x6b, 0xe5, 0xbf, 0xa9, 0x75, 0x36, 0x75,
0x2f, 0x9d, 0x14, 0x85, 0xf9, 0x71, 0x4f, 0x0e, 0x1d, 0x59, 0x27, 0x9a, 0x6a, 0x67, 0xd0, 0x27, 0x9c, 0xf4, 0x2f, 0x9d, 0x14, 0x85, 0xf9, 0xb8, 0x27, 0x87, 0x8e, 0xac, 0x13, 0x4d, 0xb5, 0x33,
0x0e, 0x4c, 0xd5, 0xe5, 0xe3, 0xbb, 0xaa, 0x85, 0x37, 0x2f, 0xe1, 0xf0, 0xf4, 0x82, 0x50, 0x00, 0xe8, 0x13, 0x07, 0xa6, 0xea, 0xf2, 0xf1, 0x5d, 0xd5, 0xc2, 0x9b, 0x97, 0x70, 0x78, 0xba, 0x41,
0xfb, 0xbb, 0xf7, 0xe3, 0x9e, 0xfd, 0xfc, 0x30, 0x06, 0x1f, 0xd5, 0xfd, 0x63, 0xd4, 0xfb, 0xfd, 0x28, 0x80, 0xfd, 0xdd, 0xfb, 0x71, 0xcf, 0x3e, 0x3f, 0x8c, 0xc1, 0x47, 0x75, 0xff, 0x18, 0xf5,
0x18, 0xf5, 0x7e, 0x1c, 0x23, 0x70, 0x7f, 0x8c, 0xc0, 0xaf, 0x63, 0x04, 0x1e, 0x8e, 0x11, 0xf8, 0x7e, 0x3f, 0x46, 0xbd, 0x1f, 0xc7, 0x08, 0xdc, 0x1f, 0x23, 0xf0, 0xeb, 0x18, 0x81, 0x87, 0x63,
0xfa, 0xe5, 0x89, 0x6f, 0x5e, 0x36, 0x95, 0xce, 0x4b, 0x9e, 0xee, 0x72, 0xa9, 0x3b, 0xad, 0x7a, 0x04, 0xbe, 0x7e, 0x79, 0xe2, 0x9d, 0x97, 0x4d, 0xa5, 0xf3, 0x92, 0xa7, 0xbb, 0x5c, 0xea, 0xce,
0x9b, 0x5d, 0xfe, 0x1d, 0x96, 0x81, 0x95, 0xef, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x11, 0x62, 0x52, 0xbd, 0xcd, 0x2e, 0x7f, 0x87, 0x65, 0x60, 0xe5, 0xbb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff,
0xe9, 0x09, 0x57, 0x03, 0x00, 0x00, 0xed, 0x3e, 0x9a, 0x58, 0x57, 0x03, 0x00, 0x00,
} }
func (m *IPAddress) Marshal() (dAtA []byte, err error) { func (m *IPAddress) Marshal() (dAtA []byte, err error) {
@ -357,10 +355,10 @@ func (m *Interface) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i-- i--
dAtA[i] = 0x3a dAtA[i] = 0x3a
} }
if len(m.PciAddr) > 0 { if len(m.PciPath) > 0 {
i -= len(m.PciAddr) i -= len(m.PciPath)
copy(dAtA[i:], m.PciAddr) copy(dAtA[i:], m.PciPath)
i = encodeVarintTypes(dAtA, i, uint64(len(m.PciAddr))) i = encodeVarintTypes(dAtA, i, uint64(len(m.PciPath)))
i-- i--
dAtA[i] = 0x32 dAtA[i] = 0x32
} }
@ -591,7 +589,7 @@ func (m *Interface) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovTypes(uint64(l)) n += 1 + l + sovTypes(uint64(l))
} }
l = len(m.PciAddr) l = len(m.PciPath)
if l > 0 { if l > 0 {
n += 1 + l + sovTypes(uint64(l)) n += 1 + l + sovTypes(uint64(l))
} }
@ -703,7 +701,7 @@ func (this *Interface) String() string {
`IPAddresses:` + repeatedStringForIPAddresses + `,`, `IPAddresses:` + repeatedStringForIPAddresses + `,`,
`Mtu:` + fmt.Sprintf("%v", this.Mtu) + `,`, `Mtu:` + fmt.Sprintf("%v", this.Mtu) + `,`,
`HwAddr:` + fmt.Sprintf("%v", this.HwAddr) + `,`, `HwAddr:` + fmt.Sprintf("%v", this.HwAddr) + `,`,
`PciAddr:` + fmt.Sprintf("%v", this.PciAddr) + `,`, `PciPath:` + fmt.Sprintf("%v", this.PciPath) + `,`,
`Type:` + fmt.Sprintf("%v", this.Type) + `,`, `Type:` + fmt.Sprintf("%v", this.Type) + `,`,
`RawFlags:` + fmt.Sprintf("%v", this.RawFlags) + `,`, `RawFlags:` + fmt.Sprintf("%v", this.RawFlags) + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
@ -1066,7 +1064,7 @@ func (m *Interface) Unmarshal(dAtA []byte) error {
iNdEx = postIndex iNdEx = postIndex
case 6: case 6:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PciAddr", wireType) return fmt.Errorf("proto: wrong wireType = %d for field PciPath", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@ -1094,7 +1092,7 @@ func (m *Interface) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.PciAddr = string(dAtA[iNdEx:postIndex]) m.PciPath = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 7: case 7:
if wireType != 2 { if wireType != 2 {

View File

@ -0,0 +1,100 @@
// Copyright Red Hat.
//
// SPDX-License-Identifier: Apache-2.0
//
package types
import (
"fmt"
"strconv"
"strings"
)
const (
// The PCI spec reserves 5 bits for slot number (a.k.a. device
// number), giving slots 0..31
pciSlotBits = 5
maxPciSlot = (1 << pciSlotBits) - 1
)
// A PciSlot describes where a PCI device sits on a single bus
//
// This encapsulates the PCI slot number a.k.a device number, which is
// limited to a 5 bit value [0x00..0x1f] by the PCI specification
//
// XXX In order to support multifunction device's we'll need to extend
// this to include the PCI 3-bit function number as well.
type PciSlot struct{ slot uint8 }
func PciSlotFromString(s string) (PciSlot, error) {
v, err := strconv.ParseUint(s, 16, pciSlotBits)
if err != nil {
return PciSlot{}, err
}
// The 5 bit width passed to ParseUint ensures the value is <=
// maxPciSlot
return PciSlot{slot: uint8(v)}, nil
}
func PciSlotFromInt(v int) (PciSlot, error) {
if v < 0 || v > maxPciSlot {
return PciSlot{}, fmt.Errorf("PCI slot 0x%x should be in range [0..0x%x]", v, maxPciSlot)
}
return PciSlot{slot: uint8(v)}, nil
}
func (slot PciSlot) String() string {
return fmt.Sprintf("%02x", slot.slot)
}
// A PciPath describes where a PCI sits in a PCI hierarchy.
//
// Consists of a list of PCI slots, giving the slot of each bridge
// that must be traversed from the PCI root to reach the device,
// followed by the slot of the device itself
//
// When formatted into a string is written as "xx/.../yy/zz" Here, zz
// is the slot of the device on its PCI bridge, yy is the slot of the
// bridge on its parent bridge and so forth until xx is the slot of
// the "most upstream" bridge on the root bus. If a device is
// connected directly to the root bus, its PciPath is just "zz"
type PciPath struct {
slots []PciSlot
}
func (p PciPath) String() string {
tokens := make([]string, len(p.slots))
for i, slot := range p.slots {
tokens[i] = slot.String()
}
return strings.Join(tokens, "/")
}
func (p PciPath) IsNil() bool {
return p.slots == nil
}
func PciPathFromString(s string) (PciPath, error) {
if s == "" {
return PciPath{}, nil
}
tokens := strings.Split(s, "/")
slots := make([]PciSlot, len(tokens))
for i, t := range tokens {
var err error
slots[i], err = PciSlotFromString(t)
if err != nil {
return PciPath{}, err
}
}
return PciPath{slots: slots}, nil
}
func PciPathFromSlots(slots ...PciSlot) (PciPath, error) {
if len(slots) == 0 {
return PciPath{}, fmt.Errorf("PCI path needs at least one component")
}
return PciPath{slots: slots}, nil
}

View File

@ -0,0 +1,110 @@
// Copyright Red Hat.
//
// SPDX-License-Identifier: Apache-2.0
//
package types
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestPciSlot(t *testing.T) {
assert := assert.New(t)
// Valid slots
slot, err := PciSlotFromInt(0x00)
assert.NoError(err)
assert.Equal(slot, PciSlot{})
assert.Equal(slot.String(), "00")
slot, err = PciSlotFromString("00")
assert.NoError(err)
assert.Equal(slot, PciSlot{})
slot, err = PciSlotFromInt(31)
assert.NoError(err)
slot2, err := PciSlotFromString("1f")
assert.NoError(err)
assert.Equal(slot, slot2)
// Bad slots
_, err = PciSlotFromInt(-1)
assert.Error(err)
_, err = PciSlotFromInt(32)
assert.Error(err)
_, err = PciSlotFromString("20")
assert.Error(err)
_, err = PciSlotFromString("xy")
assert.Error(err)
_, err = PciSlotFromString("00/")
assert.Error(err)
_, err = PciSlotFromString("")
assert.Error(err)
}
func TestPciPath(t *testing.T) {
assert := assert.New(t)
slot3, err := PciSlotFromInt(0x03)
assert.NoError(err)
slot4, err := PciSlotFromInt(0x04)
assert.NoError(err)
slot5, err := PciSlotFromInt(0x05)
assert.NoError(err)
// Empty/nil paths
pcipath := PciPath{}
assert.True(pcipath.IsNil())
pcipath, err = PciPathFromString("")
assert.NoError(err)
assert.True(pcipath.IsNil())
assert.Equal(pcipath, PciPath{})
// Valid paths
pcipath, err = PciPathFromSlots(slot3)
assert.NoError(err)
assert.False(pcipath.IsNil())
assert.Equal(pcipath.String(), "03")
pcipath2, err := PciPathFromString("03")
assert.NoError(err)
assert.Equal(pcipath, pcipath2)
pcipath, err = PciPathFromSlots(slot3, slot4)
assert.NoError(err)
assert.False(pcipath.IsNil())
assert.Equal(pcipath.String(), "03/04")
pcipath2, err = PciPathFromString("03/04")
assert.NoError(err)
assert.Equal(pcipath, pcipath2)
pcipath, err = PciPathFromSlots(slot3, slot4, slot5)
assert.NoError(err)
assert.False(pcipath.IsNil())
assert.Equal(pcipath.String(), "03/04/05")
pcipath2, err = PciPathFromString("03/04/05")
assert.NoError(err)
assert.Equal(pcipath, pcipath2)
// Bad paths
_, err = PciPathFromSlots()
assert.Error(err)
_, err = PciPathFromString("20")
assert.Error(err)
_, err = PciPathFromString("//")
assert.Error(err)
_, err = PciPathFromString("xyz")
assert.Error(err)
}

View File

@ -39,6 +39,7 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/uuid" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/uuid"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// romFile is the file name of the ROM that can be used for virtio-pci devices. // romFile is the file name of the ROM that can be used for virtio-pci devices.
@ -1288,8 +1289,18 @@ func (q *qemu) hotplugAddBlockDevice(drive *config.BlockDrive, op operation, dev
} }
}() }()
// PCI address is in the format bridge-addr/device-addr eg. "03/02" bridgeSlot, err := vcTypes.PciSlotFromInt(bridge.Addr)
drive.PCIAddr = fmt.Sprintf("%02x", bridge.Addr) + "/" + addr if err != nil {
return err
}
devSlot, err := vcTypes.PciSlotFromString(addr)
if err != nil {
return err
}
drive.PCIPath, err = vcTypes.PciPathFromSlots(bridgeSlot, devSlot)
if err != nil {
return err
}
if err = q.qmpMonitorCh.qmp.ExecutePCIDeviceAdd(q.qmpMonitorCh.ctx, drive.ID, devID, driver, addr, bridge.ID, romFile, 0, true, defaultDisableModern); err != nil { if err = q.qmpMonitorCh.qmp.ExecutePCIDeviceAdd(q.qmpMonitorCh.ctx, drive.ID, devID, driver, addr, bridge.ID, romFile, 0, true, defaultDisableModern); err != nil {
return err return err
@ -1340,8 +1351,15 @@ func (q *qemu) hotplugAddVhostUserBlkDevice(vAttr *config.VhostUserDeviceAttrs,
} }
}() }()
// PCI address is in the format bridge-addr/device-addr eg. "03/02" bridgeSlot, err := vcTypes.PciSlotFromInt(bridge.Addr)
vAttr.PCIAddr = fmt.Sprintf("%02x", bridge.Addr) + "/" + addr if err != nil {
return err
}
devSlot, err := vcTypes.PciSlotFromString(addr)
if err != nil {
return err
}
vAttr.PCIPath, err = vcTypes.PciPathFromSlots(bridgeSlot, devSlot)
if err = q.qmpMonitorCh.qmp.ExecutePCIVhostUserDevAdd(q.qmpMonitorCh.ctx, driver, devID, vAttr.DevID, addr, bridge.ID); err != nil { if err = q.qmpMonitorCh.qmp.ExecutePCIVhostUserDevAdd(q.qmpMonitorCh.ctx, driver, devID, vAttr.DevID, addr, bridge.ID); err != nil {
return err return err
@ -1546,8 +1564,16 @@ func (q *qemu) hotplugNetDevice(endpoint Endpoint, op operation) (err error) {
} }
}() }()
pciAddr := fmt.Sprintf("%02x/%s", bridge.Addr, addr) bridgeSlot, err := vcTypes.PciSlotFromInt(bridge.Addr)
endpoint.SetPciAddr(pciAddr) if err != nil {
return err
}
devSlot, err := vcTypes.PciSlotFromString(addr)
if err != nil {
return err
}
pciPath, err := vcTypes.PciPathFromSlots(bridgeSlot, devSlot)
endpoint.SetPciPath(pciPath)
var machine govmmQemu.Machine var machine govmmQemu.Machine
machine, err = q.getQemuMachine() machine, err = q.getQemuMachine()

View File

@ -850,7 +850,7 @@ func (s *Sandbox) AddInterface(inf *pbTypes.Interface) (*pbTypes.Interface, erro
} }
// Add network for vm // Add network for vm
inf.PciAddr = endpoint.PciAddr() inf.PciPath = endpoint.PciPath().String()
return s.agent.updateInterface(inf) return s.agent.updateInterface(inf)
} }

View File

@ -13,6 +13,7 @@ import (
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/uuid" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/uuid"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// TapEndpoint represents just a tap endpoint // TapEndpoint represents just a tap endpoint
@ -20,7 +21,7 @@ type TapEndpoint struct {
TapInterface TapInterface TapInterface TapInterface
EndpointProperties NetworkInfo EndpointProperties NetworkInfo
EndpointType EndpointType EndpointType EndpointType
PCIAddr string PCIPath vcTypes.PciPath
RxRateLimiter bool RxRateLimiter bool
TxRateLimiter bool TxRateLimiter bool
} }
@ -45,14 +46,14 @@ func (endpoint *TapEndpoint) Type() EndpointType {
return endpoint.EndpointType return endpoint.EndpointType
} }
// PciAddr returns the PCI address of the endpoint. // PciPath returns the PCI path of the endpoint.
func (endpoint *TapEndpoint) PciAddr() string { func (endpoint *TapEndpoint) PciPath() vcTypes.PciPath {
return endpoint.PCIAddr return endpoint.PCIPath
} }
// SetPciAddr sets the PCI address of the endpoint. // SetPciPath sets the PCI path of the endpoint.
func (endpoint *TapEndpoint) SetPciAddr(pciAddr string) { func (endpoint *TapEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
endpoint.PCIAddr = pciAddr endpoint.PCIPath = pciPath
} }
// NetworkPair returns the network pair of the endpoint. // NetworkPair returns the network pair of the endpoint.

View File

@ -14,6 +14,7 @@ import (
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// TuntapEndpoint represents just a tap endpoint // TuntapEndpoint represents just a tap endpoint
@ -22,7 +23,7 @@ type TuntapEndpoint struct {
TuntapInterface TuntapInterface TuntapInterface TuntapInterface
EndpointProperties NetworkInfo EndpointProperties NetworkInfo
EndpointType EndpointType EndpointType EndpointType
PCIAddr string PCIPath vcTypes.PciPath
RxRateLimiter bool RxRateLimiter bool
TxRateLimiter bool TxRateLimiter bool
} }
@ -47,14 +48,14 @@ func (endpoint *TuntapEndpoint) Type() EndpointType {
return endpoint.EndpointType return endpoint.EndpointType
} }
// PciAddr returns the PCI address of the endpoint. // PciPath returns the PCI path of the endpoint.
func (endpoint *TuntapEndpoint) PciAddr() string { func (endpoint *TuntapEndpoint) PciPath() vcTypes.PciPath {
return endpoint.PCIAddr return endpoint.PCIPath
} }
// SetPciAddr sets the PCI address of the endpoint. // SetPciPath sets the PCI path of the endpoint.
func (endpoint *TuntapEndpoint) SetPciAddr(pciAddr string) { func (endpoint *TuntapEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
endpoint.PCIAddr = pciAddr endpoint.PCIPath = pciPath
} }
// NetworkPair returns the network pair of the endpoint. // NetworkPair returns the network pair of the endpoint.

View File

@ -10,6 +10,7 @@ import (
"github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/ns"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// VethEndpoint gathers a network pair and its properties. // VethEndpoint gathers a network pair and its properties.
@ -17,7 +18,7 @@ type VethEndpoint struct {
NetPair NetworkInterfacePair NetPair NetworkInterfacePair
EndpointProperties NetworkInfo EndpointProperties NetworkInfo
EndpointType EndpointType EndpointType EndpointType
PCIAddr string PCIPath vcTypes.PciPath
RxRateLimiter bool RxRateLimiter bool
TxRateLimiter bool TxRateLimiter bool
} }
@ -67,14 +68,14 @@ func (endpoint *VethEndpoint) Type() EndpointType {
return endpoint.EndpointType return endpoint.EndpointType
} }
// PciAddr returns the PCI address of the endpoint. // PciPath returns the PCI path of the endpoint.
func (endpoint *VethEndpoint) PciAddr() string { func (endpoint *VethEndpoint) PciPath() vcTypes.PciPath {
return endpoint.PCIAddr return endpoint.PCIPath
} }
// SetPciAddr sets the PCI address of the endpoint. // SetPciPath sets the PCI path of the endpoint.
func (endpoint *VethEndpoint) SetPciAddr(pciAddr string) { func (endpoint *VethEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
endpoint.PCIAddr = pciAddr endpoint.PCIPath = pciPath
} }
// NetworkPair returns the network pair of the endpoint. // NetworkPair returns the network pair of the endpoint.

View File

@ -13,6 +13,7 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types"
) )
// Long term, this should be made more configurable. For now matching path // Long term, this should be made more configurable. For now matching path
@ -30,7 +31,7 @@ type VhostUserEndpoint struct {
IfaceName string IfaceName string
EndpointProperties NetworkInfo EndpointProperties NetworkInfo
EndpointType EndpointType EndpointType EndpointType
PCIAddr string PCIPath vcTypes.PciPath
} }
// Properties returns the properties of the interface. // Properties returns the properties of the interface.
@ -58,14 +59,14 @@ func (endpoint *VhostUserEndpoint) SetProperties(properties NetworkInfo) {
endpoint.EndpointProperties = properties endpoint.EndpointProperties = properties
} }
// PciAddr returns the PCI address of the endpoint. // PciPath returns the PCI path of the endpoint.
func (endpoint *VhostUserEndpoint) PciAddr() string { func (endpoint *VhostUserEndpoint) PciPath() vcTypes.PciPath {
return endpoint.PCIAddr return endpoint.PCIPath
} }
// SetPciAddr sets the PCI address of the endpoint. // SetPciPath sets the PCI path of the endpoint.
func (endpoint *VhostUserEndpoint) SetPciAddr(pciAddr string) { func (endpoint *VhostUserEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
endpoint.PCIAddr = pciAddr endpoint.PCIPath = pciPath
} }
// NetworkPair returns the network pair of the endpoint. // NetworkPair returns the network pair of the endpoint.
@ -156,7 +157,7 @@ func (endpoint *VhostUserEndpoint) save() persistapi.NetworkEndpoint {
Type: string(endpoint.Type()), Type: string(endpoint.Type()),
VhostUser: &persistapi.VhostUserEndpoint{ VhostUser: &persistapi.VhostUserEndpoint{
IfaceName: endpoint.IfaceName, IfaceName: endpoint.IfaceName,
PCIAddr: endpoint.PCIAddr, PCIPath: endpoint.PCIPath,
}, },
} }
} }
@ -166,7 +167,7 @@ func (endpoint *VhostUserEndpoint) load(s persistapi.NetworkEndpoint) {
if s.VhostUser != nil { if s.VhostUser != nil {
endpoint.IfaceName = s.VhostUser.IfaceName endpoint.IfaceName = s.VhostUser.IfaceName
endpoint.PCIAddr = s.VhostUser.PCIAddr endpoint.PCIPath = s.VhostUser.PCIPath
} }
} }