+
+ free(dpif->channels);
+ dpif->channels = NULL;
+ dpif->uc_array_size = 0;
+
+ free(dpif->epoll_events);
+ dpif->epoll_events = NULL;
+ dpif->n_events = dpif->event_offset = 0;
+
+ /* Don't close dpif->epoll_fd since that would cause other threads that
+ * call dpif_recv_wait() to wait on an arbitrary fd or a closed fd. */
+}
+
+static int
+add_channel(struct dpif_linux *dpif, odp_port_t port_no, struct nl_sock *sock)
+{
+ struct epoll_event event;
+ uint32_t port_idx = odp_to_u32(port_no);
+
+ if (dpif->epoll_fd < 0) {
+ return 0;
+ }
+
+ /* We assume that the datapath densely chooses port numbers, which
+ * can therefore be used as an index into an array of channels. */
+ if (port_idx >= dpif->uc_array_size) {
+ uint32_t new_size = port_idx + 1;
+ uint32_t i;
+
+ if (new_size > MAX_PORTS) {
+ VLOG_WARN_RL(&error_rl, "%s: datapath port %"PRIu32" too big",
+ dpif_name(&dpif->dpif), port_no);
+ return EFBIG;
+ }
+
+ dpif->channels = xrealloc(dpif->channels,
+ new_size * sizeof *dpif->channels);
+ for (i = dpif->uc_array_size; i < new_size; i++) {
+ dpif->channels[i].sock = NULL;
+ }
+
+ dpif->epoll_events = xrealloc(dpif->epoll_events,
+ new_size * sizeof *dpif->epoll_events);
+ dpif->uc_array_size = new_size;
+ }
+
+ memset(&event, 0, sizeof event);
+ event.events = EPOLLIN;
+ event.data.u32 = port_idx;
+ if (epoll_ctl(dpif->epoll_fd, EPOLL_CTL_ADD, nl_sock_fd(sock),
+ &event) < 0) {
+ return errno;
+ }
+
+ nl_sock_destroy(dpif->channels[port_idx].sock);
+ dpif->channels[port_idx].sock = sock;
+ dpif->channels[port_idx].last_poll = LLONG_MIN;
+
+ return 0;
+}
+
+static void
+del_channel(struct dpif_linux *dpif, odp_port_t port_no)
+{
+ struct dpif_channel *ch;
+ uint32_t port_idx = odp_to_u32(port_no);
+
+ if (dpif->epoll_fd < 0 || port_idx >= dpif->uc_array_size) {
+ return;
+ }
+
+ ch = &dpif->channels[port_idx];
+ if (!ch->sock) {
+ return;
+ }
+
+ epoll_ctl(dpif->epoll_fd, EPOLL_CTL_DEL, nl_sock_fd(ch->sock), NULL);
+ dpif->event_offset = dpif->n_events = 0;
+
+ nl_sock_destroy(ch->sock);
+ ch->sock = NULL;