2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-30 22:05:19 +00:00

netdev-offload-tc: Move flower_to_match action handling to isolated function.

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 <echaudro@redhat.com>
Acked-by: Mike Pattrick <mkp@redhat.com>
Acked-by: Roi Dayan <roid@nvidia.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Eelco Chaudron
2022-07-13 10:20:16 +02:00
committed by Ilya Maximets
parent 64365293a5
commit dd03672f7b

View File

@@ -646,6 +646,235 @@ 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;
case TC_ACT_POLICE: {
uint32_t meter_id;
if (police_idx_lookup(action->police.index, &meter_id)) {
return ENOENT;
}
nl_msg_put_u32(buf, OVS_ACTION_ATTR_METER, meter_id);
}
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,
@@ -658,9 +887,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);
@@ -851,213 +1077,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;
case TC_ACT_POLICE: {
uint32_t meter_id;
if (police_idx_lookup(action->police.index, &meter_id)) {
return ENOENT;
}
nl_msg_put_u32(buf, OVS_ACTION_ATTR_METER, meter_id);
}
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));