int recurse; /* Recursion level, via xlate_table_action. */
int last_pop_priority; /* Offset in 'odp_actions' just past most
- * recently added ODPAT_SET_PRIORITY. */
+ * recent ODP_ACTION_ATTR_SET_PRIORITY. */
};
static void action_xlate_ctx_init(struct action_xlate_ctx *,
*
* - Do include packets and bytes that were obtained from the datapath
* when a flow was deleted (e.g. dpif_flow_del()) or when its
- * statistics were reset (e.g. dpif_flow_put() with ODPPF_ZERO_STATS).
+ * statistics were reset (e.g. dpif_flow_put() with
+ * DPIF_FP_ZERO_STATS).
*
* - Do not include any packets or bytes that can currently be obtained
* from the datapath by, e.g., dpif_flow_get().
static void facet_make_actions(struct ofproto *, struct facet *,
const struct ofpbuf *packet);
static void facet_update_stats(struct ofproto *, struct facet *,
- const struct odp_flow_stats *);
+ const struct dpif_flow_stats *);
/* ofproto supports two kinds of OpenFlow connections:
*
/* OFPT_PACKET_IN related data. */
struct rconn_packet_counter *packet_in_counter; /* # queued on 'rconn'. */
- struct pinsched *schedulers[2]; /* Indexed by reason code; see below. */
+#define N_SCHEDULERS 2
+ struct pinsched *schedulers[N_SCHEDULERS];
struct pktbuf *pktbuf; /* OpenFlow packet buffers. */
int miss_send_len; /* Bytes to send of buffered packets. */
enum ofproto_band band; /* In-band or out-of-band? */
};
-/* We use OFPR_NO_MATCH and OFPR_ACTION as indexes into struct ofconn's
- * "schedulers" array. Their values are 0 and 1, and their meanings and values
- * coincide with _ODPL_MISS_NR and _ODPL_ACTION_NR, so this is convenient. In
- * case anything ever changes, check their values here. */
-#define N_SCHEDULERS 2
-BUILD_ASSERT_DECL(OFPR_NO_MATCH == 0);
-BUILD_ASSERT_DECL(OFPR_NO_MATCH == _ODPL_MISS_NR);
-BUILD_ASSERT_DECL(OFPR_ACTION == 1);
-BUILD_ASSERT_DECL(OFPR_ACTION == _ODPL_ACTION_NR);
static struct ofconn *ofconn_create(struct ofproto *, struct rconn *,
enum ofconn_type);
VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error));
return error;
}
- error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION | ODPL_SFLOW);
+ error = dpif_recv_set_mask(dpif,
+ ((1u << DPIF_UC_MISS) |
+ (1u << DPIF_UC_ACTION) |
+ (1u << DPIF_UC_SAMPLE)));
if (error) {
VLOG_ERR("failed to listen on datapath %s: %s",
datapath, strerror(error));
cinfo->pairs.n = 0;
- if (last_error == EOF) {
- cinfo->pairs.keys[cinfo->pairs.n] = "last_error";
- cinfo->pairs.values[cinfo->pairs.n++] = xstrdup("End of file");
- } else if (last_error > 0) {
+ if (last_error) {
cinfo->pairs.keys[cinfo->pairs.n] = "last_error";
cinfo->pairs.values[cinfo->pairs.n++] =
- xstrdup(strerror(last_error));
+ xstrdup(ovs_retval_to_string(last_error));
}
cinfo->pairs.keys[cinfo->pairs.n] = "state";
struct ofpbuf *packet)
{
if (actions_len == NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t))
- && odp_actions->nla_type == ODPAT_CONTROLLER) {
+ && odp_actions->nla_type == ODP_ACTION_ATTR_CONTROLLER) {
/* As an optimization, avoid a round-trip from userspace to kernel to
* userspace. This also avoids possibly filling up kernel packet
* buffers along the way. */
struct dpif_upcall upcall;
- upcall.type = _ODPL_ACTION_NR;
+ upcall.type = DPIF_UC_ACTION;
upcall.packet = packet;
upcall.key = NULL;
upcall.key_len = 0;
facet_execute(struct ofproto *ofproto, struct facet *facet,
struct ofpbuf *packet)
{
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in));
}
static int
-facet_put__(struct ofproto *ofproto, struct facet *facet, int flags)
+facet_put__(struct ofproto *ofproto, struct facet *facet,
+ const struct nlattr *actions, size_t actions_len,
+ struct dpif_flow_stats *stats)
{
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
+ enum dpif_flow_put_flags flags;
struct ofpbuf key;
+ flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
+ if (stats) {
+ flags |= DPIF_FP_ZERO_STATS;
+ }
+
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
odp_flow_key_from_flow(&key, &facet->flow);
assert(key.base == keybuf);
return dpif_flow_put(ofproto->dpif, flags, key.data, key.size,
- facet->actions, facet->actions_len, NULL);
+ actions, actions_len, stats);
}
/* If 'facet' is installable, inserts or re-inserts it into 'p''s datapath. If
static void
facet_install(struct ofproto *p, struct facet *facet, bool zero_stats)
{
- if (facet->may_install) {
- int flags = ODPPF_CREATE | ODPPF_MODIFY;
- if (zero_stats) {
- flags |= ODPPF_ZERO_STATS;
- }
- if (!facet_put__(p, facet, flags)) {
- facet->installed = true;
- }
+ struct dpif_flow_stats stats;
+
+ if (facet->may_install
+ && !facet_put__(p, facet, facet->actions, facet->actions_len,
+ zero_stats ? &stats : NULL)) {
+ facet->installed = true;
}
}
{
if (facet->installed) {
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
struct ofpbuf key;
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
/* If the ODP actions changed or the installability changed, then we need
* to talk to the datapath. */
- if (actions_changed || facet->may_install != facet->installed) {
- if (facet->may_install) {
- uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow_stats stats;
- struct ofpbuf key;
-
- ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, &facet->flow);
-
- dpif_flow_put(ofproto->dpif,
- ODPPF_CREATE | ODPPF_MODIFY | ODPPF_ZERO_STATS,
- key.data, key.size,
- odp_actions->data, odp_actions->size, &stats);
+ if (actions_changed || ctx.may_set_up_flow != facet->installed) {
+ if (ctx.may_set_up_flow) {
+ struct dpif_flow_stats stats;
+ facet_put__(ofproto, facet,
+ odp_actions->data, odp_actions->size, &stats);
facet_update_stats(ofproto, facet, &stats);
} else {
facet_uninstall(ofproto, facet);
*/
}
- nl_msg_put_u32(ctx->odp_actions, ODPAT_OUTPUT, port);
+ nl_msg_put_u32(ctx->odp_actions, ODP_ACTION_ATTR_OUTPUT, port);
ctx->nf_output_iface = port;
}
HMAP_FOR_EACH (ofport, hmap_node, &ofproto->ports) {
uint16_t odp_port = ofport->odp_port;
if (odp_port != odp_in_port && !(ofport->opp.config & mask)) {
- nl_msg_put_u32(odp_actions, ODPAT_OUTPUT, odp_port);
+ nl_msg_put_u32(odp_actions, ODP_ACTION_ATTR_OUTPUT, odp_port);
}
}
*nf_output_iface = NF_OUT_FLOOD;
&ctx->nf_output_iface, ctx->odp_actions);
break;
case OFPP_CONTROLLER:
- nl_msg_put_u64(ctx->odp_actions, ODPAT_CONTROLLER, max_len);
+ nl_msg_put_u64(ctx->odp_actions, ODP_ACTION_ATTR_CONTROLLER, max_len);
break;
case OFPP_LOCAL:
add_output_action(ctx, ODPP_LOCAL);
add_pop_action(struct action_xlate_ctx *ctx)
{
if (ctx->odp_actions->size != ctx->last_pop_priority) {
- nl_msg_put_flag(ctx->odp_actions, ODPAT_POP_PRIORITY);
+ nl_msg_put_flag(ctx->odp_actions, ODP_ACTION_ATTR_POP_PRIORITY);
ctx->last_pop_priority = ctx->odp_actions->size;
}
}
/* Add ODP actions. */
remove_pop_action(ctx);
- nl_msg_put_u32(ctx->odp_actions, ODPAT_SET_PRIORITY, priority);
+ nl_msg_put_u32(ctx->odp_actions, ODP_ACTION_ATTR_SET_PRIORITY, priority);
add_output_action(ctx, odp_port);
add_pop_action(ctx);
}
remove_pop_action(ctx);
- nl_msg_put_u32(ctx->odp_actions, ODPAT_SET_PRIORITY, priority);
+ nl_msg_put_u32(ctx->odp_actions, ODP_ACTION_ATTR_SET_PRIORITY, priority);
}
static void
{
ovs_be16 tci = ctx->flow.vlan_tci;
if (!(tci & htons(VLAN_CFI))) {
- nl_msg_put_flag(ctx->odp_actions, ODPAT_STRIP_VLAN);
+ nl_msg_put_flag(ctx->odp_actions, ODP_ACTION_ATTR_STRIP_VLAN);
} else {
- nl_msg_put_be16(ctx->odp_actions, ODPAT_SET_DL_TCI,
+ nl_msg_put_be16(ctx->odp_actions, ODP_ACTION_ATTR_SET_DL_TCI,
tci & ~htons(VLAN_CFI));
}
}
xlate_set_dl_tci(ctx);
}
if (ctx->flow.tun_id != state->tun_id) {
- nl_msg_put_be64(ctx->odp_actions, ODPAT_SET_TUNNEL, ctx->flow.tun_id);
+ nl_msg_put_be64(ctx->odp_actions,
+ ODP_ACTION_ATTR_SET_TUNNEL, ctx->flow.tun_id);
}
}
case NXAST_SET_TUNNEL:
nast = (const struct nx_action_set_tunnel *) nah;
tun_id = htonll(ntohl(nast->tun_id));
- nl_msg_put_be64(ctx->odp_actions, ODPAT_SET_TUNNEL, tun_id);
+ nl_msg_put_be64(ctx->odp_actions, ODP_ACTION_ATTR_SET_TUNNEL, tun_id);
ctx->flow.tun_id = tun_id;
break;
case NXAST_DROP_SPOOFED_ARP:
if (ctx->flow.dl_type == htons(ETH_TYPE_ARP)) {
- nl_msg_put_flag(ctx->odp_actions, ODPAT_DROP_SPOOFED_ARP);
+ nl_msg_put_flag(ctx->odp_actions,
+ ODP_ACTION_ATTR_DROP_SPOOFED_ARP);
}
break;
case NXAST_SET_TUNNEL64:
tun_id = ((const struct nx_action_set_tunnel64 *) nah)->tun_id;
- nl_msg_put_be64(ctx->odp_actions, ODPAT_SET_TUNNEL, tun_id);
+ nl_msg_put_be64(ctx->odp_actions, ODP_ACTION_ATTR_SET_TUNNEL, tun_id);
ctx->flow.tun_id = tun_id;
break;
case OFPAT_SET_DL_SRC:
oada = ((struct ofp_action_dl_addr *) ia);
- nl_msg_put_unspec(ctx->odp_actions, ODPAT_SET_DL_SRC,
+ nl_msg_put_unspec(ctx->odp_actions, ODP_ACTION_ATTR_SET_DL_SRC,
oada->dl_addr, ETH_ADDR_LEN);
memcpy(ctx->flow.dl_src, oada->dl_addr, ETH_ADDR_LEN);
break;
case OFPAT_SET_DL_DST:
oada = ((struct ofp_action_dl_addr *) ia);
- nl_msg_put_unspec(ctx->odp_actions, ODPAT_SET_DL_DST,
+ nl_msg_put_unspec(ctx->odp_actions, ODP_ACTION_ATTR_SET_DL_DST,
oada->dl_addr, ETH_ADDR_LEN);
memcpy(ctx->flow.dl_dst, oada->dl_addr, ETH_ADDR_LEN);
break;
case OFPAT_SET_NW_SRC:
- nl_msg_put_be32(ctx->odp_actions, ODPAT_SET_NW_SRC,
+ nl_msg_put_be32(ctx->odp_actions, ODP_ACTION_ATTR_SET_NW_SRC,
ia->nw_addr.nw_addr);
ctx->flow.nw_src = ia->nw_addr.nw_addr;
break;
case OFPAT_SET_NW_DST:
- nl_msg_put_be32(ctx->odp_actions, ODPAT_SET_NW_DST,
+ nl_msg_put_be32(ctx->odp_actions, ODP_ACTION_ATTR_SET_NW_DST,
ia->nw_addr.nw_addr);
ctx->flow.nw_dst = ia->nw_addr.nw_addr;
break;
case OFPAT_SET_NW_TOS:
- nl_msg_put_u8(ctx->odp_actions, ODPAT_SET_NW_TOS,
+ nl_msg_put_u8(ctx->odp_actions, ODP_ACTION_ATTR_SET_NW_TOS,
ia->nw_tos.nw_tos);
ctx->flow.nw_tos = ia->nw_tos.nw_tos;
break;
case OFPAT_SET_TP_SRC:
- nl_msg_put_be16(ctx->odp_actions, ODPAT_SET_TP_SRC,
+ nl_msg_put_be16(ctx->odp_actions, ODP_ACTION_ATTR_SET_TP_SRC,
ia->tp_port.tp_port);
ctx->flow.tp_src = ia->tp_port.tp_port;
break;
case OFPAT_SET_TP_DST:
- nl_msg_put_be16(ctx->odp_actions, ODPAT_SET_TP_DST,
+ nl_msg_put_be16(ctx->odp_actions, ODP_ACTION_ATTR_SET_TP_DST,
ia->tp_port.tp_port);
ctx->flow.tp_dst = ia->tp_port.tp_port;
break;
* to a rule. */
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
LIST_FOR_EACH (facet, list_node, &rule->facets) {
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
ofpbuf_clear(&key);
odp_flow_key_from_flow(&key, &facet->flow);
- dpif_flow_get(p->dpif, 0, key.data, key.size, NULL, &stats);
+ dpif_flow_get(p->dpif, key.data, key.size, NULL, &stats);
packet_count += stats.n_packets + facet->packet_count;
byte_count += stats.n_bytes + facet->byte_count;
return 0;
}
-static long long int
-msec_from_nsec(uint64_t sec, uint32_t nsec)
-{
- return !sec ? 0 : sec * 1000 + nsec / 1000000;
-}
-
static void
facet_update_time(struct ofproto *ofproto, struct facet *facet,
- const struct odp_flow_stats *stats)
+ const struct dpif_flow_stats *stats)
{
- long long int used = msec_from_nsec(stats->used_sec, stats->used_nsec);
+ long long int used = stats->used;
if (used > facet->used) {
facet->used = used;
if (used > facet->rule->used) {
* cleared out of the datapath. */
static void
facet_update_stats(struct ofproto *ofproto, struct facet *facet,
- const struct odp_flow_stats *stats)
+ const struct dpif_flow_stats *stats)
{
if (stats->n_packets) {
facet_update_time(ofproto, facet, stats);
struct ofpbuf odp_actions;
ofpbuf_init(&odp_actions, 32);
- nl_msg_put_u32(&odp_actions, ODPAT_OUTPUT, ODPP_LOCAL);
+ nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, ODPP_LOCAL);
dpif_execute(p->dpif, odp_actions.data, odp_actions.size,
upcall->packet);
ofpbuf_uninit(&odp_actions);
struct flow flow;
switch (upcall->type) {
- case _ODPL_ACTION_NR:
+ case DPIF_UC_ACTION:
COVERAGE_INC(ofproto_ctlr_action);
odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
send_packet_in(p, upcall, &flow, false);
break;
- case _ODPL_SFLOW_NR:
+ case DPIF_UC_SAMPLE:
if (p->sflow) {
odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
ofproto_sflow_received(p->sflow, upcall, &flow);
ofpbuf_delete(upcall->packet);
break;
- case _ODPL_MISS_NR:
+ case DPIF_UC_MISS:
handle_miss_upcall(p, upcall);
break;
+ case DPIF_N_UC_TYPES:
default:
VLOG_WARN_RL(&rl, "upcall has unexpected type %"PRIu32, upcall->type);
break;
static void
ofproto_update_used(struct ofproto *p)
{
- const struct odp_flow_stats *stats;
+ const struct dpif_flow_stats *stats;
struct dpif_flow_dump dump;
const struct nlattr *key;
size_t key_len;
netflow_active_timeout_expired(ofproto->netflow, &facet->nf_flow)) {
struct ofexpired expired;
+ if (facet->installed) {
+ struct dpif_flow_stats stats;
+
+ facet_put__(ofproto, facet, facet->actions, facet->actions_len,
+ &stats);
+ facet_update_stats(ofproto, facet, &stats);
+ }
+
expired.flow = facet->flow;
expired.packet_count = facet->packet_count;
expired.byte_count = facet->byte_count;
expired.used = facet->used;
-
- /* Get updated flow stats.
- *
- * XXX We could avoid this call entirely if (1) ofproto_update_used()
- * updated TCP flags and (2) the dpif_flow_list_all() in
- * ofproto_update_used() zeroed TCP flags. */
- if (facet->installed) {
- uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow_stats stats;
- struct ofpbuf key;
-
- ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, &facet->flow);
-
- if (!dpif_flow_get(ofproto->dpif, ODPFF_ZERO_TCP_FLAGS,
- key.data, key.size, NULL, &stats)) {
- expired.packet_count += stats.n_packets;
- expired.byte_count += stats.n_bytes;
- if (stats.n_packets) {
- facet_update_time(ofproto, facet, &stats);
- netflow_flow_update_flags(&facet->nf_flow,
- stats.tcp_flags);
- }
- }
- }
-
netflow_expire(ofproto->netflow, &facet->nf_flow, &expired);
}
}
int total_len, send_len;
struct ofpbuf *packet;
uint32_t buffer_id;
+ int idx;
/* Get OpenFlow buffer_id. */
- if (upcall->type == _ODPL_ACTION_NR) {
+ if (upcall->type == DPIF_UC_ACTION) {
buffer_id = UINT32_MAX;
} else if (ofproto->fail_open && fail_open_is_active(ofproto->fail_open)) {
buffer_id = pktbuf_get_null();
if (buffer_id != UINT32_MAX) {
send_len = MIN(send_len, ofconn->miss_send_len);
}
- if (upcall->type == _ODPL_ACTION_NR) {
+ if (upcall->type == DPIF_UC_ACTION) {
send_len = MIN(send_len, upcall->userdata);
}
opi->header.type = OFPT_PACKET_IN;
opi->total_len = htons(total_len);
opi->in_port = htons(odp_port_to_ofp_port(flow->in_port));
- opi->reason = upcall->type == _ODPL_MISS_NR ? OFPR_NO_MATCH : OFPR_ACTION;
+ opi->reason = upcall->type == DPIF_UC_MISS ? OFPR_NO_MATCH : OFPR_ACTION;
opi->buffer_id = htonl(buffer_id);
update_openflow_length(packet);
/* Hand over to packet scheduler. It might immediately call into
* do_send_packet_in() or it might buffer it for a while (until a later
* call to pinsched_run()). */
- pinsched_send(ofconn->schedulers[opi->reason], flow->in_port,
+ idx = upcall->type == DPIF_UC_MISS ? 0 : 1;
+ pinsched_send(ofconn->schedulers[idx], flow->in_port,
packet, do_send_packet_in, ofconn);
}
-/* Given 'upcall', of type _ODPL_ACTION_NR or _ODPL_MISS_NR, sends an
+/* Given 'upcall', of type DPIF_UC_ACTION or DPIF_UC_MISS, sends an
* OFPT_PACKET_IN message to each OpenFlow controller as necessary according to
* their individual configurations.
*
flood_packets(ofproto, flow->in_port, OFPPC_NO_FLOOD,
nf_output_iface, odp_actions);
} else if (out_port != flow->in_port) {
- nl_msg_put_u32(odp_actions, ODPAT_OUTPUT, out_port);
+ nl_msg_put_u32(odp_actions, ODP_ACTION_ATTR_OUTPUT, out_port);
*nf_output_iface = out_port;
} else {
/* Drop. */