+ }
+
+ txnsp = xmalloc(n_ops * sizeof *txnsp);
+ for (i = 0; i < n_ops; i++) {
+ txnsp[i] = &txns[i];
+ }
+
+ nl_sock_transact_multiple(genl_sock, txnsp, n_ops);
+
+ free(txnsp);
+
+ for (i = 0; i < n_ops; i++) {
+ struct nl_transaction *txn = &txns[i];
+ union dpif_op *op = ops[i];
+
+ if (op->type == DPIF_OP_FLOW_PUT) {
+ struct dpif_flow_put *put = &op->flow_put;
+ int error = txn->error;
+
+ if (!error && put->stats) {
+ struct dpif_linux_flow reply;
+
+ error = dpif_linux_flow_from_ofpbuf(&reply, txn->reply);
+ if (!error) {
+ dpif_linux_flow_get_stats(&reply, put->stats);
+ }
+ }
+ put->error = error;
+ } else if (op->type == DPIF_OP_EXECUTE) {
+ struct dpif_execute *execute = &op->execute;
+
+ execute->error = txn->error;
+ } else {
+ NOT_REACHED();
+ }
+
+ ofpbuf_delete(txn->request);
+ ofpbuf_delete(txn->reply);
+ }
+ free(txns);
+}
+
+static int
+dpif_linux_recv_get_mask(const struct dpif *dpif_, int *listen_mask)
+{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
+ *listen_mask = dpif->listen_mask;
+ return 0;
+}
+
+static void
+set_upcall_pids(struct dpif *dpif_)
+{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
+ struct dpif_port_dump port_dump;
+ struct dpif_port port;
+ int error;
+
+ DPIF_PORT_FOR_EACH (&port, &port_dump, &dpif->dpif) {
+ uint32_t upcall_pid = dpif_linux_port_get_pid__(dpif_, port.port_no,
+ DPIF_UC_MISS);
+ struct dpif_linux_vport vport_request;
+
+ 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), strerror(error));
+ }
+ }
+}
+
+static int
+dpif_linux_recv_set_mask(struct dpif *dpif_, int listen_mask)
+{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
+
+ if (listen_mask == dpif->listen_mask) {
+ return 0;
+ }
+
+ if (!listen_mask) {
+ destroy_upcall_socks(dpif);
+ } else if (!dpif->listen_mask) {
+ int i;
+ int error;
+
+ for (i = 0; i < N_UPCALL_SOCKS; i++) {
+ error = nl_sock_create(NETLINK_GENERIC, &dpif->upcall_socks[i]);
+ if (error) {
+ destroy_upcall_socks(dpif);
+ return error;
+ }
+ }
+ }
+
+ dpif->listen_mask = listen_mask;
+ set_upcall_pids(dpif_);
+
+ return 0;
+}
+
+static int
+dpif_linux_queue_to_priority(const struct dpif *dpif OVS_UNUSED,
+ uint32_t queue_id, uint32_t *priority)
+{
+ if (queue_id < 0xf000) {
+ *priority = TC_H_MAKE(1 << 16, queue_id + 1);
+ return 0;