On Mon, Mar 28, 2022 at 7:10 AM Eelco Chaudron <echau...@redhat.com> wrote: > > Move handling of the individual actions in the netdev_tc_flow_put() > function to a separate function that will make recursive action handling > easier. > > Signed-off-by: Eelco Chaudron <echau...@redhat.com>
Acked-by: Mike Pattrick <m...@redhat.com> > --- > lib/netdev-offload-tc.c | 255 > +++++++++++++++++++++++++---------------------- > 1 file changed, 138 insertions(+), 117 deletions(-) > > diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c > index 12d0a9af3..ae6f1134d 100644 > --- a/lib/netdev-offload-tc.c > +++ b/lib/netdev-offload-tc.c > @@ -1558,6 +1558,139 @@ parse_match_ct_state_to_flower(struct tc_flower > *flower, struct match *match) > } > } > > +static int > +netdev_tc_parse_nl_actions(struct netdev *netdev, struct tc_flower *flower, > + struct offload_info *info, > + const struct nlattr *actions, size_t actions_len, > + bool *recirc_act) > +{ > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); > + const struct nlattr *nla; > + size_t left; > + > + NL_ATTR_FOR_EACH (nla, left, actions, actions_len) { > + struct tc_action *action; > + int err; > + > + if (flower->action_count >= TCA_ACT_MAX_NUM) { > + VLOG_DBG_RL(&rl, "Can only support %d actions", TCA_ACT_MAX_NUM); > + return EOPNOTSUPP; > + } > + > + action = &flower->actions[flower->action_count]; > + > + if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) { > + odp_port_t port = nl_attr_get_odp_port(nla); > + struct netdev *outdev = netdev_ports_get( > + port, netdev_get_dpif_type(netdev)); > + > + if (!outdev) { > + VLOG_DBG_RL(&rl, "Can't find netdev for output port %d", > port); > + return ENODEV; > + } > + > + if (!netdev_flow_api_equals(netdev, outdev)) { > + VLOG_DBG_RL(&rl, > + "Flow API provider mismatch between ingress (%s) > " > + "and egress (%s) ports", > + netdev_get_name(netdev), > netdev_get_name(outdev)); > + netdev_close(outdev); > + return EOPNOTSUPP; > + } > + > + action->out.ifindex_out = netdev_get_ifindex(outdev); > + if (action->out.ifindex_out < 0) { > + VLOG_DBG_RL(&rl, > + "Can't find ifindex for output port %s, error > %d", > + netdev_get_name(outdev), > action->out.ifindex_out); > + netdev_close(outdev); > + return -action->out.ifindex_out; > + } > + > + action->out.ingress = is_internal_port(netdev_get_type(outdev)); > + action->type = TC_ACT_OUTPUT; > + flower->action_count++; > + netdev_close(outdev); > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_PUSH_VLAN) { > + const struct ovs_action_push_vlan *vlan_push = nl_attr_get(nla); > + > + action->vlan.vlan_push_tpid = vlan_push->vlan_tpid; > + action->vlan.vlan_push_id = vlan_tci_to_vid(vlan_push->vlan_tci); > + action->vlan.vlan_push_prio = > vlan_tci_to_pcp(vlan_push->vlan_tci); > + action->type = TC_ACT_VLAN_PUSH; > + flower->action_count++; > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_POP_VLAN) { > + action->type = TC_ACT_VLAN_POP; > + flower->action_count++; > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_PUSH_MPLS) { > + const struct ovs_action_push_mpls *mpls_push = nl_attr_get(nla); > + > + action->mpls.proto = mpls_push->mpls_ethertype; > + action->mpls.label = mpls_lse_to_label(mpls_push->mpls_lse); > + action->mpls.tc = mpls_lse_to_tc(mpls_push->mpls_lse); > + action->mpls.ttl = mpls_lse_to_ttl(mpls_push->mpls_lse); > + action->mpls.bos = mpls_lse_to_bos(mpls_push->mpls_lse); > + action->type = TC_ACT_MPLS_PUSH; > + flower->action_count++; > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_POP_MPLS) { > + action->mpls.proto = nl_attr_get_be16(nla); > + action->type = TC_ACT_MPLS_POP; > + flower->action_count++; > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET) { > + const struct nlattr *set = nl_attr_get(nla); > + const size_t set_len = nl_attr_get_size(nla); > + > + err = parse_put_flow_set_action(flower, action, set, set_len); > + if (err) { > + return err; > + } > + if (action->type == TC_ACT_ENCAP) { > + action->encap.tp_dst = info->tp_dst_port; > + action->encap.no_csum = !info->tunnel_csum_on; > + } > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET_MASKED) { > + const struct nlattr *set = nl_attr_get(nla); > + const size_t set_len = nl_attr_get_size(nla); > + > + err = parse_put_flow_set_masked_action(flower, action, set, > + set_len, true); > + if (err) { > + return err; > + } > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CT) { > + const struct nlattr *ct = nl_attr_get(nla); > + const size_t ct_len = nl_attr_get_size(nla); > + > + if (!ct_state_support) { > + return -EOPNOTSUPP; > + } > + > + err = parse_put_flow_ct_action(flower, action, ct, ct_len); > + if (err) { > + return err; > + } > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CT_CLEAR) { > + action->type = TC_ACT_CT; > + action->ct.clear = true; > + flower->action_count++; > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_RECIRC) { > + action->type = TC_ACT_GOTO; > + action->chain = nl_attr_get_u32(nla); > + flower->action_count++; > + *recirc_act = true; > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_DROP) { > + action->type = TC_ACT_GOTO; > + action->chain = 0; /* 0 is reserved and not used by recirc. */ > + flower->action_count++; > + } else { > + VLOG_DBG_RL(&rl, "unsupported put action type: %d", > + nl_attr_type(nla)); > + return EOPNOTSUPP; > + } > + } > + return 0; > +} > + > static int > netdev_tc_flow_put(struct netdev *netdev, struct match *match, > struct nlattr *actions, size_t actions_len, > @@ -1571,13 +1704,10 @@ netdev_tc_flow_put(struct netdev *netdev, struct > match *match, > struct flow *mask = &match->wc.masks; > const struct flow_tnl *tnl = &match->flow.tunnel; > const struct flow_tnl *tnl_mask = &mask->tunnel; > - struct tc_action *action; > bool recirc_act = false; > uint32_t block_id = 0; > - struct nlattr *nla; > struct tcf_id id; > uint32_t chain; > - size_t left; > int prio = 0; > int ifindex; > int err; > @@ -1822,120 +1952,11 @@ netdev_tc_flow_put(struct netdev *netdev, struct > match *match, > return err; > } > > - NL_ATTR_FOR_EACH(nla, left, actions, actions_len) { > - if (flower.action_count >= TCA_ACT_MAX_NUM) { > - VLOG_DBG_RL(&rl, "Can only support %d actions", TCA_ACT_MAX_NUM); > - return EOPNOTSUPP; > - } > - action = &flower.actions[flower.action_count]; > - if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) { > - odp_port_t port = nl_attr_get_odp_port(nla); > - struct netdev *outdev = netdev_ports_get( > - port, netdev_get_dpif_type(netdev)); > - > - if (!outdev) { > - VLOG_DBG_RL(&rl, "Can't find netdev for output port %d", > port); > - return ENODEV; > - } > - > - if (!netdev_flow_api_equals(netdev, outdev)) { > - VLOG_DBG_RL(&rl, > - "Flow API provider mismatch between ingress (%s) > " > - "and egress (%s) ports", > - netdev_get_name(netdev), > netdev_get_name(outdev)); > - netdev_close(outdev); > - return EOPNOTSUPP; > - } > - > - action->out.ifindex_out = netdev_get_ifindex(outdev); > - if (action->out.ifindex_out < 0) { > - VLOG_DBG_RL(&rl, > - "Can't find ifindex for output port %s, error > %d", > - netdev_get_name(outdev), > action->out.ifindex_out); > - netdev_close(outdev); > - return -action->out.ifindex_out; > - } > - > - action->out.ingress = is_internal_port(netdev_get_type(outdev)); > - action->type = TC_ACT_OUTPUT; > - flower.action_count++; > - netdev_close(outdev); > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_PUSH_VLAN) { > - const struct ovs_action_push_vlan *vlan_push = nl_attr_get(nla); > - > - action->vlan.vlan_push_tpid = vlan_push->vlan_tpid; > - action->vlan.vlan_push_id = vlan_tci_to_vid(vlan_push->vlan_tci); > - action->vlan.vlan_push_prio = > vlan_tci_to_pcp(vlan_push->vlan_tci); > - action->type = TC_ACT_VLAN_PUSH; > - flower.action_count++; > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_POP_VLAN) { > - action->type = TC_ACT_VLAN_POP; > - flower.action_count++; > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_PUSH_MPLS) { > - const struct ovs_action_push_mpls *mpls_push = nl_attr_get(nla); > - > - action->mpls.proto = mpls_push->mpls_ethertype; > - action->mpls.label = mpls_lse_to_label(mpls_push->mpls_lse); > - action->mpls.tc = mpls_lse_to_tc(mpls_push->mpls_lse); > - action->mpls.ttl = mpls_lse_to_ttl(mpls_push->mpls_lse); > - action->mpls.bos = mpls_lse_to_bos(mpls_push->mpls_lse); > - action->type = TC_ACT_MPLS_PUSH; > - flower.action_count++; > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_POP_MPLS) { > - action->mpls.proto = nl_attr_get_be16(nla); > - action->type = TC_ACT_MPLS_POP; > - flower.action_count++; > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET) { > - const struct nlattr *set = nl_attr_get(nla); > - const size_t set_len = nl_attr_get_size(nla); > - > - err = parse_put_flow_set_action(&flower, action, set, set_len); > - if (err) { > - return err; > - } > - if (action->type == TC_ACT_ENCAP) { > - action->encap.tp_dst = info->tp_dst_port; > - action->encap.no_csum = !info->tunnel_csum_on; > - } > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET_MASKED) { > - const struct nlattr *set = nl_attr_get(nla); > - const size_t set_len = nl_attr_get_size(nla); > - > - err = parse_put_flow_set_masked_action(&flower, action, set, > - set_len, true); > - if (err) { > - return err; > - } > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CT) { > - const struct nlattr *ct = nl_attr_get(nla); > - const size_t ct_len = nl_attr_get_size(nla); > - > - if (!ct_state_support) { > - return -EOPNOTSUPP; > - } > - > - err = parse_put_flow_ct_action(&flower, action, ct, ct_len); > - if (err) { > - return err; > - } > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CT_CLEAR) { > - action->type = TC_ACT_CT; > - action->ct.clear = true; > - flower.action_count++; > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_RECIRC) { > - action->type = TC_ACT_GOTO; > - action->chain = nl_attr_get_u32(nla); > - flower.action_count++; > - recirc_act = true; > - } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_DROP) { > - action->type = TC_ACT_GOTO; > - action->chain = 0; /* 0 is reserved and not used by recirc. */ > - flower.action_count++; > - } else { > - VLOG_DBG_RL(&rl, "unsupported put action type: %d", > - nl_attr_type(nla)); > - return EOPNOTSUPP; > - } > + /* Parse all (nested) actions. */ > + err = netdev_tc_parse_nl_actions(netdev, &flower, info, > + actions, actions_len, &recirc_act); > + if (err) { > + return err; > } > > if ((chain || recirc_act) && !info->recirc_id_shared_with_tc) { > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev