+ for (i = 0; i < dpif->n_handlers; i++) {
+ struct dpif_handler *handler = &dpif->handlers[i];
+
+ epoll_ctl(handler->epoll_fd, EPOLL_CTL_DEL,
+ nl_sock_fd(handler->channels[port_idx].sock), NULL);
+ nl_sock_destroy(handler->channels[port_idx].sock);
+ handler->channels[port_idx].sock = NULL;
+ handler->event_offset = handler->n_events = 0;
+ }
+}
+
+static void
+destroy_all_channels(struct dpif_linux *dpif) OVS_REQ_WRLOCK(dpif->upcall_lock)
+{
+ unsigned int i;
+
+ if (!dpif->handlers) {
+ return;
+ }
+
+ for (i = 0; i < dpif->uc_array_size; i++ ) {
+ struct dpif_linux_vport vport_request;
+ uint32_t upcall_pids = 0;
+
+ /* Since the sock can only be assigned in either all or none
+ * of "dpif->handlers" channels, the following check would
+ * suffice. */
+ if (!dpif->handlers[0].channels[i].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_pids = &upcall_pids;
+ dpif_linux_vport_transact(&vport_request, NULL, NULL);
+
+ vport_del_channels(dpif, u32_to_odp(i));
+ }
+
+ for (i = 0; i < dpif->n_handlers; i++) {
+ struct dpif_handler *handler = &dpif->handlers[i];
+
+ close(handler->epoll_fd);
+ free(handler->epoll_events);
+ free(handler->channels);
+ }