/* Attributes. */
const char *name; /* OVS_DP_ATTR_NAME. */
const uint32_t *upcall_pid; /* OVS_DP_ATTR_UPCALL_PID. */
+ uint32_t user_features; /* OVS_DP_ATTR_USER_FEATURES */
struct ovs_dp_stats stats; /* OVS_DP_ATTR_STATS. */
struct ovs_dp_megaflow_stats megaflow_stats;
/* OVS_DP_ATTR_MEGAFLOW_STATS.*/
/* Change notification. */
struct nl_sock *port_notifier; /* vport multicast group subscriber. */
+ bool refresh_channels;
};
static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5);
static int open_dpif(const struct dpif_linux_dp *, struct dpif **);
static uint32_t dpif_linux_port_get_pid(const struct dpif *,
odp_port_t port_no);
+static int dpif_linux_refresh_channels(struct dpif *);
static void dpif_linux_vport_to_ofpbuf(const struct dpif_linux_vport *,
struct ofpbuf *);
upcall_pid = 0;
dp_request.upcall_pid = &upcall_pid;
} else {
- dp_request.cmd = OVS_DP_CMD_GET;
+ /* Use OVS_DP_CMD_SET to report user features */
+ dp_request.cmd = OVS_DP_CMD_SET;
}
dp_request.name = name;
+ dp_request.user_features |= OVS_DP_F_UNALIGNED;
error = dpif_linux_dp_transact(&dp_request, &dp, &buf);
if (error) {
return error;
return dpif_linux_dp_transact(&dp, NULL, NULL);
}
+static void
+dpif_linux_run(struct dpif *dpif_)
+{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
+ if (dpif->refresh_channels) {
+ dpif->refresh_channels = false;
+ dpif_linux_refresh_channels(dpif_);
+ }
+}
+
static int
dpif_linux_get_stats(const struct dpif *dpif_, struct dpif_dp_stats *stats)
{
/* The ODPP_NONE "reserved" port number uses the "ovs-system"'s
* channel, since it is not heavily loaded. */
uint32_t idx = port_idx >= dpif->uc_array_size ? 0 : port_idx;
- pid = nl_sock_pid(dpif->channels[idx].sock);
+ const struct nl_sock *sock = dpif->channels[idx].sock;
+ pid = sock ? nl_sock_pid(sock) : 0;
}
ovs_mutex_unlock(&dpif->upcall_lock);
return 0;
}
-static bool
+static int
dpif_linux_port_dump_next__(const struct dpif *dpif_, struct nl_dump *dump,
struct dpif_linux_vport *vport)
{
|| vport.cmd == OVS_VPORT_CMD_SET)) {
VLOG_DBG("port_changed: dpif:%s vport:%s cmd:%"PRIu8,
dpif->dpif.full_name, vport.name, vport.cmd);
+ if (vport.cmd == OVS_VPORT_CMD_DEL) {
+ dpif->refresh_channels = true;
+ }
*devnamep = xstrdup(vport.name);
ofpbuf_uninit(&buf);
return 0;
break;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
break;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
ofpbuf_uninit(&aux->request);
dpif->n_events = dpif->event_offset = 0;
dpif_linux_port_dump_start__(dpif_, &dump);
- while (dpif_linux_port_dump_next__(dpif_, &dump, &vport)) {
+ while (!dpif_linux_port_dump_next__(dpif_, &dump, &vport)) {
uint32_t port_no = odp_to_u32(vport.port_no);
struct nl_sock *sock = (port_no < dpif->uc_array_size
? dpif->channels[port_no].sock
return EINVAL;
}
- memset(upcall, 0, sizeof *upcall);
+ /* (Re)set ALL fields of '*upcall' on successful return. */
upcall->type = type;
- upcall->packet = buf;
- upcall->packet->data = CONST_CAST(struct nlattr *,
- nl_attr_get(a[OVS_PACKET_ATTR_PACKET]));
- upcall->packet->size = nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]);
upcall->key = CONST_CAST(struct nlattr *,
nl_attr_get(a[OVS_PACKET_ATTR_KEY]));
upcall->key_len = nl_attr_get_size(a[OVS_PACKET_ATTR_KEY]);
upcall->userdata = a[OVS_PACKET_ATTR_USERDATA];
+
+ /* Allow overwriting the netlink attribute header without reallocating. */
+ ofpbuf_use_stub(&upcall->packet,
+ CONST_CAST(struct nlattr *,
+ nl_attr_get(a[OVS_PACKET_ATTR_PACKET])) - 1,
+ nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]) +
+ sizeof(struct nlattr));
+ upcall->packet.data = (char *)upcall->packet.data + sizeof(struct nlattr);
+ upcall->packet.size = nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]);
+
*dp_ifindex = ovs_header->dp_ifindex;
return 0;
dpif_linux_open,
dpif_linux_close,
dpif_linux_destroy,
- NULL, /* run */
+ dpif_linux_run,
NULL, /* wait */
dpif_linux_get_stats,
dpif_linux_port_add,
nl_msg_put_u32(buf, OVS_DP_ATTR_UPCALL_PID, *dp->upcall_pid);
}
+ if (dp->user_features) {
+ nl_msg_put_u32(buf, OVS_DP_ATTR_USER_FEATURES, dp->user_features);
+ }
+
/* Skip OVS_DP_ATTR_STATS since we never have a reason to serialize it. */
}