* this flow when actions change header fields. */
struct flow flow;
+ /* Flow at the last commit. */
+ struct flow base_flow;
+
+ /* Tunnel IP destination address as received. This is stored separately
+ * as the base_flow.tunnel is cleared on init to reflect the datapath
+ * behavior. Used to make sure not to send tunneled output to ourselves,
+ * which might lead to an infinite loop. This could happen easily
+ * if a tunnel is marked as 'ip_remote=flow', and the flow does not
+ * actually set the tun_dst field. */
+ ovs_be32 orig_tunnel_ip_dst;
+
/* stack for the push and pop actions.
* Each stack element is of the type "union mf_subvalue". */
struct ofpbuf stack;
int recurse; /* Recursion level, via xlate_table_action. */
bool max_resubmit_trigger; /* Recursed too deeply during translation. */
- struct flow base_flow; /* Flow at the last commit. */
uint32_t orig_skb_priority; /* Priority when packet arrived. */
uint8_t table_id; /* OpenFlow table ID where flow was found. */
uint32_t sflow_n_outputs; /* Number of output ports. */
netflow_expire(ofproto->netflow, &facet->nf_flow, &expired);
}
- facet->rule->packet_count += facet->packet_count;
- facet->rule->byte_count += facet->byte_count;
-
/* Reset counters to prevent double counting if 'facet' ever gets
* reinstalled. */
facet_reset_counters(facet);
facet->prev_byte_count = facet->byte_count;
facet->prev_used = facet->used;
+ rule_credit_stats(facet->rule, &stats);
flow_push_stats(facet, &stats);
update_mirror_stats(ofproto_dpif_cast(facet->rule->up.ofproto),
rule_get_stats(struct rule *rule_, uint64_t *packets, uint64_t *bytes)
{
struct rule_dpif *rule = rule_dpif_cast(rule_);
- struct facet *facet;
/* push_all_stats() can handle flow misses which, when using the learn
* action, can cause rules to be added and deleted. This can corrupt our
* in facets. This counts, for example, facets that have expired. */
*packets = rule->packet_count;
*bytes = rule->byte_count;
-
- /* Add any statistics that are tracked by facets. This includes
- * statistical data recently updated by ofproto_update_stats() as well as
- * stats for packets that were executed "by hand" via dpif_execute(). */
- LIST_FOR_EACH (facet, list_node, &rule->facets) {
- *packets += facet->packet_count;
- *bytes += facet->byte_count;
- }
}
static void
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
uint64_t odp_actions_stub[1024 / 8];
struct ofpbuf key, odp_actions;
+ struct dpif_flow_stats stats;
struct odputil_keybuf keybuf;
- uint32_t odp_port;
+ struct ofpact_output output;
+ struct action_xlate_ctx ctx;
struct flow flow;
int error;
- flow_extract(packet, 0, 0, NULL, OFPP_LOCAL, &flow);
- if (netdev_vport_is_patch(ofport->up.netdev)) {
- struct ofproto_dpif *peer_ofproto;
- struct dpif_flow_stats stats;
- struct ofport_dpif *peer;
- struct rule_dpif *rule;
-
- peer = ofport_get_peer(ofport);
- if (!peer) {
- return ENODEV;
- }
-
- dpif_flow_stats_extract(&flow, packet, time_msec(), &stats);
- netdev_vport_inc_tx(ofport->up.netdev, &stats);
- netdev_vport_inc_rx(peer->up.netdev, &stats);
-
- flow.in_port = peer->up.ofp_port;
- peer_ofproto = ofproto_dpif_cast(peer->up.ofproto);
- rule = rule_dpif_lookup(peer_ofproto, &flow);
- rule_dpif_execute(rule, &flow, packet);
-
- return 0;
- }
-
ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub);
+ ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
- if (ofport->tnl_port) {
- struct dpif_flow_stats stats;
-
- odp_port = tnl_port_send(ofport->tnl_port, &flow);
- if (odp_port == OVSP_NONE) {
- return ENODEV;
- }
-
- dpif_flow_stats_extract(&flow, packet, time_msec(), &stats);
- netdev_vport_inc_tx(ofport->up.netdev, &stats);
- odp_put_tunnel_action(&flow.tunnel, &odp_actions);
- odp_put_skb_mark_action(flow.skb_mark, &odp_actions);
- } else {
- odp_port = vsp_realdev_to_vlandev(ofproto, ofport->odp_port,
- flow.vlan_tci);
- if (odp_port != ofport->odp_port) {
- eth_pop_vlan(packet);
- flow.vlan_tci = htons(0);
- }
- }
+ /* Use OFPP_NONE as the in_port to avoid special packet processing. */
+ flow_extract(packet, 0, 0, NULL, OFPP_NONE, &flow);
+ odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(ofproto,
+ OFPP_LOCAL));
+ dpif_flow_stats_extract(&flow, packet, time_msec(), &stats);
- ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, &flow,
- ofp_port_to_odp_port(ofproto, flow.in_port));
+ ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output);
+ output.port = ofport->up.ofp_port;
+ output.max_len = 0;
- compose_sflow_action(ofproto, &odp_actions, &flow, odp_port);
- compose_ipfix_action(ofproto, &odp_actions, &flow);
+ action_xlate_ctx_init(&ctx, ofproto, &flow, NULL, NULL, 0, packet);
+ ctx.resubmit_stats = &stats;
+ xlate_actions(&ctx, &output.ofpact, sizeof output, &odp_actions);
- nl_msg_put_u32(&odp_actions, OVS_ACTION_ATTR_OUTPUT, odp_port);
error = dpif_execute(ofproto->backer->dpif,
key.data, key.size,
odp_actions.data, odp_actions.size,
ofpbuf_uninit(&odp_actions);
if (error) {
- VLOG_WARN_RL(&rl, "%s: failed to send packet on port %"PRIu32" (%s)",
- ofproto->up.name, odp_port, strerror(error));
+ VLOG_WARN_RL(&rl, "%s: failed to send packet on port %s (%s)",
+ ofproto->up.name, netdev_get_name(ofport->up.netdev),
+ strerror(error));
}
ofproto->stats.tx_packets++;
xlate_report(ctx, "Tunneling decided against output");
goto out; /* restore flow_nw_tos */
}
-
+ if (ctx->flow.tunnel.ip_dst == ctx->orig_tunnel_ip_dst) {
+ xlate_report(ctx, "Not tunneling to our own address");
+ goto out; /* restore flow_nw_tos */
+ }
if (ctx->resubmit_stats) {
netdev_vport_inc_tx(ofport->up.netdev, ctx->resubmit_stats);
}
ctx->flow = *flow;
ctx->base_flow = ctx->flow;
memset(&ctx->base_flow.tunnel, 0, sizeof ctx->base_flow.tunnel);
- ctx->base_flow.vlan_tci = initial_vals->vlan_tci;
+ ctx->orig_tunnel_ip_dst = flow->tunnel.ip_dst;
ctx->rule = rule;
ctx->packet = packet;
ctx->may_learn = packet != NULL;
ctx->resubmit_hook = NULL;
ctx->report_hook = NULL;
ctx->resubmit_stats = NULL;
+
+ if (initial_vals) {
+ ctx->base_flow.vlan_tci = initial_vals->vlan_tci;
+ }
}
/* Translates the 'ofpacts_len' bytes of "struct ofpacts" starting at 'ofpacts'