get_tables(struct ofproto *ofproto_, struct ofp_table_stats *ots)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- struct ovs_dp_stats s;
+ struct dpif_dp_stats s;
strcpy(ots->name, "classifier");
ofpbuf_uninit(&packet);
}
- enable = enable && !cfm_get_fault(ofport->cfm);
+ enable = enable && !cfm_get_fault(ofport->cfm)
+ && cfm_get_opup(ofport->cfm);
}
if (ofport->bundle) {
struct ofpbuf key;
int error;
- if (actions_len == NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t))
- && odp_actions->nla_type == OVS_ACTION_ATTR_USERSPACE) {
- const struct user_action_cookie *cookie;
+ if (odp_actions->nla_type == OVS_ACTION_ATTR_USERSPACE
+ && NLA_ALIGN(odp_actions->nla_len) == actions_len) {
+ struct user_action_cookie cookie;
struct dpif_upcall upcall;
+ uint64_t cookie_u64;
- cookie = nl_attr_get_unspec(odp_actions, sizeof(*cookie));
- if (cookie->type == USER_ACTION_COOKIE_CONTROLLER) {
+ cookie_u64 = nl_attr_get_u64(nl_attr_find_nested(
+ odp_actions,
+ OVS_USERSPACE_ATTR_USERDATA));
+ memcpy(&cookie, &cookie_u64, sizeof cookie);
+ if (cookie.type == USER_ACTION_COOKIE_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.
complete_operation(rule);
}
\f
-/* Sends 'packet' out of port 'odp_port' within 'p'.
+/* Sends 'packet' out of port 'odp_port' within 'ofproto'.
* Returns 0 if successful, otherwise a positive errno value. */
static int
send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port,
struct action_xlate_ctx *ctx);
static void xlate_normal(struct action_xlate_ctx *);
+static size_t
+put_userspace_action(const struct ofproto_dpif *ofproto,
+ struct ofpbuf *odp_actions,
+ const struct flow *flow,
+ const struct user_action_cookie *cookie)
+{
+ size_t offset;
+ uint32_t pid;
+
+ pid = dpif_port_get_pid(ofproto->dpif,
+ ofp_port_to_odp_port(flow->in_port));
+
+ offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_USERSPACE);
+ nl_msg_put_u32(odp_actions, OVS_USERSPACE_ATTR_PID, pid);
+ nl_msg_put_unspec(odp_actions, OVS_USERSPACE_ATTR_USERDATA,
+ cookie, sizeof *cookie);
+ nl_msg_end_nested(odp_actions, offset);
+
+ return odp_actions->size - NLA_ALIGN(sizeof *cookie);
+}
+
/* Compose SAMPLE action for sFlow. */
static size_t
compose_sflow_action(const struct ofproto_dpif *ofproto,
{
uint32_t port_ifindex;
uint32_t probability;
- struct user_action_cookie *cookie;
+ struct user_action_cookie cookie;
size_t sample_offset, actions_offset;
- int user_cookie_offset, n_output;
+ int cookie_offset, n_output;
if (!ofproto->sflow || flow->in_port == OFPP_NONE) {
return 0;
actions_offset = nl_msg_start_nested(odp_actions, OVS_SAMPLE_ATTR_ACTIONS);
- cookie = nl_msg_put_unspec_uninit(odp_actions, OVS_ACTION_ATTR_USERSPACE,
- sizeof(*cookie));
- cookie->type = USER_ACTION_COOKIE_SFLOW;
- cookie->data = port_ifindex;
- cookie->n_output = n_output;
- cookie->vlan_tci = 0;
- user_cookie_offset = (char *) cookie - (char *) odp_actions->data;
+ cookie.type = USER_ACTION_COOKIE_SFLOW;
+ cookie.data = port_ifindex;
+ cookie.n_output = n_output;
+ cookie.vlan_tci = 0;
+ cookie_offset = put_userspace_action(ofproto, odp_actions, flow, &cookie);
nl_msg_end_nested(odp_actions, actions_offset);
nl_msg_end_nested(odp_actions, sample_offset);
- return user_cookie_offset;
+ return cookie_offset;
}
/* SAMPLE action must be first action in any given list of actions.
}
static void
-compose_controller_action(struct ofpbuf *odp_actions, int len)
+compose_controller_action(struct action_xlate_ctx *ctx, int len)
{
struct user_action_cookie cookie;
cookie.data = len;
cookie.n_output = 0;
cookie.vlan_tci = 0;
-
- nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_USERSPACE,
- &cookie, sizeof(cookie));
+ put_userspace_action(ctx->ofproto, ctx->odp_actions, &ctx->flow, &cookie);
}
static void
break;
case OFPP_CONTROLLER:
commit_odp_actions(ctx);
- compose_controller_action(ctx->odp_actions, max_len);
+ compose_controller_action(ctx, max_len);
break;
case OFPP_LOCAL:
add_output_action(ctx, OFPP_LOCAL);