On 20/03/2025 14:51, Ilya Maximets wrote: > On 3/20/25 09:32, Roi Dayan wrote: >> >> >> On 13/03/2025 11:45, Eelco Chaudron wrote: >>> >>> >>> On 27 Jan 2025, at 17:19, Roi Dayan wrote: >>> >>>> On 22/01/2025 15:02, Roi Dayan wrote: >>>>> >>>>> >>>>> On 22/01/2025 14:30, Ilya Maximets wrote: >>>>>> On 1/22/25 13:02, Roi Dayan via dev wrote: >>>>>>> >>>>>>> >>>>>>> On 22/01/2025 11:34, Eelco Chaudron wrote: >>>>>>>> >>>>>>>> >>>>>>>> On 22 Jan 2025, at 8:37, Roi Dayan wrote: >>>>>>>> >>>>>>>>> On 21/01/2025 15:02, Ilya Maximets wrote: >>>>>>>>>> On 1/20/25 16:13, Eelco Chaudron wrote: >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 20 Jan 2025, at 14:50, Roi Dayan wrote: >>>>>>>>>>> >>>>>>>>>>>> On 20/01/2025 14:57, Eelco Chaudron wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 15 Jan 2025, at 10:18, Roi Dayan via dev wrote: >>>>>>>>>>>>> >>>>>>>>>>>>>> Use this instead of directly using dpif_is_netdev() from >>>>>>>>>>>>>> dpif-netdev. >>>>>>>>>>>>>> Return true in dpif-netdev. >>>>>>>>>>>>> >>>>>>>>>>>>> Not sure if we need an API for this, or maybe I should say, what >>>>>>>>>>>>> is the definition >>>>>>>>>>>>> of userspace? If this means anything but the kernel, we could >>>>>>>>>>>>> probably use !dpif_is_netlink(). >>>>>>>>>>>>> >>>>>>>>>>>>> But I guess, the better question would be, what would we use this >>>>>>>>>>>>> call for? If it’s similar >>>>>>>>>>>>> to the existing use cases, we are probably better off by adding a >>>>>>>>>>>>> features API to dpif. >>>>>>>>>>>>> >>>>>>>>>>>>> Thoughts? >>>>>>>>>>>>> >>>>>>>>>>>>> Cheers, >>>>>>>>>>>>> >>>>>>>>>>>>> Eelco >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Hi, >>>>>>>>>>>> >>>>>>>>>>>> The meaning of dpif is a userspace means it needs to handle >>>>>>>>>>>> tunneling and other stuff that >>>>>>>>>>>> kernel dpif doesn't need as the kernel does it for it. >>>>>>>>>>>> So while !dpif_is_netlink() is even more correct and better than >>>>>>>>>>>> current dpif_is_netdev() >>>>>>>>>>>> there was also a point here that dpif.c is not familiar with a >>>>>>>>>>>> specific dpif and not accessing >>>>>>>>>>>> a specific dpif function. >>>>>>>>>>> >>>>>>>>>>> So, this means a lot of potential stuff, so to me a general >>>>>>>>>>> dpif_is_userspace() does not make sense. >>>>>>>>>>> >>>>>>>>>>>> I think introducing a features API to dpif could be an overkill at >>>>>>>>>>>> this point. >>>>>>>>>>>> So if future dpifs might need something specific other than >>>>>>>>>>>> handled by kernel or not I think >>>>>>>>>>>> this can be done at a later time. >>>>>>>>>>> >>>>>>>>>>> It might look like an overkill right now, but the current use cases >>>>>>>>>>> might warrant one already. >>>>>>>>>>> Or are you suggesting to use/introduce !dpif_is_netlink() instead >>>>>>>>>>> for now? >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Ilya and other maintainers have any preferences or thoughts on this. >>>>>>>>>> >>>>>>>>>> In general, using either dpif_is_netlink or dpif_is_netdev outside >>>>>>>>>> of dpif-netlink >>>>>>>>>> and dpif-netdev respectively is icky. And I agree that even today >>>>>>>>>> the number of >>>>>>>>>> uses of these functions outside their modules justifies doing the >>>>>>>>>> feature discovery >>>>>>>>>> properly. Majority of the cases here in dpif.c are caused by the >>>>>>>>>> fact that >>>>>>>>>> dpif-netdev doesn't validate actions, so it's not possible to probe >>>>>>>>>> them. It may be >>>>>>>>>> better to introduce some form of action validation in case of >>>>>>>>>> probing instead, so >>>>>>>>>> the features can be discovered normally. >>>>>>>>>> >>>>>>>>>> Best regards, Ilya Maximets. >>>>>>>>> >>>>>>>>> I think this is out-of-scope for this patch. >>>>>>>>> In this small commit I just wanted to do the separation from dpif.c >>>>>>>>> knowing >>>>>>>>> about existing dpifs and accessing them directly and not introducing >>>>>>>>> new layers and mechanisem. >>>>>> >>>>>> Feature probing is not a new mechanism. We do that for many other >>>>>> actions >>>>>> and it is a primary mechanism for a datapath feature discovery. >>>>>> >>>>>>>>> Can we continue with this patch currently? a rename to the callback >>>>>>>>> is also feasible though >>>>>>>>> I think its saying exactly what it is. >>>>>>>> >>>>>>>> This patch introduces a new API, but its purpose is unclear to me. >>>>>>>> While it’s a small change, >>>>>>>> I don't see a concrete use case for it. The term 'userspace' seems >>>>>>>> vague when used outside the >>>>>>>> context of the actual dpif. Could you provide a clear example of how >>>>>>>> this API will be used? >>>>>>>> This might help us explore better alternative approaches if needed. >>>>>>>> For the current use cases >>>>>>>> see Ilya’s response. >>>>>>>> >>>>>>>> Cheers, >>>>>>>> >>>>>>>> Eelco >>>>>>>> >>>>>>> >>>>>>> A concrete example is tunnel handling. In "netdev" datapath, OVS >>>>>>> userspace application handles >>>>>>> tunnel push and pop, as opposed to "netlink" datapath in which the >>>>>>> kernel handles it. >>>>>>> A more suitable name for it in the first place was "is_userspace". >>>>>>> We want to add another userspace datapath (dpif-doca), that will handle >>>>>>> tunnels, therefore this >>>>>>> change. >>>>>> >>>>>> This is exactly the use case for a feature probing. How we do that for >>>>>> other >>>>>> matches and actions is constructing a dummy flow rule, calling flow_put >>>>>> with a >>>>>> probe flag set and letting datapath validate it. This works for various >>>>>> versions >>>>>> of linux kernel datapath that can be running and that works for windows >>>>>> datapath. >>>>>> This works fine for userspace datapath as well, except only for matches. >>>>>> For >>>>>> actions it doesn't work, because the userspace datapath doesn't validate >>>>>> actions. >>>>>> If we plan to have multiple implementations for userspace-style >>>>>> datpaths, then we >>>>>> should probe them properly as we do for multiple implementations of >>>>>> dpif-netlink. >>>>> >>>>> Are you talking about the TC probing in netdev-offload-tc ? those probing >>>>> is not being done from the dpif.c. >>>>> TC offloading checks the probes there and either offload or not. >>>>> Maybe all those wrappers checking dpif_is_netdev in dpif.c should not >>>>> exists then and maybe all actions should just be passed into the dpif and >>>>> the dpif itself should decide what to do with the actions. dpif-netlink >>>>> should decide if to skip the actions or not. >>>>> All this seems out of scope of keeping the same behavior as it but just >>>>> opening it a bit without touching the specific logic that exists now. >>>>> Moving to the proposal using !dpif_is_netlink also solves the issue for >>>>> userspace dpif implementations. >>>>> if not, I don't understand what kind of probing is expected here. can you >>>>> share an example? >>>>> >>>> >>>> Hi, >>>> >>>> Just updating here that point is not to change the API or logic of the >>>> callers using the dpif_is_netdev. >>>> >>>> dpif_supports_tnl_push_pop >>>> dpif_may_support_explicit_drop_action >>>> dpif_supports_lb_output_action >>>> dpif_may_support_psample >>>> >>>> My intention that if I test with a new userspace dpif then not getting >>>> blocked by dpif that those features are not supported just because its not >>>> specific dpif-netdev. >>>> Please provide an example how you suggest you proceed here. >>> >>> I think what Ilya proposed is to add proper action verification for >>> dpif-netdev, so we can get rid of the psample instance, and then you change >>> the remaining cases to actual probes. Ilya, correct me if I’m wrong. >>> >>> For the netdev part, see a quick patch below; >>> >>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c >>> index 87d69c46d..e6b7131d4 100644 >>> --- a/lib/dpif-netdev.c >>> +++ b/lib/dpif-netdev.c >>> @@ -4307,6 +4307,60 @@ exit: >>> return error; >>> } >>> >>> +static bool >>> +dpif_netdev_actions_supported(const struct nlattr *actions, size_t >>> actions_len) >>> +{ >>> + const struct nlattr *nla; >>> + size_t left; >>> + >>> + if (!actions_len) { >>> + return true; >>> + } >>> + >>> + NL_ATTR_FOR_EACH(nla, left, actions, actions_len) { >>> + enum ovs_action_attr type = nl_attr_type(nla); >>> + >>> + switch (type) { >>> + /* Supported actions go here in order of definition. */ >>> + case OVS_ACTION_ATTR_OUTPUT: >>> + case OVS_ACTION_ATTR_USERSPACE: >>> + case OVS_ACTION_ATTR_SET: >>> + case OVS_ACTION_ATTR_PUSH_VLAN: >>> + case OVS_ACTION_ATTR_POP_VLAN: >>> + case OVS_ACTION_ATTR_SAMPLE: >>> + case OVS_ACTION_ATTR_RECIRC: >>> + case OVS_ACTION_ATTR_HASH: >>> + case OVS_ACTION_ATTR_PUSH_MPLS: >>> + case OVS_ACTION_ATTR_POP_MPLS: >>> + case OVS_ACTION_ATTR_SET_MASKED: >>> + case OVS_ACTION_ATTR_CT: >>> + case OVS_ACTION_ATTR_TRUNC: >>> + case OVS_ACTION_ATTR_PUSH_ETH: >>> + case OVS_ACTION_ATTR_POP_ETH: >>> + case OVS_ACTION_ATTR_CT_CLEAR: >>> + case OVS_ACTION_ATTR_PUSH_NSH: >>> + case OVS_ACTION_ATTR_POP_NSH: >>> + case OVS_ACTION_ATTR_METER: >>> + case OVS_ACTION_ATTR_CLONE: >>> + case OVS_ACTION_ATTR_CHECK_PKT_LEN: >>> + case OVS_ACTION_ATTR_ADD_MPLS: >>> + case OVS_ACTION_ATTR_DEC_TTL: >>> + case OVS_ACTION_ATTR_DROP: >>> + case OVS_ACTION_ATTR_TUNNEL_PUSH: >>> + case OVS_ACTION_ATTR_TUNNEL_POP: >>> + case OVS_ACTION_ATTR_LB_OUTPUT: >>> + return true; >>> + >>> + /* Unsupported actions go here in order of definition. */ >>> + case OVS_ACTION_ATTR_UNSPEC: >>> + case OVS_ACTION_ATTR_PSAMPLE: >>> + case __OVS_ACTION_ATTR_MAX: >>> + break; >>> + } >>> + } >>> + return false; >>> +} >>> + >>> static int >>> dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put) >>> { >>> @@ -4367,6 +4421,13 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct >>> dpif_flow_put *put) >>> * address mask. Installation of the flow will use the match variable. >>> */ >>> netdev_flow_key_init(&key, &match.flow); >>> >>> + /* For probe operations, verify if the individual actions are >>> supported. >>> + * Otherwise, assume the higher layer, ofproto, manages action >>> support. */ >>> + if (probe && !dpif_netdev_actions_supported(put->actions, >>> + put->actions_len)) { >>> + return EINVAL; >>> + } >>> + >>> if (put->pmd_id == PMD_ID_NULL) { >>> if (cmap_count(&dp->poll_threads) == 0) { >>> return EINVAL; >>> diff --git a/lib/dpif.c b/lib/dpif.c >>> index a064f717f..c22a47c3c 100644 >>> --- a/lib/dpif.c >>> +++ b/lib/dpif.c >>> @@ -1953,13 +1953,6 @@ dpif_supports_lb_output_action(const struct dpif >>> *dpif) >>> return dpif_is_netdev(dpif); >>> } >>> >>> -bool >>> -dpif_may_support_psample(const struct dpif *dpif) >>> -{ >>> - /* Userspace datapath does not support this action. */ >>> - return !dpif_is_netdev(dpif); >>> -} >>> - >>> /* Meters */ >>> void >>> dpif_meter_get_features(const struct dpif *dpif, >>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c >>> index bf43d5d4b..7637d93de 100644 >>> --- a/ofproto/ofproto-dpif.c >>> +++ b/ofproto/ofproto-dpif.c >>> @@ -1646,8 +1646,8 @@ check_psample(struct dpif_backer *backer) >>> >>> odp_put_psample_action(&actions, 10, cookie, sizeof cookie); >>> >>> - supported = dpif_may_support_psample(backer->dpif) && >>> - dpif_probe_feature(backer->dpif, "psample", &key, &actions, NULL); >>> + supported = dpif_probe_feature(backer->dpif, "psample", &key, &actions, >>> + NULL); >>> >>> ofpbuf_uninit(&actions); >>> VLOG_INFO("%s: Datapath %s psample action", dpif_name(backer->dpif), >>> >>> >>> >> >> thanks Eelco, I'll take a look at this example and see what I come with as a >> different patch. > > Sorry, I lost track of this duscussion at some point. > > Eelco, yes, your reference code above matches my previous suggestion. > A few small comments though: > 1. The check should be recursive, since we have nested actions. > 2. dpif-netdev should only check actions it implements on it's own and > call a verification helper for all other actions implemented in the > odp-execute.c. That helper may return true for all the actions it > supports directly and false for all the actions that require datapath > assistance. > > Other than that and the indentation of the cases, it looks good. :) > > Best regards, Ilya Maximets. >
Thanks for the suggestions and comments. I submitted a different series according the suggestions instead of this patch: https://patchwork.ozlabs.org/project/openvswitch/list/?series=450922 >> >>>>>> >>>>>> This is_userspace call is actually a request "if this implementation >>>>>> supports >>>>>> the following actions: tunnel_push_pop, explicit drop, lb_output and >>>>>> psample?". >>>>>> Answer "true" corresponds to "yes, yes, yes, no", and "false" means "no, >>>>>> maybe, >>>>>> no, maybe", and then dpif.c proceeds to probe for "maybe" actions. >>>>>> >>>>>> So, this call is only a shortcut with non-obvious overloaded meaning >>>>>> that will >>>>>> change over time as we add new actions. Instead, we can remove it and >>>>>> just do >>>>>> probing as dpif layer already does for most of other matches and actions. >>>>>> It should also be easier for you to maintain an alternative userspace >>>>>> datapath >>>>>> implementation this way, as you'll not need to worry about what this call >>>>>> actually means, as dpif layer would just probe what it needs directly >>>>>> instead >>>>>> of assuming things based on a single boolean value. >>>>>> >>>>>> Best regards, Ilya Maximets. >>>>> >>> >> > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev