+
+ if (!enable) {
+ destroy_channels(dpif);
+ } else {
+ struct dpif_port_dump port_dump;
+ struct dpif_port port;
+
+ if (dpif->epoll_fd < 0) {
+ dpif->epoll_fd = epoll_create(10);
+ if (dpif->epoll_fd < 0) {
+ return errno;
+ }
+ }
+
+ DPIF_PORT_FOR_EACH (&port, &port_dump, &dpif->dpif) {
+ struct dpif_linux_vport vport_request;
+ struct nl_sock *sock;
+ uint32_t upcall_pid;
+ int error;
+
+ error = nl_sock_create(NETLINK_GENERIC, &sock);
+ if (error) {
+ return error;
+ }
+
+ upcall_pid = nl_sock_pid(sock);
+
+ dpif_linux_vport_init(&vport_request);
+ vport_request.cmd = OVS_VPORT_CMD_SET;
+ vport_request.dp_ifindex = dpif->dp_ifindex;
+ vport_request.port_no = port.port_no;
+ vport_request.upcall_pid = &upcall_pid;
+ error = dpif_linux_vport_transact(&vport_request, NULL, NULL);
+ if (!error) {
+ VLOG_DBG("%s: assigning port %"PRIu32" to netlink pid %"PRIu32,
+ dpif_name(&dpif->dpif), vport_request.port_no,
+ upcall_pid);
+ } else {
+ VLOG_WARN_RL(&error_rl,
+ "%s: failed to set upcall pid on port: %s",
+ dpif_name(&dpif->dpif), ovs_strerror(error));
+ nl_sock_destroy(sock);
+
+ if (error == ENODEV || error == ENOENT) {
+ /* This device isn't there, but keep trying the others. */
+ continue;
+ } else {
+ return error;
+ }
+ }
+
+ error = add_channel(dpif, port.port_no, sock);
+ if (error) {
+ VLOG_INFO("%s: could not add channel for port %s",
+ dpif_name(dpif_), port.name);
+ nl_sock_destroy(sock);
+ return error;
+ }
+ }
+ }
+
+ return 0;