error = netdev_get_stats(ofport->up.netdev, stats);
- if (!error && ofport->odp_port == OVSP_LOCAL) {
+ if (!error && ofport_->ofp_port == OFPP_LOCAL) {
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
/* ofproto->stats.tx_packets represents packets that we created
ofpbuf_use_stack(&buf, stub, stub_size);
if (slow & (SLOW_CFM | SLOW_LACP | SLOW_STP)) {
- uint32_t pid = dpif_port_get_pid(ofproto->backer->dpif, UINT16_MAX);
+ uint32_t pid = dpif_port_get_pid(ofproto->backer->dpif, UINT32_MAX);
odp_put_userspace_action(pid, &cookie, &buf);
} else {
put_userspace_action(ofproto, &buf, flow, &cookie);
ovs_be16 initial_tci, struct rule_dpif *rule,
uint8_t tcp_flags, const struct ofpbuf *packet)
{
+ ovs_be64 initial_tun_id = flow->tunnel.tun_id;
+
+ /* Flow initialization rules:
+ * - 'base_flow' must match the kernel's view of the packet at the
+ * time that action processing starts. 'flow' represents any
+ * transformations we wish to make through actions.
+ * - By default 'base_flow' and 'flow' are the same since the input
+ * packet matches the output before any actions are applied.
+ * - When using VLAN splinters, 'base_flow''s VLAN is set to the value
+ * of the received packet as seen by the kernel. If we later output
+ * to another device without any modifications this will cause us to
+ * insert a new tag since the original one was stripped off by the
+ * VLAN device.
+ * - Tunnel 'flow' is largely cleared when transitioning between
+ * the input and output stages since it does not make sense to output
+ * a packet with the exact headers that it was received with (i.e.
+ * the destination IP is us). The one exception is the tun_id, which
+ * is preserved to allow use in later resubmit lookups and loads into
+ * registers.
+ * - Tunnel 'base_flow' is completely cleared since that is what the
+ * kernel does. If we wish to maintain the original values an action
+ * needs to be generated. */
+
ctx->ofproto = ofproto;
ctx->flow = *flow;
memset(&ctx->flow.tunnel, 0, sizeof ctx->flow.tunnel);
ctx->base_flow = ctx->flow;
ctx->base_flow.vlan_tci = initial_tci;
+ ctx->flow.tunnel.tun_id = initial_tun_id;
ctx->rule = rule;
ctx->packet = packet;
ctx->may_learn = packet != NULL;
} else {
static struct vlog_rate_limit trace_rl = VLOG_RATE_LIMIT_INIT(1, 1);
ovs_be16 initial_tci = ctx->base_flow.vlan_tci;
+ uint32_t local_odp_port;
add_sflow_action(ctx);
do_xlate_actions(ofpacts, ofpacts_len, ctx);
}
}
+ local_odp_port = ofp_port_to_odp_port(ctx->ofproto, OFPP_LOCAL);
if (!connmgr_may_set_up_flow(ctx->ofproto->up.connmgr, &ctx->flow,
+ local_odp_port,
ctx->odp_actions->data,
ctx->odp_actions->size)) {
ctx->slow |= SLOW_IN_BAND;
struct ofport_dpif *port;
port = odp_port_to_ofport(ofproto->backer, odp_port);
- if (port && ofproto == ofproto_dpif_cast(port->up.ofproto)) {
+ if (port && &ofproto->up == port->up.ofproto) {
return port->up.ofp_port;
} else {
return OFPP_NONE;