diff --git a/pkg/pillar/cmd/domainmgr/domainmgr.go b/pkg/pillar/cmd/domainmgr/domainmgr.go index 24c4fe67a7f..5fdff4a6760 100644 --- a/pkg/pillar/cmd/domainmgr/domainmgr.go +++ b/pkg/pillar/cmd/domainmgr/domainmgr.go @@ -2939,6 +2939,10 @@ func updatePortAndPciBackIoBundle(ctx *domainContext, ib *types.IoBundle) (chang ib.Type, ib.Phylabel, ib.AssignmentGroup, isPort, keepInHost, len(list)) anyChanged := false for _, ib := range list { + if ib.UsbAddr != "" { + // this is usb device forwarding, so usbmanager cares for not passing through network devices + continue + } changed, err := updatePortAndPciBackIoMember(ctx, ib, isPort, keepInHost) anyChanged = anyChanged || changed if err != nil { @@ -3011,7 +3015,7 @@ func updatePortAndPciBackIoMember(ctx *domainContext, ib *types.IoBundle, isPort ib.IsPCIBack = false // Verify that it has been returned from pciback _, err = types.IoBundleToPci(log, ib) - if err != nil { + if err != nil || ib.UsbAddr != "" { err = fmt.Errorf("adapter %s (group %s type %d) PCI ID %s not found: %v", ib.Phylabel, ib.AssignmentGroup, ib.Type, ib.PciLong, err) diff --git a/pkg/pillar/types/assignableadapters.go b/pkg/pillar/types/assignableadapters.go index e979cd228bf..6763fa61791 100644 --- a/pkg/pillar/types/assignableadapters.go +++ b/pkg/pillar/types/assignableadapters.go @@ -447,6 +447,19 @@ func (aa *AssignableAdapters) CheckBadAssignmentGroups(log *base.LogObject, PCIS if ib.AssignmentGroup == "" || ib2.AssignmentGroup == ib.AssignmentGroup { continue } + if ib.UsbAddr != "" || ib2.UsbAddr != "" { + usbAddr1 := strings.TrimLeft(ib.UsbAddr, "0") + usbAddr2 := strings.TrimLeft(ib2.UsbAddr, "0") + if usbAddr1 == usbAddr2 { + err := fmt.Errorf("CheckBadAssignmentGroup: %s same USB address as %s; UsbAddr %s vs %s", + ib2.Ifname, ib.Ifname, usbAddr1, usbAddr2) + log.Error(err) + ib.Error = err.Error() + ib.ErrorTime = time.Now() + changed = true + } + continue + } if PCISameController != nil && PCISameController(ib.PciLong, ib2.PciLong) { err := fmt.Errorf("CheckBadAssignmentGroup: %s same PCI controller as %s; pci long %s vs %s", ib2.Ifname, ib.Ifname, ib2.PciLong, ib.PciLong) @@ -481,6 +494,9 @@ func (aa *AssignableAdapters) ExpandControllers(log *base.LogObject, list []*IoB ib2.Phylabel, ib2.PciLong) continue } + if ib.UsbAddr != "" || ib2.UsbAddr != "" { + continue + } if PCISameController != nil && PCISameController(ib.PciLong, ib2.PciLong) { log.Warnf("ExpandController found %s matching %s; long %s long %s", ib2.Phylabel, ib.Phylabel, ib2.PciLong, ib.PciLong) diff --git a/pkg/pillar/types/ifnametopci.go b/pkg/pillar/types/ifnametopci.go index dc9450f4f16..dd50f4ab9cc 100644 --- a/pkg/pillar/types/ifnametopci.go +++ b/pkg/pillar/types/ifnametopci.go @@ -12,6 +12,7 @@ import ( "os" "path" "regexp" + "strconv" "strings" "github.com/lf-edge/eve/pkg/pillar/base" @@ -22,10 +23,32 @@ import ( const basePath = "/sys/class/net" const pciPath = "/sys/bus/pci/devices" +// ExtractUSBBusnumPort extracts busnum and port number out of a sysfs device path +func ExtractUSBBusnumPort(path string) (uint16, string, error) { + var busnum uint16 + + re := regexp.MustCompile(`\/usb\d+(\/\d+\-[\d\.]+)*(\/(\d+)\-([\d\.]+))\/`) + + matches := re.FindStringSubmatch(path) + if len(matches) < 3 { + return busnum, "", fmt.Errorf("could not extract usb portnum from %s", path) + } + port := matches[len(matches)-1] + busnumString := matches[len(matches)-2] + busnum64, err := strconv.ParseUint(busnumString, 10, 16) + if err != nil { + return 0, port, fmt.Errorf("could not extract usb busnum from %s", path) + } + busnum = uint16(busnum64) + + return busnum, port, nil +} + // Returns the long PCI IDs -func ifNameToPci(log *base.LogObject, ifName string) (string, error) { +func ifNameToPciAndUsbAddr(log *base.LogObject, ifName string) (string, string, error) { // Match for PCI IDs re := regexp.MustCompile("([0-9a-f]){4}:([0-9a-f]){2}:([0-9a-f]){2}.[ls0-9a-f]") + var usbAddr string ifPath := basePath + "/" + ifName devPath := ifPath + "/device" info, err := os.Lstat(devPath) @@ -34,7 +57,7 @@ func ifNameToPci(log *base.LogObject, ifName string) (string, error) { if !os.IsNotExist(err) { log.Errorln(err) } - return "", err + return "", usbAddr, err } // Try alternate since the PCI device can be kethN // if ifName is ethN @@ -46,47 +69,52 @@ func ifNameToPci(log *base.LogObject, ifName string) (string, error) { if !os.IsNotExist(err) { log.Errorln(err) } - return "", err + return "", usbAddr, err } log.Noticef("ifNameToPci using alternate %s", ifName) } if (info.Mode() & os.ModeSymlink) == 0 { log.Errorf("Skipping non-symlink %s\n", devPath) - return "", fmt.Errorf("Not a symlink %s", devPath) + return "", usbAddr, fmt.Errorf("Not a symlink %s", devPath) } link, err := os.Readlink(devPath) if err != nil { - return "", err + return "", usbAddr, err + } + + busnum, portnum, err := ExtractUSBBusnumPort(link) + if err == nil { + usbAddr = fmt.Sprintf("%d:%s", busnum, portnum) } target := path.Base(link) if re.MatchString(target) { - return target, nil + return target, usbAddr, nil } log.Noticef("Not PCI %s - try fallback for %s", target, ifName) // Try fallback to handle nested virtualization info, err = os.Lstat(ifPath) if err != nil { log.Noticef("Fallback failed: %s", err) - return target, fmt.Errorf("Not PCI %s", target) + return target, usbAddr, fmt.Errorf("Not PCI %s", target) } if (info.Mode() & os.ModeSymlink) == 0 { log.Noticef("Fallback not symlink") - return target, fmt.Errorf("Not PCI %s", target) + return target, usbAddr, fmt.Errorf("Not PCI %s", target) } link, err = os.Readlink(ifPath) if err != nil { log.Noticef("Fallback readlink failed: %s", err) - return target, fmt.Errorf("Not PCI %s", target) + return target, usbAddr, fmt.Errorf("Not PCI %s", target) } link = path.Clean(link) components := strings.Split(link, "/") for _, c := range components { if re.MatchString(c) { log.Noticef("Fallback found %s", c) - return c, nil + return c, usbAddr, nil } } - return target, fmt.Errorf("Not PCI %s", target) + return target, usbAddr, fmt.Errorf("Not PCI %s", target) } // Returns the long PCI IDs for Virtual function @@ -210,7 +238,7 @@ func IoBundleToPci(log *base.LogObject, ib *IoBundle) (string, error) { //nolint if ib.Type == IoNetEthVF { l, err = vfIfNameToPci(ib.Ifname) } else { - l, err = ifNameToPci(log, ib.Ifname) + l, ib.UsbAddr, err = ifNameToPciAndUsbAddr(log, ib.Ifname) } rename := false if err == nil { @@ -239,7 +267,7 @@ func IoBundleToPci(log *base.LogObject, ib *IoBundle) (string, error) { //nolint return long, err } } else { - long, err = ifNameToPci(log, ib.Ifname) + long, ib.UsbAddr, err = ifNameToPciAndUsbAddr(log, ib.Ifname) if err != nil { return long, err }