#include "ovs-router.h"
#include "tnl-ports.h"
#include "tunnel.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
COVERAGE_DEFINE(xlate_actions);
COVERAGE_DEFINE(xlate_actions_oversize);
COVERAGE_DEFINE(xlate_actions_too_many_output);
-COVERAGE_DEFINE(xlate_actions_mpls_overflow);
VLOG_DEFINE_THIS_MODULE(ofproto_dpif_xlate);
struct hmap_node hmap_node; /* Node in global 'xbridges' map. */
struct ofproto_dpif *ofproto; /* Key in global 'xbridges' map. */
- struct list xbundles; /* Owned xbundles. */
+ struct ovs_list xbundles; /* Owned xbundles. */
struct hmap xports; /* Indexed by ofp_port. */
char *name; /* Name used in log messages. */
struct hmap_node hmap_node; /* In global 'xbundles' map. */
struct ofbundle *ofbundle; /* Key in global 'xbundles' map. */
- struct list list_node; /* In parent 'xbridges' list. */
+ struct ovs_list list_node; /* In parent 'xbridges' list. */
struct xbridge *xbridge; /* Parent xbridge. */
- struct list xports; /* Contains "struct xport"s. */
+ struct ovs_list xports; /* Contains "struct xport"s. */
char *name; /* Name used in log messages. */
struct bond *bond; /* Nonnull iff more than one port. */
odp_port_t odp_port; /* Datapath port number or ODPP_NONE. */
- struct list bundle_node; /* In parent xbundle (if it exists). */
+ struct ovs_list bundle_node; /* In parent xbundle (if it exists). */
struct xbundle *xbundle; /* Parent xbundle or null. */
struct netdev *netdev; /* 'ofport''s netdev. */
const struct group_dpif *group, int depth)
{
struct ofputil_bucket *bucket;
- const struct list *buckets;
+ const struct ovs_list *buckets;
group_dpif_get_buckets(group, &buckets);
LIST_FOR_EACH (bucket, list_node, buckets) {
int i = 0;
struct ofputil_bucket *bucket;
- const struct list *buckets;
+ const struct ovs_list *buckets;
group_dpif_get_buckets(group, &buckets);
LIST_FOR_EACH (bucket, list_node, buckets) {
const struct xport *peer = xport->peer;
struct flow old_flow = ctx->xin->flow;
enum slow_path_reason special;
+ uint8_t table_id = rule_dpif_lookup_get_init_table_id(&ctx->xin->flow);
ctx->xbridge = peer->xbridge;
flow->in_port.ofp_port = peer->ofp_port;
ctx->xout->slow |= special;
} else if (may_receive(peer, ctx)) {
if (xport_stp_forward_state(peer) && xport_rstp_forward_state(peer)) {
- xlate_table_action(ctx, flow->in_port.ofp_port, 0, true, true);
+ xlate_table_action(ctx, flow->in_port.ofp_port, table_id,
+ true, true);
} else {
/* Forwarding is disabled by STP and RSTP. Let OFPP_NORMAL and
* the learning action look at the packet, then drop it. */
struct flow old_base_flow = ctx->base_flow;
size_t old_size = ofpbuf_size(ctx->xout->odp_actions);
mirror_mask_t old_mirrors = ctx->xout->mirrors;
- xlate_table_action(ctx, flow->in_port.ofp_port, 0, true, true);
+ xlate_table_action(ctx, flow->in_port.ofp_port, table_id,
+ true, true);
ctx->xout->mirrors = old_mirrors;
ctx->base_flow = old_base_flow;
ofpbuf_set_size(ctx->xout->odp_actions, old_size);
xlate_all_group(struct xlate_ctx *ctx, struct group_dpif *group)
{
struct ofputil_bucket *bucket;
- const struct list *buckets;
+ const struct ovs_list *buckets;
struct flow old_flow = ctx->xin->flow;
group_dpif_get_buckets(group, &buckets);
}
ctx->exit = true;
return;
- } else if (n >= ctx->xbridge->max_mpls_depth) {
- COVERAGE_INC(xlate_actions_mpls_overflow);
- ctx->xout->slow |= SLOW_ACTION;
}
flow_push_mpls(flow, n, mpls->ethertype, wc);
int n = flow_count_mpls_labels(flow, wc);
if (flow_pop_mpls(flow, n, eth_type, wc)) {
- if (ctx->xbridge->enable_recirc && !eth_type_mpls(eth_type)) {
+ if (ctx->xbridge->enable_recirc) {
ctx->was_mpls = true;
}
} else if (n >= FLOW_MAX_MPLS_LABELS) {
}
static bool
-ofpact_needs_recirculation_after_mpls(const struct xlate_ctx *ctx,
- const struct ofpact *a)
+ofpact_needs_recirculation_after_mpls(const struct ofpact *a, struct xlate_ctx *ctx)
{
struct flow_wildcards *wc = &ctx->xout->wc;
struct flow *flow = &ctx->xin->flow;
+ if (!ctx->was_mpls) {
+ return false;
+ }
+
switch (a->type) {
case OFPACT_OUTPUT:
case OFPACT_GROUP:
case OFPACT_SET_TUNNEL:
case OFPACT_SET_QUEUE:
case OFPACT_POP_QUEUE:
- case OFPACT_POP_MPLS:
- case OFPACT_DEC_MPLS_TTL:
- case OFPACT_SET_MPLS_TTL:
- case OFPACT_SET_MPLS_TC:
- case OFPACT_SET_MPLS_LABEL:
case OFPACT_NOTE:
case OFPACT_OUTPUT_REG:
case OFPACT_EXIT:
case OFPACT_SAMPLE:
return false;
+ case OFPACT_POP_MPLS:
+ case OFPACT_DEC_MPLS_TTL:
+ case OFPACT_SET_MPLS_TTL:
+ case OFPACT_SET_MPLS_TC:
+ case OFPACT_SET_MPLS_LABEL:
case OFPACT_SET_IPV4_SRC:
case OFPACT_SET_IPV4_DST:
case OFPACT_SET_IP_DSCP:
break;
}
- if (ctx->was_mpls && ofpact_needs_recirculation_after_mpls(ctx, a)) {
+ if (ofpact_needs_recirculation_after_mpls(a, ctx)) {
compose_recirculate_action(ctx, ofpacts, a, ofpacts_len);
return;
}