+#ifdef _WIN32
+static void
+vport_delete_sock_pool(struct dpif_handler *handler)
+ OVS_REQ_WRLOCK(dpif->upcall_lock)
+{
+ if (handler->vport_sock_pool) {
+ uint32_t i;
+ struct dpif_windows_vport_sock *sock_pool =
+ handler->vport_sock_pool;
+
+ for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
+ if (sock_pool[i].nl_sock) {
+ nl_sock_unsubscribe_packets(sock_pool[i].nl_sock);
+ nl_sock_destroy(sock_pool[i].nl_sock);
+ sock_pool[i].nl_sock = NULL;
+ }
+ }
+
+ free(handler->vport_sock_pool);
+ handler->vport_sock_pool = NULL;
+ }
+}
+
+static int
+vport_create_sock_pool(struct dpif_handler *handler)
+ OVS_REQ_WRLOCK(dpif->upcall_lock)
+{
+ struct dpif_windows_vport_sock *sock_pool;
+ size_t i;
+ int error = 0;
+
+ sock_pool = xzalloc(VPORT_SOCK_POOL_SIZE * sizeof *sock_pool);
+ for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
+ error = nl_sock_create(NETLINK_GENERIC, &sock_pool[i].nl_sock);
+ if (error) {
+ goto error;
+ }
+
+ /* Enable the netlink socket to receive packets. This is equivalent to
+ * calling nl_sock_join_mcgroup() to receive events. */
+ error = nl_sock_subscribe_packets(sock_pool[i].nl_sock);
+ if (error) {
+ goto error;
+ }
+ }
+
+ handler->vport_sock_pool = sock_pool;
+ handler->last_used_pool_idx = 0;
+ return 0;
+
+error:
+ vport_delete_sock_pool(handler);
+ return error;
+}
+
+/* Returns an array pointers to netlink sockets. The sockets are picked from a
+ * pool. Records the error in 'error'. */
+static struct nl_sock **
+vport_create_socksp_windows(struct dpif_netlink *dpif, int *error)
+ OVS_REQ_WRLOCK(dpif->upcall_lock)
+{
+ uint32_t n_socks = dpif->n_handlers;
+ struct nl_sock **socksp;
+ size_t i;
+
+ ovs_assert(n_socks <= 1);
+ socksp = xzalloc(n_socks * sizeof *socksp);
+
+ /* Pick netlink sockets to use in a round-robin fashion from each
+ * handler's pool of sockets. */
+ for (i = 0; i < n_socks; i++) {
+ struct dpif_handler *handler = &dpif->handlers[i];
+ struct dpif_windows_vport_sock *sock_pool = handler->vport_sock_pool;
+ size_t index = handler->last_used_pool_idx;
+
+ /* A pool of sockets is allocated when the handler is initialized. */
+ if (sock_pool == NULL) {
+ free(socksp);
+ *error = EINVAL;
+ return NULL;
+ }
+
+ ovs_assert(index < VPORT_SOCK_POOL_SIZE);
+ socksp[i] = sock_pool[index].nl_sock;
+ socksp[i] = sock_pool[index].nl_sock;
+ ovs_assert(socksp[i]);
+ index = (index == VPORT_SOCK_POOL_SIZE - 1) ? 0 : index + 1;
+ handler->last_used_pool_idx = index;
+ }
+
+ return socksp;
+}
+
+static void
+vport_del_socksp_windows(struct dpif_netlink *dpif, struct nl_sock **socksp)
+{
+ free(socksp);
+}
+#endif /* _WIN32 */
+
+static struct nl_sock **
+vport_create_socksp(struct dpif_netlink *dpif, int *error)
+{
+#ifdef _WIN32
+ return vport_create_socksp_windows(dpif, error);
+#else
+ return vport_create_socksp__(dpif->n_handlers, error);
+#endif
+}
+
+static void
+vport_del_socksp(struct dpif_netlink *dpif, struct nl_sock **socksp)
+{
+#ifdef _WIN32
+ vport_del_socksp_windows(dpif, socksp);
+#else
+ vport_del_socksp__(socksp, dpif->n_handlers);
+#endif
+}
+