-
Notifications
You must be signed in to change notification settings - Fork 29
Mctp bridge support #71
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
base: main
Are you sure you want to change the base?
Mctp bridge support #71
Conversation
Thanks for the contribution! I'll get to a proper review shortly. I have some pending changes that rework a lot of the peer, link and network allocation mechanisms. That shouldn't affect your code too much, but I'll request a rebase once that is merged. |
Sure no problem |
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.
So the main design point here is how we're handling the pool allocations. It looks like your particular use-case is around static allocations, which I'll focus on here.
As I mentioned in the dbus changes, we cannot add arguments without further version-compatiblity changes. After a bit of chatting with the team, I think a better approach would be to add a new dbus call to explicitly allocate a bridge and a predefined pool (which would include the pool size). Perhaps something like:
AllocateBridgeStatic(addr: ay, pool_start: y, pool_size: y)
- where the
Set Endpoint ID
response must match the expected pool size.
(we would also want purely-dynamic pools to be allocated from SetupEndpoint and friends, but that would result in a dynamic pool allocation. This dynamic pool would be defined either by a toml config option, or via a new TMBO dbus interface. However, we can handle those later, I think)
Would that work?
In general, can you add a bit more of an explanation / rationale as part of your commit messages, instead of just log output? There is some good guidance for commit messages up in the "Patch formatting and changelogs" section of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/5.Posting.rst |
We'll also need to consider the routing setup for bridged endpoints. Ideally we would:
the issue is that there is no kernel support for (2) at present: we need some kernel changes to implement gateway routes. It is possible to create "somewhat-fake" routes for those endpoints, using a neighbour table entry for each (bridged) peer that uses the bridge phys address, but that's a bit suboptimal. I'd prefer not to encode that hack into mctpd if possible. I do have a todo for the kernel changes necessary for that, sounds like I should get onto it! |
IIUC, 1 is what we can achieve with the tools we have today, right? For ex: add route to the bridge itself and then When you say sub-optimal, are you referring to the neighbour lookup that happens in When is the gateway support in kernel for MCTP nets planned? We can help if you have a design in mind. |
Hi Santosh,
Yes, but it requires a lot of workaround to set up.
That isn't adding a neighbour table entry though; just a route. USB is a little different in that there are no neighbour table entries required, because there is no physical addressing. For a bridge, using this scheme would require:
(for USB, we don't need (2) or (4), but that's purely a property of the transport type. We would need those to be supported in mctpd to allow other transport types like i2c). This would work, but it's messy.
No, the neighbour lookups happen in
Not so much faster, more tidier. With a gateway route, we would require:
No fake neighbour table entries are required - since the kernel just looks up the gateway physical address from the gateway's neighbour table entry.
I have it done - will push a development branch shortly. |
https://github.com/CodeConstruct/linux/tree/dev/forwarding |
Hi Jeremy, Thank you for the detailed response.
Ack, I see something like I2C would need a PHY address.
Ack. I should have said the neigh_lookup call that happens in route.c!
Thank you, that does seem cleaner. |
And for the userspace changes, my |
@jk-ozlabs : I think we agree that mctpd has to poll all allocated endpoints with a Get Endpoint ID periodically. I think the first thing we'd need to enable in order to do that is to make MCTP requests and responses asynchronous. Do you have a design in mind to make MCTP requests async (like via a request queue per allocated endpoint)? |
Just as a clarification - not all endpoints, but EIDs within allocated endpoint ranges, which have not yet been enumerated. And this is assuming we expect mctpd to automatically enumerate those bridged devices. I think the latter is reasonable, but we don't have a specific design point around that yet. With that in mind, yes, we probably want to make that async, as those requests are likely to not have a response, and therefore we're at worst-case waiting time. In terms of design: we probably don't want a We don't necessarily need to keep much state for that polling mechanism (ie, between request and response) - receiving a Get Endpoint ID response for anything in that range would trigger the enumeration process. |
Wouldn't we also want to poll enumerated endpoints under the bridge to determine when they "went away"?
Ack. How periodically do you think we should check? Same as the logic for determining when to set endpoint state as degraded (TReclaim/2)? |
No, and we don't do that with directly-attached endpoints either. The current philosophy is that we don't care if an endpoint disappears, until some application calls [I'm okay with revisiting this, or handling bridged endpoints differently, if there's a compelling argument for doing so]
Treclaim/2 seems a bit too often to me, but might be fine as a starting point. I suspect that an ideal approach would be to poll more regularly when a bridge pool is initially allocated, then reduce frequency. However, let's not complicate the initial implementation too much here, and just use a configurable constant. |
.. and speaking of |
So we have a case where we will have to call allocate endpoint ID on the bridge device when not all of its downstream devices are available. In such a case, how do you think we can determine when those downstream EIDs become available unless we poll? |
I am suggesting we poll. Just that we then stop polling once we enumerate the endpoint. |
Ah, ack, then. |
It will need some rework as currently it assumes the peer is a neighbour and uses physical addressing for |
Thanks for that, Andrew. There might be some commonality between the peers undergoing (non-local) recovery, and those EIDs that are behind a bridge, but not-yet enumerated. If a The same should occur for a |
Yep, that sounds sensible. |
686395a
to
f6d0b8a
Compare
Thank you all for taking out time to look into the PR, I've addressed to the asked comments on previous commit, added new commit for MCTP Bridge design doc, need to push Polling mechanism now |
Thanks for the updates! A couple of comments:
|
bf8f331
to
fa59ed7
Compare
Hello Jeremy Thank you for looking over the commits, based on your comment # 1 I have removed the new .md file which captured MCTP Bridge support details on PR and updated the existing mctpd.md file with new information about dbus api AssignBridgeStatic. Regarding user consumable document, I'm not much sure what this could be, if you could let me know what this document should be I can create one and update the PR. I recently got the permission for PMCI WG, have glanced over what was stated on issue #1540, basically the Idea is to split the BusOwner EID pool and segregate a chunk of eids for Bridge's downstream pool on the higher end of Busowner pool while keeping lower end for non-bridge devices. This would be helpful for Dynamic EID assignment of downstream pool devices incase multiple Bridge's are there under same network. My current implementation involves finding of contiguous eid chunk of min(requested pool size, bridge's pool size capability) from available BusOwner's pool but we begin looking from Asked pool_start (Static) or from next to Bridge's EID (Dynamic) and we look till we get right sized chunk and mark that eid as pool_start. I did based this from the same line of spec for which you raised the issue.
I can create a new PR for Endpoint polling if thats what you mean and skip for this PR. Also for adding route for the downstream endpoint to Bridge, we would need your implementation implementation to be merged for both linux kernel and mctpd. Internally I've tested my polling logic with your pulled changes, but for this PR I haven't picked them up so discovery of downstream EID via LearnEndpoint would probably not be possible with only this PR
I've updated the patch set now for easier review, hope it helps, let me know if I can do anything else to further ease the review. Thanks for your .clang format, once that is pushed I would reply those onto my change |
fa59ed7
to
2766a52
Compare
I see, I might have misunderstood you, so ask is about failure in Allocate Endpoint ID control command but Bridge's own eid has been assigned. So that should remain (we are on same page here, changes are dong the same). What I meant earlier was with failure of setup endpoint itself will lead to removal of peer (already part of design)
Need one suggestion here too, since we publish the peer right after successfull Setup endpoint id, so by this time we have one assumed pool size of max_pool_size (toml config), this will create new interface
|
Yes. Sorry, my fault with the ambiguous wording there: should have been "failure from Allocate Endpoint IDs" :) |
Thanks I have update my previous comment with questions, #71 (comment) |
Hm, good question! I would say that the important thing is that external consumers of the (Bridge1) interface are able to use the interface functionality immediately, and that the data presented is correct. So, I think that the correct approach would be to publish the Bridge1 interface once the pool assignment is finalised. This would mean waiting until the Allocate Endpoint IDs command has succeeded, and after the gateway range route has been added. |
6a4c3a1
to
679e177
Compare
Alright, I've updated the logic and added related test case. Thank you !! |
Hello Jeremy, Thank you taking out time in the reviews, all comments have been addressed, open to any further modifications needed. |
OK cool. I'll take a look through soon. |
src/mctpd.c
Outdated
bug_warn("%s: Bad old net %d", __func__, netid); | ||
return -EPROTO; | ||
} | ||
if (is_eid_in_bridge_pool(n, ctx, eid)) { |
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 is creating two separate conflict checks: in add_peer()
, we check that the EID is not occupied by a direct peer, and here we check that the EID is not occupied by a bridge range.
Would it make sense to unify these and call a common is_eid_available()
from add_peer()
?
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 would, I'll update
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.
on second thought, everytime you add a peer (in future when we poll and see endpoint presence and then create peer for it) you'll have this check while doing add_peer(), but this time downstream eid (for which you are creating peer) will anyways belong to some pool space which would invalidate the function everytime.
So we would then need a way to distinguish:
“Globally free”: EID not already used by a direct peer
“Allowed for this bridge”: EID is inside the correct bridge’s pool (and not inside another bridge’s pool)
Which is why I feel keeping these separate makes sense, plus we only need this to be checked while static eid assignment is involved
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.
perhaps in that case we should ensure that if the EID is allocated as a bridge range, then it is bridged through that specific peer?
There may be other paths that we need to consider. For example, it shouldn't be possible for LearnEndpoint to claim an EID in a bridged range.
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 may be other paths that we need to consider. For example, it shouldn't be possible for LearnEndpoint to claim an EID in a bridged range.
LearnEndpoint method under au.com.codeconstruct.MCTP.Network1
interface was purposed to be used for already routed endpoints which in a way could also be used for bridged endpoints as stated in the mctpd.md
We also had relief as polling based downstream endpoint implementation is yet to be added and LearnEndpoints was a way through which downstream endpoints could be exposed too under d-bus.
but I see in current implementation we don't really have a way to check if there is a route to that endpoint for which we have called LearnEndpoint other than checking peer itself is present in the maintained structure for that eid via find_peer_by_addr
method. May be we should integrate all this checks for eid being part of bridge to this method itself?
perhaps in that case we should ensure that if the EID is allocated as a bridge range, then it is bridged through that specific peer?
do you mean don't let any external methods to engage in taking up that eid and only polling mechanism is a way to expose endpoint on dbus? if so then we need that check right which I added in AssignEndpointStatic method?
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.
LearnEndpoint method under
au.com.codeconstruct.MCTP.Network1
interface was purposed to be used for already routed endpoints which in a way could also be used for bridged endpoints as stated in themctpd.md
I was more referring to BusOwner1.LearnEndpoint here, which is another facility (alongside LearnEndpointStatic) which may consume an eid without the bridge pool checking, as it calls add_peer()
directly.
Ideally, we would want to check all EID allocations via add_peer(). That would involve allowing EID assignments that have addresses that we "exepect": if they're routed behind some other peer that we know about, it should use an EID in that pool's range. If not, we should reject the assignment.
As you say though, we may be missing some information to properly do that. We can defer this checking to later if necessary.
However, In the case of BusOwner1.LearnEndpoint though, we know that this is a directly-connected peer (we are addressing it physically), so should probably disallow any learnt EID in a pool range in that path too.
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 more referring to BusOwner1.LearnEndpoint here, which is another facility (alongside LearnEndpointStatic) which may consume an eid without the bridge pool checking, as it calls
add_peer()
directly.
So all other usecase such as AssignStaticEid SetupEndpoint LearnEndpoint(BusOwner if)
requires this check i.e if eid under discussion belongs to some peer pool space then reject the assignment. But on contrary LearnEndpoint (Network if)
and in future Bridge Polling would actually want the EID to be part of already available routes or part of some bridge's pool space.
LearnEndpoint (Network if)
was implemented under assumption that MCTP network would have direct-connected pee only, but we might need to refine it more due to introduction of Bridge support.
As a proposal I think we need to implement a utility method under mctp-netlink.c
to fetch out this information about eid is routed to some interface/bridge eid or not, for full LearnEndpoint method functionality, something I could pick for future PR. (open to any other suggestions to handle this)
so for now I've made the check within add_peer()
to reject the assignment if eid falls within any of pool space.
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.
So all other usecase such as
AssignStaticEid SetupEndpoint LearnEndpoint(BusOwner if)
requires this check i.e if eid under discussion belongs to some peer pool space then reject the assignment. But on contraryLearnEndpoint (Network if)
and in future Bridge Polling would actually want the EID to be part of already available routes or part of some bridge's pool space.
Yes, exactly.
LearnEndpoint (Network if)
was implemented under assumption that MCTP network would have direct-connected pee only, but we might need to refine it more due to introduction of Bridge support.
No, it was implemented under the assumption that there is some existing route to the device, and it doesn't matter whether directly-connected or via a gateway. The primary use-case for this is for bridged endpoints though.
As a proposal I think we need to implement a utility method under
mctp-netlink.c
to fetch out this information
We have some information on the bridge structure, but only for bridges that are managed by mctpd. You're correct - we would need the netlink data for other (non-mctp-managed) bridge routes.
(A valid design here may be that we only support bridging through mctp-managed bridges)
So, there's a bit of complexity here.
so for now I've made the check within
add_peer()
to reject the assignment if eid falls within any of pool space.
This may break an intended usage of Network1.LearnEndpoint
, no? where:
- a bridge is managed by mctpd
- a user calls
Network1.LearnEndpoint
on a peer behind that bridge
ie., this case is required for scenarios where the bridged endpoints are not automatically polled by mctpd.
In general: I am fine with doing a partial implementation now - we don't need to have all scenarios covered at the moment. We do need to make sure we don't "paint ourselves into a corner" though, where a future change would break existing supported usage.
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.
No, it was implemented under the assumption that there is some existing route to the device, and it doesn't matter whether directly-connected or via a gateway. The primary use-case for this is for bridged endpoints though.
What I meant earlier was, we would still need to find a way to identify if routes to that eid (argument of Network1.LearnEndpoint
)even exist or not. Because in current implementation (without my patch) we are simply checking if peer for that eid exists, if doesn't exist we still blindly go ahead with eid consumption and populating d-bus tree.
This may break an intended usage of
Network1.LearnEndpoint
, no? where:
- a bridge is managed by mctpd
- a user calls
Network1.LearnEndpoint
on a peer behind that bridge
Yes this check under add_peer()
would break the intended Network1.LearnEndpoint only for bridged eids, I wanted to avoid the need to manipulate add_peer() signature right now and may be address this better on next MCTP Bridge Poll PR, but I agree on make sure we don't "paint ourselves into a corner" though, where a future change would break existing supported usage.
so I'll update this. But then again will this method will only focus on endpoints which are part of any bridge? But random unbridged EID(which seem to be the case for now with which this method, as it ends up populating on dbus for such eid too) will be blocked ?(whether they have the routes or not doesn't matter). Ideally it should have been route checks (missing implementation) which would decide to take a call for this.
With this at least our intention we only support bridging through mctpd-managed bridges
would be taken care of (hopefully) but as you said too, we might need some netlink data for (non mctpd managed) bridged routes.
Will update the mctpd.md
document about managing only MCTPD managed bridges
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.
updated the patch, to avoid check altogether when Network1.LearnEndpoint is called, so that we don't break things for it for now.
210b2a5
to
2a311f8
Compare
Add MCTP control message structures for the ALLOCATE_ENDPOINT_ID command to support bridge endpoint EID pool allocation. Signed-off-by: Faizan Ali <[email protected]>
2a311f8
to
4cf636d
Compare
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.
Looking good. I have some comments on some minor things, and would like to do bit of experimentation on:
- whether we can make Network1.LearnEndpoint more accurately-selective on the bridge states
- adding further test cases
I will follow up with the outcomes of those shortly; likely as proposed additions to the series.
/* Returns the newly added peer. | ||
* Error is -EEXISTS if it exists */ | ||
static int add_peer(struct ctx *ctx, const dest_phys *dest, mctp_eid_t eid, | ||
uint32_t net, struct peer **ret_peer) | ||
uint32_t net, struct peer **ret_peer, bool net_learn) |
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 argument name is not clear, and has no documentation.
I get that this indicates that the call comes from the Network1.LearnEndpoint dbus call, but that information does not help with understanding how the function & argument behaves. More on this below though...
/* only LearnEndpoint methods of au.com.codeconstruct.MCTP.Network1 | ||
* interface will approve peer structure if eid belongs to a bridge | ||
* pool space else never allow. | ||
*/ |
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.
Not sure I agree with this behaviour. I think we can do a bit better by looking up the peer and checking that the EID is valid with that extra context.
However, I'm happy to take a look at that - I'll work on a proposed change.
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.
checking that the EID is valid : would you be updating with logic to check if eid under question even has any routes?
Add support for MCTP bridge endpoints that can allocate pools of EIDs for downstream endpoints. We assume each AssignEndpoint d-bus call will be for an MCTP bridge, with this we allocate/reserve a max_pool_size eid range contiguous to bridge's own eid. Later this pool size is updated based on SET_ENDPOINT_ID command response. - for static eid assignment via AssignEndpointStatic d-bus call, add check if eid is part of any other bridge's pool range. [Fixup and requested change from Jeremy Kerr <[email protected]>] Signed-off-by: Faizan Ali <[email protected]> Signed-off-by: Jeremy Kerr <[email protected]>
I am keeping my pending changes in a If you want to squash any of those into your series, feel free, just let me know first. |
Thank you for the commits. |
4cf636d
to
bb3f965
Compare
Add implementation for the MCTP ALLOCATE_ENDPOINT_ID control command to enable bridges to allocate EID pools for downstream endpoints. Update gateway route for downstream EIDs Signed-off-by: Faizan Ali <[email protected]>
* updated mctpd.md with new mctp bridge support for dynamic eid assignment from AssignEndpoint d-bus call Signed-off-by: Faizan Ali <[email protected]>
Add new test for validating AssignEndpoint D-Bus method to verify bridge endpoint EID allocation being contiguous to its downstream eids. Add Allocate Endpoint control message support with new endpoint property for allocated pool size also assign dynamic eid contiguous to bridge during Allocate Endpoint control message. Signed-off-by: Faizan Ali <[email protected]>
New endpoint object interface au.com.codeconstruct.MCTP.Bridge1 which will capture details of bridge type endpoint such as pool start, pool end. Update test framework with new test methods to validate bridge pool assignemnt. Signed-off-by: Faizan Ali <[email protected]>
Currently, test_assign_dynamic_bridge_eid test both the bridge assignment, and conflicts against static EIDs. Instead, split this into two smaller tests, which provide a base for future bridge-conflict tests. Signed-off-by: Jeremy Kerr <[email protected]>
In addition to the static assignments, we want to ensure that LearnEndpoint does not result in EID conflicts. Signed-off-by: Jeremy Kerr <[email protected]>
bb3f965
to
d6d11e3
Compare
OK, I have pushed by review branch again: main...jk-ozlabs:mctp:review/bridge . Please have a look at let me know if you have any objections. I am happy to merge this as it stands, but I am also okay if you would like to squash changes into your original series. If you do so, please keep the additional patches (ie., those after main...jk-ozlabs:mctp:review/bridge) as-is. If you need to modify anything (ie, more than just squashing within that series) please do so as new commits, so we can both keep in sync. |
This PR aims to introduce ALLOCATE_ENDPOINT_ID message support along with MCTP Bridge endpoint into the existing peer structure.