}
static int
-xlate_flood_packet(struct xbridge *xbridge, struct dp_packet *packet)
+compose_table_xlate(struct xlate_ctx *ctx, const struct xport *out_dev,
+ struct dp_packet *packet)
{
+ struct xbridge *xbridge = out_dev->xbridge;
struct ofpact_output output;
struct flow flow;
ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output);
- /* Use OFPP_NONE as the in_port to avoid special packet processing. */
flow_extract(packet, &flow);
- flow.in_port.ofp_port = OFPP_NONE;
- output.port = OFPP_FLOOD;
+ flow.in_port.ofp_port = out_dev->ofp_port;
+ output.port = OFPP_TABLE;
output.max_len = 0;
- return ofproto_dpif_execute_actions(xbridge->ofproto, &flow, NULL,
- &output.ofpact, sizeof output,
- packet);
+ return ofproto_dpif_execute_actions__(xbridge->ofproto, &flow, NULL,
+ &output.ofpact, sizeof output,
+ ctx->recurse, ctx->resubmits, packet);
}
static void
-tnl_send_arp_request(const struct xport *out_dev,
+tnl_send_arp_request(struct xlate_ctx *ctx, const struct xport *out_dev,
const struct eth_addr eth_src,
ovs_be32 ip_src, ovs_be32 ip_dst)
{
- struct xbridge *xbridge = out_dev->xbridge;
struct dp_packet packet;
dp_packet_init(&packet, 0);
compose_arp(&packet, ARP_OP_REQUEST,
eth_src, eth_addr_zero, true, ip_src, ip_dst);
- xlate_flood_packet(xbridge, &packet);
+ compose_table_xlate(ctx, out_dev, &packet);
dp_packet_uninit(&packet);
}
xlate_report(ctx, "ARP cache miss for "IP_FMT" on bridge %s, "
"sending ARP request",
IP_ARGS(d_ip), out_dev->xbridge->name);
- tnl_send_arp_request(out_dev, smac, s_ip, d_ip);
+ tnl_send_arp_request(ctx, out_dev, smac, s_ip, d_ip);
return err;
}
if (ctx->xin->xcache) {
xin->resubmit_hook = NULL;
xin->report_hook = NULL;
xin->resubmit_stats = NULL;
+ xin->recurse = 0;
+ xin->resubmits = 0;
xin->wc = wc;
xin->odp_actions = odp_actions;
.wc = xin->wc ? xin->wc : &scratch_wc,
.odp_actions = xin->odp_actions ? xin->odp_actions : &scratch_actions,
- .recurse = 0,
- .resubmits = 0,
+ .recurse = xin->recurse,
+ .resubmits = xin->resubmits,
.in_group = false,
.in_action_set = false,
* calling xlate_in_init(). */
const struct dpif_flow_stats *resubmit_stats;
+ /* Recursion and resubmission levels carried over from a pre-existing
+ * translation of a related flow. An example of when this can occur is
+ * the translation of an ARP packet that was generated as the result of
+ * outputting to a tunnel port. In this case, the original flow going to
+ * the tunnel is the related flow. Since the two flows are different, they
+ * should not use the same xlate_ctx structure. However, we still need
+ * limit the maximum recursion across the entire translation.
+ *
+ * These fields are normally set to zero, so the client has to set them
+ * manually after calling xlate_in_init(). In that case, they should be
+ * copied from the same-named fields in the related flow's xlate_ctx. */
+ int recurse;
+ int resubmits;
+
/* If nonnull, flow translation populates this cache with references to all
* modules that are affected by translation. This 'xlate_cache' may be
* passed to xlate_push_stats() to perform the same function as
}
}
-/* Executes, within 'ofproto', the actions in 'rule' or 'ofpacts' on 'packet'.
- * 'flow' must reflect the data in 'packet'. */
int
-ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto,
- const struct flow *flow,
- struct rule_dpif *rule,
- const struct ofpact *ofpacts, size_t ofpacts_len,
- struct dp_packet *packet)
+ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto,
+ const struct flow *flow,
+ struct rule_dpif *rule,
+ const struct ofpact *ofpacts, size_t ofpacts_len,
+ int recurse, int resubmits,
+ struct dp_packet *packet)
{
struct dpif_flow_stats stats;
struct xlate_out xout;
xin.ofpacts = ofpacts;
xin.ofpacts_len = ofpacts_len;
xin.resubmit_stats = &stats;
+ xin.recurse = recurse;
+ xin.resubmits = resubmits;
xlate_actions(&xin, &xout);
execute.actions = odp_actions.data;
return error;
}
+/* Executes, within 'ofproto', the actions in 'rule' or 'ofpacts' on 'packet'.
+ * 'flow' must reflect the data in 'packet'. */
+int
+ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto,
+ const struct flow *flow,
+ struct rule_dpif *rule,
+ const struct ofpact *ofpacts, size_t ofpacts_len,
+ struct dp_packet *packet)
+{
+ return ofproto_dpif_execute_actions__(ofproto, flow, rule, ofpacts,
+ ofpacts_len, 0, 0, packet);
+}
+
void
rule_dpif_credit_stats(struct rule_dpif *rule,
const struct dpif_flow_stats *stats)
int ofproto_dpif_execute_actions(struct ofproto_dpif *, const struct flow *,
struct rule_dpif *, const struct ofpact *,
size_t ofpacts_len, struct dp_packet *);
+int ofproto_dpif_execute_actions__(struct ofproto_dpif *, const struct flow *,
+ struct rule_dpif *, const struct ofpact *,
+ size_t ofpacts_len, int recurse,
+ int resubmits, struct dp_packet *);
void ofproto_dpif_send_packet_in(struct ofproto_dpif *,
struct ofproto_packet_in *);
bool ofproto_dpif_wants_packet_in_on_miss(struct ofproto_dpif *);