On Mon, Mar 28, 2022 at 7:10 AM Eelco Chaudron <echau...@redhat.com> wrote: > > Move handling of the individual actions in the parse_tc_flower_to_match() > 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 | 422 > +++++++++++++++++++++++++---------------------- > 1 file changed, 221 insertions(+), 201 deletions(-) > > diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c > index ae6f1134d..a7838e503 100644 > --- a/lib/netdev-offload-tc.c > +++ b/lib/netdev-offload-tc.c > @@ -617,6 +617,226 @@ parse_tc_flower_terse_to_match(struct tc_flower *flower, > return 0; > } > > +static int > +_parse_tc_flower_to_actions(struct tc_flower *flower, struct ofpbuf *buf, > + int start_index, int max_index) > +{ > + struct tc_action *action; > + int i; > + > + if (max_index <= 0 || max_index > flower->action_count) { > + max_index = flower->action_count; > + } > + > + for (i = start_index; i < max_index; i++) { > + action = &flower->actions[i]; > + > + switch (action->type) { > + case TC_ACT_VLAN_POP: { > + nl_msg_put_flag(buf, OVS_ACTION_ATTR_POP_VLAN); > + } > + break; > + case TC_ACT_VLAN_PUSH: { > + struct ovs_action_push_vlan *push; > + > + push = nl_msg_put_unspec_zero(buf, OVS_ACTION_ATTR_PUSH_VLAN, > + sizeof *push); > + push->vlan_tpid = action->vlan.vlan_push_tpid; > + push->vlan_tci = htons(action->vlan.vlan_push_id > + | (action->vlan.vlan_push_prio << 13) > + | VLAN_CFI); > + } > + break; > + case TC_ACT_MPLS_POP: { > + nl_msg_put_be16(buf, OVS_ACTION_ATTR_POP_MPLS, > + action->mpls.proto); > + } > + break; > + case TC_ACT_MPLS_PUSH: { > + struct ovs_action_push_mpls *push; > + ovs_be32 mpls_lse = 0; > + > + flow_set_mpls_lse_label(&mpls_lse, action->mpls.label); > + flow_set_mpls_lse_tc(&mpls_lse, action->mpls.tc); > + flow_set_mpls_lse_ttl(&mpls_lse, action->mpls.ttl); > + flow_set_mpls_lse_bos(&mpls_lse, action->mpls.bos); > + > + push = nl_msg_put_unspec_zero(buf, OVS_ACTION_ATTR_PUSH_MPLS, > + sizeof *push); > + push->mpls_ethertype = action->mpls.proto; > + push->mpls_lse = mpls_lse; > + } > + break; > + case TC_ACT_MPLS_SET: { > + size_t set_offset = nl_msg_start_nested(buf, > + OVS_ACTION_ATTR_SET); > + struct ovs_key_mpls *set_mpls; > + ovs_be32 mpls_lse = 0; > + > + flow_set_mpls_lse_label(&mpls_lse, action->mpls.label); > + flow_set_mpls_lse_tc(&mpls_lse, action->mpls.tc); > + flow_set_mpls_lse_ttl(&mpls_lse, action->mpls.ttl); > + flow_set_mpls_lse_bos(&mpls_lse, action->mpls.bos); > + > + set_mpls = nl_msg_put_unspec_zero(buf, OVS_KEY_ATTR_MPLS, > + sizeof *set_mpls); > + set_mpls->mpls_lse = mpls_lse; > + nl_msg_end_nested(buf, set_offset); > + } > + break; > + case TC_ACT_PEDIT: { > + parse_flower_rewrite_to_netlink_action(buf, action); > + } > + break; > + case TC_ACT_ENCAP: { > + size_t set_offset = nl_msg_start_nested(buf, > OVS_ACTION_ATTR_SET); > + size_t tunnel_offset = > + nl_msg_start_nested(buf, OVS_KEY_ATTR_TUNNEL); > + > + if (action->encap.id_present) { > + nl_msg_put_be64(buf, OVS_TUNNEL_KEY_ATTR_ID, > action->encap.id); > + } > + if (action->encap.ipv4.ipv4_src) { > + nl_msg_put_be32(buf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, > + action->encap.ipv4.ipv4_src); > + } > + if (action->encap.ipv4.ipv4_dst) { > + nl_msg_put_be32(buf, OVS_TUNNEL_KEY_ATTR_IPV4_DST, > + action->encap.ipv4.ipv4_dst); > + } > + if (ipv6_addr_is_set(&action->encap.ipv6.ipv6_src)) { > + nl_msg_put_in6_addr(buf, OVS_TUNNEL_KEY_ATTR_IPV6_SRC, > + &action->encap.ipv6.ipv6_src); > + } > + if (ipv6_addr_is_set(&action->encap.ipv6.ipv6_dst)) { > + nl_msg_put_in6_addr(buf, OVS_TUNNEL_KEY_ATTR_IPV6_DST, > + &action->encap.ipv6.ipv6_dst); > + } > + if (action->encap.tos) { > + nl_msg_put_u8(buf, OVS_TUNNEL_KEY_ATTR_TOS, > + action->encap.tos); > + } > + if (action->encap.ttl) { > + nl_msg_put_u8(buf, OVS_TUNNEL_KEY_ATTR_TTL, > + action->encap.ttl); > + } > + if (action->encap.tp_dst) { > + nl_msg_put_be16(buf, OVS_TUNNEL_KEY_ATTR_TP_DST, > + action->encap.tp_dst); > + } > + if (!action->encap.no_csum) { > + nl_msg_put_flag(buf, OVS_TUNNEL_KEY_ATTR_CSUM); > + } > + > + parse_tc_flower_geneve_opts(action, buf); > + nl_msg_end_nested(buf, tunnel_offset); > + nl_msg_end_nested(buf, set_offset); > + } > + break; > + case TC_ACT_OUTPUT: { > + odp_port_t outport = 0; > + > + if (action->out.ifindex_out) { > + outport = > + netdev_ifindex_to_odp_port(action->out.ifindex_out); > + if (!outport) { > + return ENOENT; > + } > + } > + nl_msg_put_u32(buf, OVS_ACTION_ATTR_OUTPUT, odp_to_u32(outport)); > + } > + break; > + case TC_ACT_CT: { > + size_t ct_offset; > + > + if (action->ct.clear) { > + nl_msg_put_flag(buf, OVS_ACTION_ATTR_CT_CLEAR); > + break; > + } > + > + ct_offset = nl_msg_start_nested(buf, OVS_ACTION_ATTR_CT); > + > + if (action->ct.commit) { > + nl_msg_put_flag(buf, OVS_CT_ATTR_COMMIT); > + } > + > + if (action->ct.zone) { > + nl_msg_put_u16(buf, OVS_CT_ATTR_ZONE, action->ct.zone); > + } > + > + if (action->ct.mark_mask) { > + uint32_t mark_and_mask[2] = { action->ct.mark, > + action->ct.mark_mask }; > + nl_msg_put_unspec(buf, OVS_CT_ATTR_MARK, &mark_and_mask, > + sizeof mark_and_mask); > + } > + > + if (!ovs_u128_is_zero(action->ct.label_mask)) { > + struct { > + ovs_u128 key; > + ovs_u128 mask; > + } *ct_label; > + > + ct_label = nl_msg_put_unspec_uninit(buf, > + OVS_CT_ATTR_LABELS, > + sizeof *ct_label); > + ct_label->key = action->ct.label; > + ct_label->mask = action->ct.label_mask; > + } > + > + if (action->ct.nat_type) { > + size_t nat_offset = nl_msg_start_nested(buf, > + OVS_CT_ATTR_NAT); > + > + if (action->ct.nat_type == TC_NAT_SRC) { > + nl_msg_put_flag(buf, OVS_NAT_ATTR_SRC); > + } else if (action->ct.nat_type == TC_NAT_DST) { > + nl_msg_put_flag(buf, OVS_NAT_ATTR_DST); > + } > + > + if (action->ct.range.ip_family == AF_INET) { > + nl_msg_put_be32(buf, OVS_NAT_ATTR_IP_MIN, > + action->ct.range.ipv4.min); > + nl_msg_put_be32(buf, OVS_NAT_ATTR_IP_MAX, > + action->ct.range.ipv4.max); > + } else if (action->ct.range.ip_family == AF_INET6) { > + nl_msg_put_in6_addr(buf, OVS_NAT_ATTR_IP_MIN, > + &action->ct.range.ipv6.min); > + nl_msg_put_in6_addr(buf, OVS_NAT_ATTR_IP_MAX, > + &action->ct.range.ipv6.max); > + } > + > + if (action->ct.range.port.min) { > + nl_msg_put_u16(buf, OVS_NAT_ATTR_PROTO_MIN, > + ntohs(action->ct.range.port.min)); > + if (action->ct.range.port.max) { > + nl_msg_put_u16(buf, OVS_NAT_ATTR_PROTO_MAX, > + ntohs(action->ct.range.port.max)); > + } > + } > + > + nl_msg_end_nested(buf, nat_offset); > + } > + > + nl_msg_end_nested(buf, ct_offset); > + } > + break; > + case TC_ACT_GOTO: { > + nl_msg_put_u32(buf, OVS_ACTION_ATTR_RECIRC, action->chain); > + } > + break; > + } > + } > + return i; > +} > + > +static void > +parse_tc_flower_to_actions(struct tc_flower *flower, > + struct ofpbuf *buf) > +{ > + _parse_tc_flower_to_actions(flower, buf, 0, 0); > +} > + > static int > parse_tc_flower_to_match(struct tc_flower *flower, > struct match *match, > @@ -629,9 +849,6 @@ parse_tc_flower_to_match(struct tc_flower *flower, > size_t act_off; > struct tc_flower_key *key = &flower->key; > struct tc_flower_key *mask = &flower->mask; > - odp_port_t outport = 0; > - struct tc_action *action; > - int i; > > if (terse) { > return parse_tc_flower_terse_to_match(flower, match, stats, attrs); > @@ -822,204 +1039,7 @@ parse_tc_flower_to_match(struct tc_flower *flower, > } > > act_off = nl_msg_start_nested(buf, OVS_FLOW_ATTR_ACTIONS); > - { > - action = flower->actions; > - for (i = 0; i < flower->action_count; i++, action++) { > - switch (action->type) { > - case TC_ACT_VLAN_POP: { > - nl_msg_put_flag(buf, OVS_ACTION_ATTR_POP_VLAN); > - } > - break; > - case TC_ACT_VLAN_PUSH: { > - struct ovs_action_push_vlan *push; > - > - push = nl_msg_put_unspec_zero(buf, OVS_ACTION_ATTR_PUSH_VLAN, > - sizeof *push); > - push->vlan_tpid = action->vlan.vlan_push_tpid; > - push->vlan_tci = htons(action->vlan.vlan_push_id > - | (action->vlan.vlan_push_prio << 13) > - | VLAN_CFI); > - } > - break; > - case TC_ACT_MPLS_POP: { > - nl_msg_put_be16(buf, OVS_ACTION_ATTR_POP_MPLS, > - action->mpls.proto); > - } > - break; > - case TC_ACT_MPLS_PUSH: { > - struct ovs_action_push_mpls *push; > - ovs_be32 mpls_lse = 0; > - > - flow_set_mpls_lse_label(&mpls_lse, action->mpls.label); > - flow_set_mpls_lse_tc(&mpls_lse, action->mpls.tc); > - flow_set_mpls_lse_ttl(&mpls_lse, action->mpls.ttl); > - flow_set_mpls_lse_bos(&mpls_lse, action->mpls.bos); > - > - push = nl_msg_put_unspec_zero(buf, OVS_ACTION_ATTR_PUSH_MPLS, > - sizeof *push); > - push->mpls_ethertype = action->mpls.proto; > - push->mpls_lse = mpls_lse; > - } > - break; > - case TC_ACT_MPLS_SET: { > - size_t set_offset = nl_msg_start_nested(buf, > - OVS_ACTION_ATTR_SET); > - struct ovs_key_mpls *set_mpls; > - ovs_be32 mpls_lse = 0; > - > - flow_set_mpls_lse_label(&mpls_lse, action->mpls.label); > - flow_set_mpls_lse_tc(&mpls_lse, action->mpls.tc); > - flow_set_mpls_lse_ttl(&mpls_lse, action->mpls.ttl); > - flow_set_mpls_lse_bos(&mpls_lse, action->mpls.bos); > - > - set_mpls = nl_msg_put_unspec_zero(buf, OVS_KEY_ATTR_MPLS, > - sizeof *set_mpls); > - set_mpls->mpls_lse = mpls_lse; > - nl_msg_end_nested(buf, set_offset); > - } > - break; > - case TC_ACT_PEDIT: { > - parse_flower_rewrite_to_netlink_action(buf, action); > - } > - break; > - case TC_ACT_ENCAP: { > - size_t set_offset = nl_msg_start_nested(buf, > OVS_ACTION_ATTR_SET); > - size_t tunnel_offset = > - nl_msg_start_nested(buf, OVS_KEY_ATTR_TUNNEL); > - > - if (action->encap.id_present) { > - nl_msg_put_be64(buf, OVS_TUNNEL_KEY_ATTR_ID, > action->encap.id); > - } > - if (action->encap.ipv4.ipv4_src) { > - nl_msg_put_be32(buf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, > - action->encap.ipv4.ipv4_src); > - } > - if (action->encap.ipv4.ipv4_dst) { > - nl_msg_put_be32(buf, OVS_TUNNEL_KEY_ATTR_IPV4_DST, > - action->encap.ipv4.ipv4_dst); > - } > - if (ipv6_addr_is_set(&action->encap.ipv6.ipv6_src)) { > - nl_msg_put_in6_addr(buf, OVS_TUNNEL_KEY_ATTR_IPV6_SRC, > - &action->encap.ipv6.ipv6_src); > - } > - if (ipv6_addr_is_set(&action->encap.ipv6.ipv6_dst)) { > - nl_msg_put_in6_addr(buf, OVS_TUNNEL_KEY_ATTR_IPV6_DST, > - &action->encap.ipv6.ipv6_dst); > - } > - if (action->encap.tos) { > - nl_msg_put_u8(buf, OVS_TUNNEL_KEY_ATTR_TOS, > - action->encap.tos); > - } > - if (action->encap.ttl) { > - nl_msg_put_u8(buf, OVS_TUNNEL_KEY_ATTR_TTL, > - action->encap.ttl); > - } > - if (action->encap.tp_dst) { > - nl_msg_put_be16(buf, OVS_TUNNEL_KEY_ATTR_TP_DST, > - action->encap.tp_dst); > - } > - if (!action->encap.no_csum) { > - nl_msg_put_flag(buf, OVS_TUNNEL_KEY_ATTR_CSUM); > - } > - > - parse_tc_flower_geneve_opts(action, buf); > - nl_msg_end_nested(buf, tunnel_offset); > - nl_msg_end_nested(buf, set_offset); > - } > - break; > - case TC_ACT_OUTPUT: { > - if (action->out.ifindex_out) { > - outport = > - netdev_ifindex_to_odp_port(action->out.ifindex_out); > - if (!outport) { > - return ENOENT; > - } > - } > - nl_msg_put_u32(buf, OVS_ACTION_ATTR_OUTPUT, > odp_to_u32(outport)); > - } > - break; > - case TC_ACT_CT: { > - size_t ct_offset; > - > - if (action->ct.clear) { > - nl_msg_put_flag(buf, OVS_ACTION_ATTR_CT_CLEAR); > - break; > - } > - > - ct_offset = nl_msg_start_nested(buf, OVS_ACTION_ATTR_CT); > - > - if (action->ct.commit) { > - nl_msg_put_flag(buf, OVS_CT_ATTR_COMMIT); > - } > - > - if (action->ct.zone) { > - nl_msg_put_u16(buf, OVS_CT_ATTR_ZONE, action->ct.zone); > - } > - > - if (action->ct.mark_mask) { > - uint32_t mark_and_mask[2] = { action->ct.mark, > - action->ct.mark_mask }; > - nl_msg_put_unspec(buf, OVS_CT_ATTR_MARK, &mark_and_mask, > - sizeof mark_and_mask); > - } > - > - if (!ovs_u128_is_zero(action->ct.label_mask)) { > - struct { > - ovs_u128 key; > - ovs_u128 mask; > - } *ct_label; > - > - ct_label = nl_msg_put_unspec_uninit(buf, > - OVS_CT_ATTR_LABELS, > - sizeof *ct_label); > - ct_label->key = action->ct.label; > - ct_label->mask = action->ct.label_mask; > - } > - > - if (action->ct.nat_type) { > - size_t nat_offset = nl_msg_start_nested(buf, > - OVS_CT_ATTR_NAT); > - > - if (action->ct.nat_type == TC_NAT_SRC) { > - nl_msg_put_flag(buf, OVS_NAT_ATTR_SRC); > - } else if (action->ct.nat_type == TC_NAT_DST) { > - nl_msg_put_flag(buf, OVS_NAT_ATTR_DST); > - } > - > - if (action->ct.range.ip_family == AF_INET) { > - nl_msg_put_be32(buf, OVS_NAT_ATTR_IP_MIN, > - action->ct.range.ipv4.min); > - nl_msg_put_be32(buf, OVS_NAT_ATTR_IP_MAX, > - action->ct.range.ipv4.max); > - } else if (action->ct.range.ip_family == AF_INET6) { > - nl_msg_put_in6_addr(buf, OVS_NAT_ATTR_IP_MIN, > - &action->ct.range.ipv6.min); > - nl_msg_put_in6_addr(buf, OVS_NAT_ATTR_IP_MAX, > - &action->ct.range.ipv6.max); > - } > - > - if (action->ct.range.port.min) { > - nl_msg_put_u16(buf, OVS_NAT_ATTR_PROTO_MIN, > - ntohs(action->ct.range.port.min)); > - if (action->ct.range.port.max) { > - nl_msg_put_u16(buf, OVS_NAT_ATTR_PROTO_MAX, > - ntohs(action->ct.range.port.max)); > - } > - } > - > - nl_msg_end_nested(buf, nat_offset); > - } > - > - nl_msg_end_nested(buf, ct_offset); > - } > - break; > - case TC_ACT_GOTO: { > - nl_msg_put_u32(buf, OVS_ACTION_ATTR_RECIRC, action->chain); > - } > - break; > - } > - } > - } > + parse_tc_flower_to_actions(flower, buf); > nl_msg_end_nested(buf, act_off); > > *actions = ofpbuf_at_assert(buf, act_off, sizeof(struct nlattr)); > > _______________________________________________ > 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