On 12 Oct 2026, at 18:14, Eli Britstein wrote:
> On 12/10/2026 18:39, Eelco Chaudron wrote:
>> [You don't often get email from [email protected]. Learn why this is
>> important at https://aka.ms/LearnAboutSenderIdentification ]
>>
>> External email: Use caution opening links or attachments
>>
>>
>> From: Eelco Chaudron <[email protected]>
>>
>> Exercise the alt_actions parameter added to the netdev_hw_post_process()
>> callback. When a flow contains only OUTPUT actions with a mix of
>> dummy-pmd and non-dummy-pmd egress ports, the dummy driver executes the
>> dummy-pmd outputs in the simulated hardware pipeline and returns the
>> non-dummy-pmd outputs as alternative actions for the PMD thread.
>> A new test case validates the new API.
> Few nits below
>>
>> Signed-off-by: Eelco Chaudron <[email protected]>
>> ---
>> lib/dpif-offload-dummy.c | 131 +++++++++++++++++++++++++++++++++------
>> tests/dpif-netdev.at | 103 +++++++++++++++++++++++++++++-
>> tests/ofproto-dpif.at | 65 ++++++++++++-------
>> 3 files changed, 255 insertions(+), 44 deletions(-)
>>
>> diff --git a/lib/dpif-offload-dummy.c b/lib/dpif-offload-dummy.c
> ...
>> +
>> +/* Build a set of alternative actions to exercise the alt_actions support in
>> + * the netdev_hw_post_process() API. The dummy implementation returns
>> + * alternative actions only when the action list consists solely of
>> + * OVS_ACTION_ATTR_OUTPUT actions, and at least one egress port is not of
>> + * type dummy-pmd. In that case, the dummy-pmd outputs are handled in
>> + * 'hardware', while the non-dummy-pmd outputs are returned as alternative
>> + * actions to be executed by the PMD thread. */
>> +static struct offload_actions *
>> +dummy_build_alt_actions(const struct dpif_offload *offload_,
>> + odp_port_t in_odp,
>> + const struct nlattr *actions,
>> + size_t actions_len)
>> +{
>> + struct offload_actions *alt_actions = NULL;
>> + const struct nlattr *nla;
>> + struct ofpbuf buf;
>> + size_t left;
>> +
>> + ofpbuf_init(&buf, 0);
>> +
>> + NL_ATTR_FOR_EACH (nla, left, actions, actions_len) {
>> + enum ovs_action_attr action = nl_attr_type(nla);
>> + struct dummy_offload_port *out_port;
>> + odp_port_t out_odp;
>> +
>> + if (action != OVS_ACTION_ATTR_OUTPUT) {
>> + goto out;
>> + }
>> +
>> + out_odp = nl_attr_get_odp_port(nla);
>> + out_port = dummy_offload_get_port_by_odp_port(offload_, out_odp);
>> + if (out_odp != in_odp
>> + && (!out_port
>> + || strcmp("dummy-pmd",
>> + netdev_get_type(out_port->pm_port.netdev)))) {
>> + ofpbuf_put(&buf, nla, NLA_ALIGN(nla->nla_len));
> I still think it can be simplified. Here you build a struct ofpbuf, that you
> copy from the actions to. Later, you copy this to alt_actions. All we need is
> to detect this case, then copy actions (minus the first one) to alt_actions.
Your suggestion assumes the non-dummy-pmd ports are always at the
start of the list. We support mixed port lists like:
p1(non-pmd), p2(pmd), p3(non-pmd), p4(pmd)
In this case we can not simply copy everything after the first
action, as the pmd ports (p2, p4) must still be handled in hardware
and should not be part of the alt_actions. However I reworked the
code to avoid the copy, by using xrealloc() instead of an ofpbuf.
Will send this in a v3 later.
>> + }
>> + }
>> +
>> + if (buf.size) {
>> + alt_actions = xmalloc(sizeof *alt_actions + buf.size);
>> + alt_actions->size = buf.size;
>> + memcpy(alt_actions->actions, buf.data, buf.size);
>> + }
>> +
>> +out:
>> + ofpbuf_uninit(&buf);
>> + return alt_actions;
>> }
>>
>> static int
>> @@ -863,12 +935,24 @@ dummy_flow_put(const struct dpif_offload *offload_,
>> struct netdev *netdev,
>> }
>> memcpy(&off_flow->match, put->match, sizeof *put->match);
>> free(CONST_CAST(struct nlattr *, off_flow->actions));
> ...
>> flow = &packet_flow;
>> flow_extract(packet, flow);
>> @@ -1071,9 +1162,6 @@ dummy_netdev_simulate_offload(struct netdev *netdev,
>> struct dp_packet *packet,
>> }
>>
>> if (data->actions) {
>> - /* Perform hardware offload simulation. The packet is
>> stolen
>> - * here and handed off to the PMD thread callback for
>> - * processing. */
> Why is this comment removed?
I removed the comment thinking it was no longer accurate with the
new alt_actions changes, but looking at it again it still holds,
the packet is always stolen into the hw pipeline which will handle
the sw re-inject if needed via alt_actions. Will restore it in v3.
>> struct hw_pkt_node *pkt_node = xmalloc(sizeof *pkt_node);
>>
>> pkt_node->pkt = packet;
>> @@ -1123,7 +1211,7 @@ dummy_netdev_hw_offload_run(struct netdev *netdev)
>> LIST_FOR_EACH_POP (pkt_node, list_node, &port->hw_recv_queue) {
> ...
>> 2.55.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev