#include <config.h>
#include "dpif.h"
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
static int openflow_family;
static int lookup_openflow_multicast_group(int dp_idx, int *multicast_group);
-static int send_mgmt_command(struct dpif *, int command,
+static int send_mgmt_command(struct dpif *, int dp_idx, int command,
const char *netdev);
-/* Opens the local datapath numbered 'dp_idx', initializing 'dp'. If
- * 'subscribe' is true, listens for asynchronous messages (packet-in, etc.)
- * from the datapath; otherwise, 'dp' will receive only replies to explicitly
- * initiated requests. */
+/* Opens a socket for a local datapath, initializing 'dp'. If
+ * 'subscribe_dp_idx' is nonnegative, listens for asynchronous messages
+ * (packet-in, etc.) from the datapath with that number; otherwise, 'dp' will
+ * receive only replies to explicitly initiated requests. */
int
-dpif_open(int dp_idx, bool subscribe, struct dpif *dp)
+dpif_open(int subscribe_dp_idx, struct dpif *dp)
{
struct nl_sock *sock;
int multicast_group = 0;
return retval;
}
- if (subscribe) {
- retval = lookup_openflow_multicast_group(dp_idx, &multicast_group);
+ if (subscribe_dp_idx >= 0) {
+ retval = lookup_openflow_multicast_group(subscribe_dp_idx,
+ &multicast_group);
if (retval) {
return retval;
}
return retval;
}
- dp->dp_idx = dp_idx;
dp->sock = sock;
return 0;
}
* If 'wait' is true, dpif_recv_openflow waits for a message to be ready;
* otherwise, returns EAGAIN if the 'sock' receive buffer is empty. */
int
-dpif_recv_openflow(struct dpif *dp, struct ofpbuf **bufferp,
- bool wait)
+dpif_recv_openflow(struct dpif *dp, struct ofpbuf **bufferp, bool wait)
{
struct nlattr *attrs[ARRAY_SIZE(openflow_policy)];
struct ofpbuf *buffer;
ARRAY_SIZE(openflow_policy))) {
goto error;
}
- if (nl_attr_get_u32(attrs[DP_GENL_A_DP_IDX]) != dp->dp_idx) {
- VLOG_WARN_RL(&rl, "received dp_idx (%"PRIu32") differs from expected "
- "(%d)", nl_attr_get_u32(attrs[DP_GENL_A_DP_IDX]),
- dp->dp_idx);
- goto error;
- }
oh = buffer->data = (void *) nl_attr_get(attrs[DP_GENL_A_OPENFLOW]);
buffer->size = nl_attr_get_size(attrs[DP_GENL_A_OPENFLOW]);
}
/* Encapsulates 'msg', which must contain an OpenFlow message, in a Netlink
- * message, and sends it to the OpenFlow kernel module via 'sock'.
+ * message, and sends it to the OpenFlow local datapath numbered 'dp_idx' via
+ * 'sock'.
*
* Returns 0 if successful, otherwise a positive errno value. If
* 'wait' is true, then the send will wait until buffer space is ready;
* for details).
*/
int
-dpif_send_openflow(struct dpif *dp, struct ofpbuf *buffer, bool wait)
+dpif_send_openflow(struct dpif *dp, int dp_idx, struct ofpbuf *buffer,
+ bool wait)
{
struct ofp_header *oh;
unsigned int dump_flag;
ofpbuf_use(&hdr, fixed_buffer, sizeof fixed_buffer);
nl_msg_put_genlmsghdr(&hdr, dp->sock, 32, openflow_family,
NLM_F_REQUEST | dump_flag, DP_GENL_C_OPENFLOW, 1);
- nl_msg_put_u32(&hdr, DP_GENL_A_DP_IDX, dp->dp_idx);
+ nl_msg_put_u32(&hdr, DP_GENL_A_DP_IDX, dp_idx);
nla = ofpbuf_put_uninit(&hdr, sizeof *nla);
nla->nla_len = sizeof *nla + buffer->size;
nla->nla_type = DP_GENL_A_OPENFLOW;
return retval;
}
-/* Creates the datapath represented by 'dp'. Returns 0 if successful,
+/* Creates local datapath numbered 'dp_idx'. Returns 0 if successful,
* otherwise a positive errno value. */
int
-dpif_add_dp(struct dpif *dp)
+dpif_add_dp(struct dpif *dp, int dp_idx)
{
- return send_mgmt_command(dp, DP_GENL_C_ADD_DP, NULL);
+ return send_mgmt_command(dp, dp_idx, DP_GENL_C_ADD_DP, NULL);
}
-/* Destroys the datapath represented by 'dp'. Returns 0 if successful,
+/* Destroys local datapath numbered 'dp_idx'. Returns 0 if successful,
* otherwise a positive errno value. */
int
-dpif_del_dp(struct dpif *dp)
+dpif_del_dp(struct dpif *dp, int dp_idx)
{
- return send_mgmt_command(dp, DP_GENL_C_DEL_DP, NULL);
+ return send_mgmt_command(dp, dp_idx, DP_GENL_C_DEL_DP, NULL);
}
-/* Adds the Ethernet device named 'netdev' to this datapath. Returns 0 if
- * successful, otherwise a positive errno value. */
+/* Adds the Ethernet device named 'netdev' to the local datapath numbered
+ * 'dp_idx'. Returns 0 if successful, otherwise a positive errno value. */
int
-dpif_add_port(struct dpif *dp, const char *netdev)
+dpif_add_port(struct dpif *dp, int dp_idx, const char *netdev)
{
- return send_mgmt_command(dp, DP_GENL_C_ADD_PORT, netdev);
+ return send_mgmt_command(dp, dp_idx, DP_GENL_C_ADD_PORT, netdev);
}
-/* Removes the Ethernet device named 'netdev' from this datapath. Returns 0
- * if successful, otherwise a positive errno value. */
+/* Removes the Ethernet device named 'netdev' from the local datapath numbered
+ * 'dp_idx'. Returns 0 if successful, otherwise a positive errno value. */
int
-dpif_del_port(struct dpif *dp, const char *netdev)
+dpif_del_port(struct dpif *dp, int dp_idx, const char *netdev)
{
- return send_mgmt_command(dp, DP_GENL_C_DEL_PORT, netdev);
+ return send_mgmt_command(dp, dp_idx, DP_GENL_C_DEL_PORT, netdev);
}
\f
static const struct nl_policy openflow_multicast_policy[] = {
return 0;
}
-/* Sends the given 'command' to datapath 'dp'. If 'netdev' is nonnull, adds it
- * to the command as the port name attribute. Returns 0 if successful,
- * otherwise a positive errno value. */
+/* Sends the given 'command' to datapath 'dp', related to the local datapath
+ * numbered 'dp_idx'. If 'netdev' is nonnull, adds it to the command as the
+ * port name attribute. Returns 0 if successful, otherwise a positive errno
+ * value. */
static int
-send_mgmt_command(struct dpif *dp, int command, const char *netdev)
+send_mgmt_command(struct dpif *dp, int dp_idx,
+ int command, const char *netdev)
{
struct ofpbuf request, *reply;
int retval;
ofpbuf_init(&request, 0);
nl_msg_put_genlmsghdr(&request, dp->sock, 32, openflow_family,
NLM_F_REQUEST | NLM_F_ACK, command, 1);
- nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp->dp_idx);
+ nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp_idx);
if (netdev) {
nl_msg_put_string(&request, DP_GENL_A_PORTNAME, netdev);
}
return retval;
}
-static void open_nl_vconn(const char *name, bool subscribe, struct dpif *dpif)
+static int
+get_dp_idx(const char *name)
{
if (strncmp(name, "nl:", 3)
|| strlen(name) < 4
|| name[strspn(name + 3, "0123456789") + 3]) {
ofp_fatal(0, "%s: argument is not of the form \"nl:DP_ID\"", name);
}
- run(dpif_open(atoi(name + 3), subscribe, dpif), "opening datapath");
+ return atoi(name + 3);
}
-static void do_add_dp(const struct settings *s, int argc UNUSED, char *argv[])
+static void
+do_add_dp(const struct settings *s, int argc UNUSED, char *argv[])
{
- struct dpif dp;
- open_nl_vconn(argv[1], false, &dp);
- run(dpif_add_dp(&dp), "add_dp");
- dpif_close(&dp);
+ struct dpif dpif;
+ run(dpif_open(-1, &dpif), "opening management socket");
+ run(dpif_add_dp(&dpif, get_dp_idx(argv[1])), "add_dp");
+ dpif_close(&dpif);
}
-static void do_del_dp(const struct settings *s, int argc UNUSED, char *argv[])
+static void
+do_del_dp(const struct settings *s, int argc UNUSED, char *argv[])
{
- struct dpif dp;
- open_nl_vconn(argv[1], false, &dp);
- run(dpif_del_dp(&dp), "del_dp");
- dpif_close(&dp);
+ struct dpif dpif;
+ run(dpif_open(-1, &dpif), "opening management socket");
+ run(dpif_del_dp(&dpif, get_dp_idx(argv[1])), "del_dp");
+ dpif_close(&dpif);
}
static void add_del_ports(int argc UNUSED, char *argv[],
- int (*function)(struct dpif *, const char *netdev),
+ int (*function)(struct dpif *, int dp_idx,
+ const char *netdev),
const char *operation, const char *preposition)
{
- struct dpif dp;
bool failure = false;
+ struct dpif dpif;
+ int dp_idx;
int i;
- open_nl_vconn(argv[1], false, &dp);
+ run(dpif_open(-1, &dpif), "opening management socket");
+ dp_idx = get_dp_idx(argv[1]);
for (i = 2; i < argc; i++) {
- int retval = function(&dp, argv[i]);
+ int retval = function(&dpif, dp_idx, argv[i]);
if (retval) {
ofp_error(retval, "failed to %s %s %s %s",
operation, argv[i], preposition, argv[1]);
failure = true;
}
}
- dpif_close(&dp);
+ dpif_close(&dpif);
if (failure) {
exit(EXIT_FAILURE);
}
}
-static int ifup_and_add_port(struct dpif *dpif, const char *netdev)
+static int ifup_and_add_port(struct dpif *dpif, int dp_idx, const char *netdev)
{
int retval = if_up(netdev);
- return retval ? retval : dpif_add_port(dpif, netdev);
+ return retval ? retval : dpif_add_port(dpif, dp_idx, netdev);
}
static void do_add_port(const struct settings *s, int argc UNUSED,