-
Couldn't load subscription status.
- Fork 41
allow use of already enabled sr-iov virtual functions in xapi managed sr-iov networks #173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Thanks for the detailed explanation. I think it would be better to try to enable the maximum number of VFs, and only if that fails fall back to checking how many VFs we have enabled (and if that is >0 as in your code then succeed). |
|
Please also add a Signed-off-by line to your commit, see the error from the DCO bot and https://elinux.org/Developer_Certificate_Of_Origin |
|
We also have the Modprobe configuration option, which is handled just above Sysfs in the same function, which comes with another valid return value for the "success" case: We could extend this method to support the cards that you mentioned, so that xcp-networkd has the power to enable VFs in case they aren't yet, by updating the modprobe file. However, I'm not sure if it's worth doing that if, as you say, VFs are enabled by default and we can count on that. |
|
Thank you everybody for the investment! edit: fixed a word and clarification |
|
I just found out, that what I wrote is not true! Excuse me please.
The modprobe interface does in fact not rely on a working sysfs interface implementation! Reading the code again, it should, as you @robhoes stated, in fact rely on the the functions being enabled directly after reboot. When a templated modprobe config is detected, the "modprobe branch" is taken and no "escaping" to the sysfs configuration code is possible. To come back to the original issue: I think the way proposed by @edwintorok (and in the pull request) would be a solution that works in most cases. In my opinion, a clean solution could be as follows:
This would require an additional return value, as neither the modprobe not the sysfs configuration were successful. sysfs would in fact be used to determine the actual number of virtual functions, but would not be used for configuration. Adding an additional return value, e.g. Any thoughts on this? |
I don't think that's true for Intel/igb, as you'll never get into the |
|
Yes, what you wrote at the end looks like a clean way to do it. Unfortunately, it would require changing three repos: besides xcp-networkd and xen-api, you need to define the new return code in xcp-idl ( In xen-api, you should also add the |
|
Thank you for the pointers! That should be doable. |
|
Yes, that's how we normally do it. |
…etworks managed by xapi; network server failed to use already enabled virtual functions, for network adapters that do not allow configurations via sysfs interface, but require manual configuration by user Signed-off-by: Arne Wendt <arne.wendt@tuhh.de>
|
The proposed solution of:
This may be a special problem of the Mellanox driver (mlx4_core) thoug. I modified the approach to something similiar as @edwintorok proposed as an addition to the first pull request:
Trying to deduce the configuration mode only happens when enabling sriov, disabling does not call updates and pull requests for xen-api and xcp-idl will be filed and referenced shortly
|
networkd/network_server.ml
Outdated
| with e -> let msg = Printf.sprintf "Error: trying sysfs SR-IOV interface failed with exception %s on device: %s" (Printexc.to_string e) dev in Error(Other, msg) ), | ||
| present_numvfs | ||
| with | ||
| | Ok _ , _ -> debug "%s SR-IOV on a device: %s via sysfs" op dev; Ok Sysfs_successful |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was a bit surprised that the code would not use error and return (as I would expect in monadic code) but the existing code does not use it either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to stick to the original code for error handling and return types, to not mess with other code portions and keep currently expected behavior.
networkd/network_server.ml
Outdated
| end | ||
| else | ||
| begin | ||
| Sysfs.unbind_child_vfs dev >>= fun () -> Sysfs.set_sriov_numvfs dev 0 >>= fun _ -> debug "%s SR-IOV on a device: %s via sysfs" op dev; Ok Sysfs_successful |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please shorten lines by using
… >>= fun () ->
… >>= fun _ ->
…
|
@lindig: I hope I could address all of your comments with the latest commit. Thanks for all the input and pointers! I'm sorry for the delay, but was occupied with getting our team working in the current situation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks all good to me. Any comments from @robhoes who knows the domain better than I do.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Travis build is broken - please take a look
|
This should be expected, or not? |
networkd/network_server.ml
Outdated
| match (Sysfs.get_sriov_maxvfs dev >>= fun maxvfs -> maxvfs |> Sysfs.set_sriov_numvfs dev), present_numvfs | ||
| with | ||
| | Ok _ , _ -> debug "%s SR-IOV on a device: %s via sysfs" op dev; Ok Sysfs_successful | ||
| | _, _ -> debug "SR-IOV/VFs %sd manually on device: %s" op dev; Ok Manual_successful |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are not actually matching on present_numvfs. Don't you need at least | _, present -> when present > 0? Or better, check that it is equal to maxvfs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are absolutely right! When adapting the code I was more amazed by the fact that I may integrate the exception handling in the match, and forgot to think twice about the actual semantics.
The code now does something very different and it just tested fine on my machine, as currently enabled VFs and maximum number of VFs is equal.
I am currently thinking about a way to rewrite the code with my new knowledge about matching of exceptions, but for now did not come to a conclusion. I think the old way of implementing this + the "style-fixes" will be the way to go.
I hope to come to a conclusion within the next hour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it is a problem is the number of VFs is smaller than the max. At least, I hope that we do the accounting, when allocating VFs to VMs, based on the current number rather than the max. As long as the number is larger than zero. So the when clause I suggested above may be enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And to actually reply to your question:
Don't you need at least
| _, present -> when present > 0? Or better, check that it is equal tomaxvfs?
I would need to check if it is >0 or <>0. Problem here is, that the code to set the new number of VFs is expected to throw. I have to match for exception and > 0, or like in the last version, match exception, 0 first and know that anything matched afterwards can only be exception and > 0. This was the reason I built the Ok() and Error() returning try-catch-construct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| _, present -> when present > 0
So thewhenclause I suggested above may be enough?
The attempt to set a new number of VFs may return with Error _, when a failure is handled internally by the called methods, or may just throw. Both, exception and Error, are acceptable in the case of present_numvfs > 0.
As far as I understand, the wildcard _ does not match exceptions. But trying to match multi case on | exception _ | Error _ when present_numvfs > 0 -> ... is unfortunately not supported either (no mixing of value and exception patterns when using when-guard).
Including the exception in the match is possible, but for now I cannot find a solution that is actually cleaner and more concise than the original variant. Combining Error and exception into one match case by catching exceptions beforehand, effectively avoids code duplication.
It is possible to get rid of the try-catch and matching a tuple, but the match is not any more readable, due to the reason given above. Example:
| Ok _ -> debug [...]; Ok
| Error _ when present_numvfs > 0 -> debug [...]; Ok Manual_successful
| exception _ when present_numvfs > 0 -> debug [...]; Ok Manual_successful
| Error err -> Error err
| exception e -> let msg = [...]; Error(Other, msg)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is correct that a single pattern either matches a normal value or an exception, but never both. I still think a collection of patterns is easier to reason about and easier to extend than if-then-else or try-with chains. So I do like the above but would not insist on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, my take at the implementation with the least redundancy would be as follows:
let man_successful () =
debug "SR-IOV/VFs %sd manually on device: %s" op dev;
Manual_successful
in
if enable then
begin
let present_numvfs = Sysfs.get_sriov_numvfs dev in
match Sysfs.get_sriov_maxvfs dev >>= fun maxvfs -> maxvfs |> Sysfs.set_sriov_numvfs dev
with
| Ok _ -> debug "%s SR-IOV on a device: %s via sysfs" op dev; Ok Sysfs_successful
| Error _ when present_numvfs > 0 -> Ok (man_successful ())
| exception _ when present_numvfs > 0 -> Ok (man_successful ())
| Error err -> Error err
| exception e ->
let msg = Printf.sprintf "Error: trying sysfs SR-IOV interface failed with exception %s on device: %s" (Printexc.to_string e) dev in
Error(Other, msg)
endshould be equivalent to following code with doublings, but without introduction of an additional function:
if enable then
begin
let present_numvfs = Sysfs.get_sriov_numvfs dev in
match Sysfs.get_sriov_maxvfs dev >>= fun maxvfs -> maxvfs |> Sysfs.set_sriov_numvfs dev
with
| Ok _ -> debug "%s SR-IOV on a device: %s via sysfs" op dev; Ok Sysfs_successful
| Error _ when present_numvfs > 0 -> debug "SR-IOV/VFs %sd manually on device: %s" op dev; Ok Manual_successful
| exception _ when present_numvfs > 0 -> debug "SR-IOV/VFs %sd manually on device: %s" op dev; Ok Manual_successful
| Error err -> Error err
| exception e ->
let msg = Printf.sprintf "Error: trying sysfs SR-IOV interface failed with exception %s on device: %s" (Printexc.to_string e) dev in
Error(Other, msg)
endor, using try catch:
begin
let present_numvfs = Sysfs.get_sriov_numvfs dev in
match
( try Sysfs.get_sriov_maxvfs dev >>= fun (maxvfs) -> maxvfs |> Sysfs.set_sriov_numvfs dev
with e ->
let msg = Printf.sprintf "Error: trying sysfs SR-IOV interface failed with exception %s on device: %s" (Printexc.to_string e) dev in
Error(Other, msg) ),
present_numvfs
with
| Ok _ , _ -> debug "%s SR-IOV on a device: %s via sysfs" op dev; Ok Sysfs_successful
| Error(err), 0 -> Error(err)
| _, _ -> debug "SR-IOV/VFs %sd manually on device: %s" op dev; Ok Manual_successful
endif there are any preferences, tell me and I can commit the code
edit: updated code snippet 1, as there were errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the first option of the three, if that helps you unlock the work :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks good apart from what I commented above about present_numvfs.
|
I think that you need a rebase as well, since Edwin's commit shows up. |
…bled sr-iov/vfs. manual configuration is assumed if: no modprobe template is present, setting numvfs to maxvfs via sysfs interface fails, but vfs are present. a new return `Manual_successful` is introduced. **this patch depends on updated versions of:** * xen-api * xcp-idl Signed-off-by: Arne Wendt <arne.wendt@tuhh.de> clean code Signed-off-by: Arne Wendt <arne.wendt@tuhh.de> fix broken functionality after code clean and style change Signed-off-by: Arne Wendt <arne.wendt@tuhh.de>
|
As there have been no further comments on the style of the implementation, I'm following what I think to be the preferences of @lindig and @psafont. Implementation snippet #1, as the now chosen one, included errors; snippet has been updated above with working code. Code has been updated and functionality restored. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good now, thanks.
|
Unfortunately, there appears to be a merge conflict. |
|
I believe Travis failures are expected because of mutual dependencies between pull requests. |
|
I've rebased it and fixed the conflict: #177. I'll close this PR now in favour of the other. |
When creating and enabling SR-IOV networks, using xapi, xcp-networkd tries to enable virtual functions on the physical adapter using sysfs interface. xcp-networkd tries to set the number of VFs equal to the maximum number of of virtual functions (
sriov_totalvfs). When using adapters that do not fully implement the sysfs interface for SR-IOV configuration, currently, enabling fails. Enabling virtual functions via sysfs is executed even if the virtual functions are already enabled. Failing to execute the enabling procedure (even though unnecessary, when VFs are already enabled), prevents successful creation of an SR-IOV network.An example are Mellanox ConnectX-3 cards, using
mlx4_coredriver: Virtual functions can be configured in firmware or using modprobe config. All configured virtual interfaces are enabled by default. The driver, though, does not allow configuration using the sysfs interface, and trying to write tosriov_numvfsfails; thus preventing successful creation and enabling of a SR-IOV network - even though, the virtual functions are enabled.This pull request allows to use network adapters that require manual enabling (do not fully support configuration via sysfs interface) with xapi/xcp-networkd managed SR-IOV networks, by checking for enabled VFs on the interface, prior to trying to enable them. When virtual functions are already enabled on the interface, enabling is skipped, a debug message about already enabled virtual functions is logged and
config_sriovreturns withOk Sysfs_successful(Ok Sysfs_successfulbeing the only valid return value for successfully enabling virtual functions).