2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-29 15:28:56 +00:00

Remove mpls_depth field from flow

Rather than tracking the MPLS depth as a field in the
flow, which is an entirely poor place for it, just track
the delta to the MPLS depth during translation.

This logic was developed while implementing recirculation
and intended to be used to detect when recirculation should
occur. This variant of the patch uses the logic to determine
if processing of actions should stop due to an MPLS
action which cannot be translated (without recirculation).

A side-effect of this patch is that it resolves a bug
whereby ovs-vswitchd will abort due to to an assertion
on eth_type_mpls(ctx->xin->flow.dl_type) in compose_mpls_pop_action(()
if the actions of a flow include pop_mpls twice without
a push_mpls in between.

Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Simon Horman
2013-09-27 06:55:19 +09:00
committed by Ben Pfaff
parent e15653c927
commit b0a17866c3
13 changed files with 153 additions and 81 deletions

View File

@@ -2503,9 +2503,7 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data,
arp_key->arp_op = htons(data->nw_proto);
memcpy(arp_key->arp_sha, data->arp_sha, ETH_ADDR_LEN);
memcpy(arp_key->arp_tha, data->arp_tha, ETH_ADDR_LEN);
}
if (flow->mpls_depth) {
} else if (eth_type_mpls(flow->dl_type)) {
struct ovs_key_mpls *mpls_key;
mpls_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_MPLS,
@@ -2798,7 +2796,6 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
return ODP_FIT_TOO_LITTLE;
}
flow->mpls_lse = nl_attr_get_be32(attrs[OVS_KEY_ATTR_MPLS]);
flow->mpls_depth++;
} else if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_MPLS)) {
flow->mpls_lse = nl_attr_get_be32(attrs[OVS_KEY_ATTR_MPLS]);
@@ -2806,10 +2803,6 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
return ODP_FIT_ERROR;
}
expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_MPLS);
if (flow->mpls_lse) {
/* XXX Is this needed? */
flow->mpls_depth = 0xffff;
}
}
goto done;
} else if (src_flow->dl_type == htons(ETH_TYPE_IP)) {
@@ -3351,48 +3344,44 @@ commit_vlan_action(const struct flow *flow, struct flow *base,
static void
commit_mpls_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions, struct flow_wildcards *wc)
struct ofpbuf *odp_actions, struct flow_wildcards *wc,
int *mpls_depth_delta)
{
if (flow->mpls_lse == base->mpls_lse &&
flow->mpls_depth == base->mpls_depth) {
if (flow->mpls_lse == base->mpls_lse && !*mpls_depth_delta) {
return;
}
memset(&wc->masks.mpls_lse, 0xff, sizeof wc->masks.mpls_lse);
if (flow->mpls_depth < base->mpls_depth) {
if (base->mpls_depth - flow->mpls_depth > 1) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10);
VLOG_WARN_RL(&rl, "Multiple mpls_pop actions reduced to "
" a single mpls_pop action");
}
switch (*mpls_depth_delta) {
case -1:
nl_msg_put_be16(odp_actions, OVS_ACTION_ATTR_POP_MPLS, flow->dl_type);
} else if (flow->mpls_depth > base->mpls_depth) {
break;
case 1: {
struct ovs_action_push_mpls *mpls;
if (flow->mpls_depth - base->mpls_depth > 1) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10);
VLOG_WARN_RL(&rl, "Multiple mpls_push actions reduced to "
" a single mpls_push action");
}
mpls = nl_msg_put_unspec_uninit(odp_actions, OVS_ACTION_ATTR_PUSH_MPLS,
sizeof *mpls);
memset(mpls, 0, sizeof *mpls);
mpls->mpls_ethertype = flow->dl_type;
mpls->mpls_lse = flow->mpls_lse;
} else {
break;
}
case 0: {
struct ovs_key_mpls mpls_key;
mpls_key.mpls_lse = flow->mpls_lse;
commit_set_action(odp_actions, OVS_KEY_ATTR_MPLS,
&mpls_key, sizeof(mpls_key));
break;
}
default:
NOT_REACHED();
}
base->dl_type = flow->dl_type;
base->mpls_lse = flow->mpls_lse;
base->mpls_depth = flow->mpls_depth;
*mpls_depth_delta = 0;
}
static void
@@ -3563,7 +3552,8 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base,
* used as part of the action. */
void
commit_odp_actions(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions, struct flow_wildcards *wc)
struct ofpbuf *odp_actions, struct flow_wildcards *wc,
int *mpls_depth_delta)
{
commit_set_ether_addr_action(flow, base, odp_actions, wc);
commit_vlan_action(flow, base, odp_actions, wc);
@@ -3573,7 +3563,7 @@ commit_odp_actions(const struct flow *flow, struct flow *base,
* actions. This is because committing MPLS actions may alter a packet so
* that it is no longer IP and thus nw and port actions are no longer valid.
*/
commit_mpls_action(flow, base, odp_actions, wc);
commit_mpls_action(flow, base, odp_actions, wc, mpls_depth_delta);
commit_set_priority_action(flow, base, odp_actions, wc);
commit_set_pkt_mark_action(flow, base, odp_actions, wc);
}