/* Attributes.
*
- * The 'stats' and 'used' members point to 64-bit data that might only be
- * aligned on 32-bit boundaries, so get_unaligned_u64() should be used to
- * access their values.
+ * The 'stats' member points to 64-bit data that might only be aligned on
+ * 32-bit boundaries, so get_unaligned_u64() should be used to access its
+ * values.
*
* If 'actions' is nonnull then OVS_FLOW_ATTR_ACTIONS will be included in
* the Netlink version of the command, even if actions_len is zero. */
size_t key_len;
const struct nlattr *actions; /* OVS_FLOW_ATTR_ACTIONS. */
size_t actions_len;
- const uint32_t *upcall_pid; /* OVS_FLOW_ATTR_UPCALL_PID. */
const struct ovs_flow_stats *stats; /* OVS_FLOW_ATTR_STATS. */
const uint8_t *tcp_flags; /* OVS_FLOW_ATTR_TCP_FLAGS. */
- const uint64_t *used; /* OVS_FLOW_ATTR_USED. */
+ const ovs_32aligned_u64 *used; /* OVS_FLOW_ATTR_USED. */
bool clear; /* OVS_FLOW_ATTR_CLEAR. */
};
static void open_dpif(const struct dpif_linux_dp *, struct dpif **);
static bool dpif_linux_nln_parse(struct ofpbuf *, void *);
static void dpif_linux_port_changed(const void *vport, void *dpif);
-static uint32_t get_upcall_pid_port(struct dpif_linux *, uint32_t port);
-static uint32_t get_upcall_pid_flow(struct dpif_linux *,
- const struct nlattr *key, size_t key_len);
+static uint32_t dpif_linux_port_get_pid__(const struct dpif *,
+ uint16_t port_no,
+ enum dpif_upcall_type);
static void dpif_linux_vport_to_ofpbuf(const struct dpif_linux_vport *,
struct ofpbuf *);
uint32_t upcall_pid;
request.port_no = dpif_linux_pop_port(dpif);
- upcall_pid = get_upcall_pid_port(dpif, request.port_no);
+ upcall_pid = dpif_linux_port_get_pid__(dpif_, request.port_no,
+ DPIF_UC_MISS);
request.upcall_pid = &upcall_pid;
error = dpif_linux_vport_transact(&request, &reply, &buf);
return 1024;
}
+static uint32_t
+dpif_linux_port_get_pid__(const struct dpif *dpif_, uint16_t port_no,
+ enum dpif_upcall_type upcall_type)
+{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
+
+ if (!(dpif->listen_mask & (1u << upcall_type))) {
+ return 0;
+ } else {
+ int idx = port_no & (N_UPCALL_SOCKS - 1);
+ return nl_sock_pid(dpif->upcall_socks[idx]);
+ }
+}
+
+static uint32_t
+dpif_linux_port_get_pid(const struct dpif *dpif, uint16_t port_no)
+{
+ return dpif_linux_port_get_pid__(dpif, port_no, DPIF_UC_ACTION);
+}
+
static int
dpif_linux_flow_flush(struct dpif *dpif_)
{
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
struct dpif_linux_flow request, reply;
struct nlattr dummy_action;
- uint32_t upcall_pid;
struct ofpbuf *buf;
int error;
- upcall_pid = get_upcall_pid_flow(dpif, key, key_len);
-
dpif_linux_flow_init(&request);
request.cmd = flags & DPIF_FP_CREATE ? OVS_FLOW_CMD_NEW : OVS_FLOW_CMD_SET;
request.dp_ifindex = dpif->dp_ifindex;
/* Ensure that OVS_FLOW_ATTR_ACTIONS will always be included. */
request.actions = actions ? actions : &dummy_action;
request.actions_len = actions_len;
- request.upcall_pid = &upcall_pid;
if (flags & DPIF_FP_ZERO_STATS) {
request.clear = true;
}
}
static int
-dpif_linux_execute__(int dp_ifindex, uint32_t upcall_pid,
- const struct nlattr *key, size_t key_len,
+dpif_linux_execute__(int dp_ifindex, const struct nlattr *key, size_t key_len,
const struct nlattr *actions, size_t actions_len,
const struct ofpbuf *packet)
{
nl_msg_put_unspec(buf, OVS_PACKET_ATTR_PACKET, packet->data, packet->size);
nl_msg_put_unspec(buf, OVS_PACKET_ATTR_KEY, key, key_len);
nl_msg_put_unspec(buf, OVS_PACKET_ATTR_ACTIONS, actions, actions_len);
- nl_msg_put_u32(buf, OVS_PACKET_ATTR_UPCALL_PID, upcall_pid);
error = nl_sock_transact(genl_sock, buf, NULL);
ofpbuf_delete(buf);
const struct ofpbuf *packet)
{
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
- uint32_t upcall_pid = get_upcall_pid_flow(dpif, key, key_len);
- return dpif_linux_execute__(dpif->dp_ifindex, upcall_pid, key, key_len,
+ return dpif_linux_execute__(dpif->dp_ifindex, key, key_len,
actions, actions_len, packet);
}
return 0;
}
-static uint32_t
-get_upcall_pid_port__(struct dpif_linux *dpif, uint32_t port)
-{
- int idx = port & (N_UPCALL_SOCKS - 1);
- return nl_sock_pid(dpif->upcall_socks[idx]);
-}
-
-static uint32_t
-get_upcall_pid_port(struct dpif_linux *dpif, uint32_t port)
-{
- if (!(dpif->listen_mask & (1u << DPIF_UC_MISS))) {
- return 0;
- }
-
- return get_upcall_pid_port__(dpif, port);
-}
-
-static uint32_t
-get_upcall_pid_flow(struct dpif_linux *dpif,
- const struct nlattr *key, size_t key_len)
-{
- const struct nlattr *nla;
- uint32_t port;
-
- if (!(dpif->listen_mask & (1u << DPIF_UC_ACTION))) {
- return 0;
- }
-
- nla = nl_attr_find__(key, key_len, OVS_KEY_ATTR_IN_PORT);
- if (nla) {
- port = nl_attr_get_u32(nla);
- } else {
- port = random_uint32();
- }
-
- return get_upcall_pid_port__(dpif, port);
-}
-
static void
-set_upcall_pids(struct dpif_linux *dpif)
+set_upcall_pids(struct dpif *dpif_)
{
- struct dpif_port port;
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
struct dpif_port_dump port_dump;
- struct dpif_flow_dump flow_dump;
- const struct nlattr *key;
- size_t key_len;
+ struct dpif_port port;
int error;
DPIF_PORT_FOR_EACH (&port, &port_dump, &dpif->dpif) {
- uint32_t upcall_pid = get_upcall_pid_port(dpif, port.port_no);
+ uint32_t upcall_pid = dpif_linux_port_get_pid__(dpif_, port.port_no,
+ DPIF_UC_MISS);
struct dpif_linux_vport vport_request;
dpif_linux_vport_init(&vport_request);
dpif_name(&dpif->dpif), strerror(error));
}
}
-
- dpif_flow_dump_start(&flow_dump, &dpif->dpif);
- while (dpif_flow_dump_next(&flow_dump, &key, &key_len,
- NULL, NULL, NULL)) {
- uint32_t upcall_pid = get_upcall_pid_flow(dpif, key, key_len);
- struct dpif_linux_flow flow_request;
-
- dpif_linux_flow_init(&flow_request);
- flow_request.cmd = OVS_FLOW_CMD_SET;
- flow_request.dp_ifindex = dpif->dp_ifindex;
- flow_request.key = key;
- flow_request.key_len = key_len;
- flow_request.upcall_pid = &upcall_pid;
- error = dpif_linux_flow_transact(&flow_request, NULL, NULL);
- if (error) {
- VLOG_WARN_RL(&error_rl, "%s: failed to set upcall pid on flow: %s",
- dpif_name(&dpif->dpif), strerror(error));
- }
- }
- dpif_flow_dump_done(&flow_dump);
}
static int
}
dpif->listen_mask = listen_mask;
- set_upcall_pids(dpif);
+ set_upcall_pids(dpif_);
return 0;
}
dpif_linux_port_query_by_number,
dpif_linux_port_query_by_name,
dpif_linux_get_max_ports,
+ dpif_linux_port_get_pid,
dpif_linux_port_dump_start,
dpif_linux_port_dump_next,
dpif_linux_port_dump_done,
ofpbuf_use_stack(&actions, &action, sizeof action);
nl_msg_put_u32(&actions, OVS_ACTION_ATTR_OUTPUT, port_no);
- return dpif_linux_execute__(dp_ifindex, 0, key.data, key.size,
+ return dpif_linux_execute__(dp_ifindex, key.data, key.size,
actions.data, actions.size, &packet);
}
static const struct nl_policy ovs_flow_policy[] = {
[OVS_FLOW_ATTR_KEY] = { .type = NL_A_NESTED },
[OVS_FLOW_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
- [OVS_FLOW_ATTR_UPCALL_PID] = { .type = NL_A_U32 },
[OVS_FLOW_ATTR_STATS] = { .type = NL_A_UNSPEC,
.min_len = sizeof(struct ovs_flow_stats),
.max_len = sizeof(struct ovs_flow_stats),
flow->actions = nl_attr_get(a[OVS_FLOW_ATTR_ACTIONS]);
flow->actions_len = nl_attr_get_size(a[OVS_FLOW_ATTR_ACTIONS]);
}
- if (a[OVS_FLOW_ATTR_UPCALL_PID]) {
- flow->upcall_pid = nl_attr_get(a[OVS_FLOW_ATTR_UPCALL_PID]);
- }
if (a[OVS_FLOW_ATTR_STATS]) {
flow->stats = nl_attr_get(a[OVS_FLOW_ATTR_STATS]);
}
flow->actions, flow->actions_len);
}
- if (flow->upcall_pid) {
- nl_msg_put_u32(buf, OVS_FLOW_ATTR_UPCALL_PID, *flow->upcall_pid);
- }
-
/* We never need to send these to the kernel. */
assert(!flow->stats);
assert(!flow->tcp_flags);
stats->n_packets = 0;
stats->n_bytes = 0;
}
- stats->used = flow->used ? get_unaligned_u64(flow->used) : 0;
+ stats->used = flow->used ? get_32aligned_u64(flow->used) : 0;
stats->tcp_flags = flow->tcp_flags ? *flow->tcp_flags : 0;
}