VLOG_DEFINE_THIS_MODULE(dpif_linux);
enum { MAX_PORTS = USHRT_MAX };
-enum { N_UPCALL_SOCKS = 16 };
-BUILD_ASSERT_DECL(IS_POW2(N_UPCALL_SOCKS));
+enum { N_UPCALL_SOCKS = 17 };
+BUILD_ASSERT_DECL(IS_POW2(N_UPCALL_SOCKS - 1));
+BUILD_ASSERT_DECL(N_UPCALL_SOCKS > 1);
BUILD_ASSERT_DECL(N_UPCALL_SOCKS <= 32); /* We use a 32-bit word as a mask. */
/* This ethtool flag was introduced in Linux 2.6.24, so it might be
if (dpif->epoll_fd < 0) {
return 0;
} else {
- int idx = port_no & (N_UPCALL_SOCKS - 1);
+ int idx;
+
+ idx = (port_no != UINT16_MAX
+ ? 1 + (port_no & (N_UPCALL_SOCKS - 2))
+ : 0);
return nl_sock_pid(dpif->upcall_socks[idx]);
}
}
* actions as the OVS_USERSPACE_ATTR_PID attribute's value, for use in
* flows whose packets arrived on port 'port_no'.
*
+ * A 'port_no' of UINT16_MAX should be treated as a special case. The
+ * implementation should return a reserved PID, not allocated to any port,
+ * that the client may use for special purposes.
+ *
* The return value only needs to be meaningful when DPIF_UC_ACTION has
* been enabled in the 'dpif''s listen mask, and it is allowed to change
* when DPIF_UC_ACTION is disabled and then re-enabled.
* as the OVS_USERSPACE_ATTR_PID attribute's value, for use in flows whose
* packets arrived on port 'port_no'.
*
+ * A 'port_no' of UINT16_MAX is a special case: it returns a reserved PID, not
+ * allocated to any port, that the client may use for special purposes.
+ *
* The return value is only meaningful when DPIF_UC_ACTION has been enabled in
* the 'dpif''s listen mask. It is allowed to change when DPIF_UC_ACTION is
* disabled and then re-enabled, so a client that does that must be prepared to
static void
expire_subfacets(struct ofproto_dpif *ofproto, int dp_max_idle)
{
- long long int cutoff = time_msec() - dp_max_idle;
+ /* Cutoff time for most flows. */
+ long long int normal_cutoff = time_msec() - dp_max_idle;
+
+ /* We really want to keep flows for special protocols around, so use a more
+ * conservative cutoff. */
+ long long int special_cutoff = time_msec() - 10000;
struct subfacet *subfacet, *next_subfacet;
struct subfacet *batch[EXPIRE_MAX_BATCH];
n_batch = 0;
HMAP_FOR_EACH_SAFE (subfacet, next_subfacet, hmap_node,
&ofproto->subfacets) {
+ long long int cutoff;
+
+ cutoff = (subfacet->slow & (SLOW_CFM | SLOW_LACP | SLOW_STP)
+ ? special_cutoff
+ : normal_cutoff);
if (subfacet->used < cutoff) {
if (subfacet->path != SF_NOT_INSTALLED) {
batch[n_batch++] = subfacet;
cookie.slow_path.reason = slow;
ofpbuf_use_stack(&buf, stub, stub_size);
- put_userspace_action(ofproto, &buf, flow, &cookie);
+ if (slow & (SLOW_CFM | SLOW_LACP | SLOW_STP)) {
+ uint32_t pid = dpif_port_get_pid(ofproto->dpif, UINT16_MAX);
+ odp_put_userspace_action(pid, &cookie, &buf);
+ } else {
+ put_userspace_action(ofproto, &buf, flow, &cookie);
+ }
*actionsp = buf.data;
*actions_lenp = buf.size;
}