+
+ for (i = 0; i < dpif->uc_array_size; i++ ) {
+ struct dpif_linux_vport vport_request;
+ struct dpif_channel *ch = &dpif->channels[i];
+ uint32_t upcall_pid = 0;
+
+ if (!ch->sock) {
+ continue;
+ }
+
+ /* Turn off upcalls. */
+ dpif_linux_vport_init(&vport_request);
+ vport_request.cmd = OVS_VPORT_CMD_SET;
+ vport_request.dp_ifindex = dpif->dp_ifindex;
+ vport_request.port_no = u32_to_odp(i);
+ vport_request.upcall_pid = &upcall_pid;
+ dpif_linux_vport_transact(&vport_request, NULL, NULL);
+
+ nl_sock_destroy(ch->sock);
+ }
+
+ 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;
+
+ close(dpif->epoll_fd);
+ dpif->epoll_fd = -1;
+}
+
+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;