/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
VLOG_DEFINE_THIS_MODULE(dpif_linux);
enum { MAX_PORTS = USHRT_MAX };
-enum { N_UPCALL_SOCKS = 16 };
-BUILD_ASSERT_DECL(IS_POW2(N_UPCALL_SOCKS));
+enum { N_UPCALL_SOCKS = 17 };
+BUILD_ASSERT_DECL(IS_POW2(N_UPCALL_SOCKS - 1));
+BUILD_ASSERT_DECL(N_UPCALL_SOCKS > 1);
BUILD_ASSERT_DECL(N_UPCALL_SOCKS <= 32); /* We use a 32-bit word as a mask. */
/* This ethtool flag was introduced in Linux 2.6.24, so it might be
if (dpif->epoll_fd < 0) {
return 0;
} else {
- int idx = port_no & (N_UPCALL_SOCKS - 1);
+ int idx;
+
+ idx = (port_no != UINT16_MAX
+ ? 1 + (port_no & (N_UPCALL_SOCKS - 2))
+ : 0);
return nl_sock_pid(dpif->upcall_socks[idx]);
}
}
struct op_auxdata {
struct nl_transaction txn;
+
struct ofpbuf request;
uint64_t request_stub[1024 / 8];
+
+ struct ofpbuf reply;
+ uint64_t reply_stub[1024 / 8];
} auxes[MAX_OPS];
struct nl_transaction *txnsp[MAX_OPS];
aux->request_stub, sizeof aux->request_stub);
aux->txn.request = &aux->request;
+ ofpbuf_use_stub(&aux->reply, aux->reply_stub, sizeof aux->reply_stub);
+ aux->txn.reply = NULL;
+
switch (op->type) {
case DPIF_OP_FLOW_PUT:
put = &op->u.flow_put;
dpif_linux_init_flow_put(dpif_, put, &flow);
if (put->stats) {
flow.nlmsg_flags |= NLM_F_ECHO;
+ aux->txn.reply = &aux->reply;
}
dpif_linux_flow_to_ofpbuf(&flow, &aux->request);
break;
dpif_linux_init_flow_del(dpif_, del, &flow);
if (del->stats) {
flow.nlmsg_flags |= NLM_F_ECHO;
+ aux->txn.reply = &aux->reply;
}
dpif_linux_flow_to_ofpbuf(&flow, &aux->request);
break;
nl_sock_transact_multiple(genl_sock, txnsp, n_ops);
for (i = 0; i < n_ops; i++) {
+ struct op_auxdata *aux = &auxes[i];
struct nl_transaction *txn = &auxes[i].txn;
struct dpif_op *op = ops[i];
struct dpif_flow_put *put;
NOT_REACHED();
}
- ofpbuf_uninit(txn->request);
- ofpbuf_delete(txn->reply);
+ ofpbuf_uninit(&aux->request);
+ ofpbuf_uninit(&aux->reply);
}
}
}
static int
-dpif_linux_recv(struct dpif *dpif_, struct dpif_upcall *upcall)
+dpif_linux_recv(struct dpif *dpif_, struct dpif_upcall *upcall,
+ struct ofpbuf *buf)
{
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
int read_tries = 0;
dpif->ready_mask &= ~(1u << indx);
for (;;) {
- struct ofpbuf *buf;
int dp_ifindex;
int error;
return EAGAIN;
}
- error = nl_sock_recv(upcall_sock, &buf, false);
- if (error == EAGAIN) {
- break;
- } else if (error) {
+ error = nl_sock_recv(upcall_sock, buf, false);
+ if (error) {
+ if (error == EAGAIN) {
+ break;
+ }
return error;
}
if (!error && dp_ifindex == dpif->dp_ifindex) {
return 0;
}
-
- ofpbuf_delete(buf);
if (error) {
return error;
}