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

Reply via email to