#include "vlog.h"
COVERAGE_DEFINE(xlate_actions);
+COVERAGE_DEFINE(xlate_actions_oversize);
VLOG_DEFINE_THIS_MODULE(ofproto_dpif_xlate);
ctx->recurse--;
}
-static void
-xlate_table_action(struct xlate_ctx *ctx,
- ofp_port_t in_port, uint8_t table_id, bool may_packet_in)
+static bool
+xlate_resubmit_resource_check(struct xlate_ctx *ctx)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
} else if (ctx->stack.size >= 65536) {
VLOG_ERR_RL(&rl, "resubmits yielded over 64 kB of stack");
} else {
+ return true;
+ }
+
+ return false;
+}
+
+static void
+xlate_table_action(struct xlate_ctx *ctx,
+ ofp_port_t in_port, uint8_t table_id, bool may_packet_in)
+{
+ if (xlate_resubmit_resource_check(ctx)) {
struct rule_dpif *rule;
ofp_port_t old_in_port = ctx->xin->flow.in_port.ofp_port;
uint8_t old_table_id = ctx->table_id;
}
}
+static bool
+compose_set_mpls_label_action(struct xlate_ctx *ctx, ovs_be32 label)
+{
+ if (!eth_type_mpls(ctx->xin->flow.dl_type)) {
+ return true;
+ }
+
+ /* If mpls_depth_delta is negative then an MPLS POP action has been
+ * executed and the resulting MPLS label stack is unknown. This means
+ * a SET MPLS LABEL action can't be executed as it needs to manipulate
+ * the top-most MPLS LSE. Thus, stop processing.
+ *
+ * It is planned that in the future this case will be handled
+ * by recirculation.
+ */
+ if (ctx->mpls_depth_delta < 0) {
+ return true;
+ }
+
+ ctx->xout->wc.masks.mpls_lse |= htonl(MPLS_LABEL_MASK);
+ set_mpls_lse_label(&ctx->xin->flow.mpls_lse, label);
+ return false;
+}
+
+static bool
+compose_set_mpls_tc_action(struct xlate_ctx *ctx, uint8_t tc)
+{
+ if (!eth_type_mpls(ctx->xin->flow.dl_type)) {
+ return true;
+ }
+
+ /* If mpls_depth_delta is negative then an MPLS POP action has been
+ * executed and the resulting MPLS label stack is unknown. This means
+ * a SET MPLS TC action can't be executed as it needs to manipulate
+ * the top-most MPLS LSE. Thus, stop processing.
+ *
+ * It is planned that in the future this case will be handled
+ * by recirculation.
+ */
+ if (ctx->mpls_depth_delta < 0) {
+ return true;
+ }
+
+ ctx->xout->wc.masks.mpls_lse |= htonl(MPLS_TC_MASK);
+ set_mpls_lse_tc(&ctx->xin->flow.mpls_lse, tc);
+ return false;
+}
+
static bool
compose_set_mpls_ttl_action(struct xlate_ctx *ctx, uint8_t ttl)
{
}
break;
+ case OFPACT_SET_MPLS_LABEL:
+ if (compose_set_mpls_label_action(ctx,
+ ofpact_get_SET_MPLS_LABEL(a)->label)) {
+ return;
+ }
+ break;
+
+ case OFPACT_SET_MPLS_TC:
+ if (compose_set_mpls_tc_action(ctx,
+ ofpact_get_SET_MPLS_TC(a)->tc)) {
+ return;
+ }
+ break;
+
case OFPACT_SET_MPLS_TTL:
if (compose_set_mpls_ttl_action(ctx,
ofpact_get_SET_MPLS_TTL(a)->ttl)) {
if (nl_attr_oversized(ctx.xout->odp_actions.size)) {
/* These datapath actions are too big for a Netlink attribute, so we
- * can't execute them. */
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-
- VLOG_ERR_RL(&rl, "discarding oversize datapath actions");
- ofpbuf_clear(&ctx.xout->odp_actions);
+ * can't hand them to the kernel directly. dpif_execute() can execute
+ * them one by one with help, so just mark the result as SLOW_ACTION to
+ * prevent the flow from being installed. */
+ COVERAGE_INC(xlate_actions_oversize);
+ ctx.xout->slow |= SLOW_ACTION;
}
ofpbuf_uninit(&ctx.stack);