Skip to content
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

Attaching XDP to VF #3651

Merged
merged 8 commits into from
May 26, 2023
Merged

Attaching XDP to VF #3651

merged 8 commits into from
May 26, 2023

Conversation

ami-GS
Copy link
Contributor

@ami-GS ami-GS commented May 25, 2023

Description

If XDP runs on VM with SR-IOV, trying to attach XDP to VF

Testing

Send/Recv is failing

Documentation

N/A

@ami-GS ami-GS requested a review from a team as a code owner May 25, 2023 18:39
@@ -78,6 +78,7 @@ typedef struct CXPLAT_DATAPATH {
typedef struct CXPLAT_INTERFACE {
CXPLAT_LIST_ENTRY Link;
uint32_t IfIndex;
uint32_t ActualIfIndex;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we should do this the other way around: we should track each interface's IfIndex and also an optional VfIfIndex. We should then not have any VFs directly in the interface table, and only explicitly VF-aware code needs to use the VfIfIndex.

Copy link
Contributor

@mtfriesen mtfriesen May 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if we can't find the VF for an interface, we could just set VfIfIndex to the regular IfIndex value, or some magic value like IFI_UNSPECIFIED.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently I'm not sure where the conventional IfIndex should be used and so use ActualIfIndex everywhere.
If we use VfIfIndex as VF-aware code, there whould require if-else where code refers IfIndex

for (int i = 0; i < (int) pIfTable->NumEntries; i++) {
MIB_IF_ROW2* pIfRow = &pIfTable->Table[i];
if (pIfRow->InterfaceAndOperStatusFlags.FilterInterface ||
!pIfRow->InterfaceAndOperStatusFlags.HardwareInterface ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the HardwareInterface or ConnectorPresent checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empirically these three flags are useful for filter out useless interfaces. Not sure other corner case

// NOTE: O(n^2), but realistically enough small
for (int j = 0; j < IfRowsCount; j++) {
struct IfMatching* pMatching = &IfMatching[j];
if (pIfRow->PhysicalMediumType == NdisPhysicalMedium802_3 &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to look at the physical mediums? This strikes me as being potentially very fragile.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also empirical point of view. However it should be impossible to identify which is VF if we don't use the PhysicalMediumType

@ami-GS
Copy link
Contributor Author

ami-GS commented May 25, 2023

Oh, test issue was only on my dev system. something corrupted in my side


CXPLAT_FRE_ASSERT(pIfTable->NumEntries <= 128);
BOOLEAN Initialized[128] = {0};
for (int i = 0; i < (int) pIfTable->NumEntries; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the MIB interface table for the outer loop could cause us to create XDP interfaces for interfaces that don't have an IP address at all, right? I am still leaning towards keeping the same outer loop (over adapter addresses) to pick which interfaces to use, but then use the MIB table for the inner loop to find an interface with a matching physical address.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it is covered by first flag check.
I was not 100% sure whether these flags is for whether having IP address or not. just empirically verified this check works (duonic and NetVSC and VF can pass through)

        if (pIfRow->InterfaceAndOperStatusFlags.FilterInterface ||
            !pIfRow->InterfaceAndOperStatusFlags.HardwareInterface ||
            !pIfRow->InterfaceAndOperStatusFlags.ConnectorPresent ||
            Initialized[i])
            if (Adapter->IfType == IF_TYPE_ETHERNET_CSMACD &&
                Adapter->OperStatus == IfOperStatusUp &&
                Adapter->PhysicalAddressLength == ETH_MAC_ADDR_LEN)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You meant use GetAdaptersAddresses as outer loop?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with GAA as outer loop. But if you really think based on your testing this is the way to go, feel free to "won't fix" this comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea works. let me quickly push it.

Comment on lines 1086 to 1087
CXPLAT_FRE_ASSERT(pIfTable->NumEntries <= 128);
BOOLEAN Initialized[128] = {0};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit unsure, but do we really need this array? I don't like the hard coded limit, but it seems more like an optimization that's not really necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to use std::bitset or heap allocated array. It is possible to remove this by checking Xdp->Interfaces linked list at beginning of outer loop whether there is adapter with same Mac address is already registered.

x is same mac address (VF and NetVSC) merged as one interface, then later

outer  |--->x             |
inner  |      ----->x     |
outer  |      -----o-->     |
inner  |                    |

o is skipped because it was marked as Initialized earlier

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure why we need to keep this at all? It's not a big deal if you search the whole array N^2, since it's so small.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be removed by using GAA for outer loop

@nibanks nibanks merged commit 707c1fa into main May 26, 2023
350 of 361 checks passed
@nibanks nibanks deleted the dev/daiki/xdp_attach_vf branch May 26, 2023 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants