Add the ability to connect to a vconn asynchronously.
[sliver-openvswitch.git] / lib / vconn-netlink.c
1 /* Copyright (C) 2007 Board of Trustees, Leland Stanford Jr. University.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21
22 #include "vconn.h"
23 #include <arpa/inet.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <netdb.h>
27 #include <poll.h>
28 #include <netinet/in.h>
29 #include <netinet/tcp.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include "openflow-netlink.h"
34 #include "buffer.h"
35 #include "dpif.h"
36 #include "netlink.h"
37 #include "poll-loop.h"
38 #include "socket-util.h"
39 #include "util.h"
40 #include "openflow.h"
41
42 #include "vlog.h"
43 #define THIS_MODULE VLM_VCONN_NETLINK
44
45 struct netlink_vconn
46 {
47     struct vconn vconn;
48     struct dpif dp;
49 };
50
51 static struct netlink_vconn *
52 netlink_vconn_cast(struct vconn *vconn) 
53 {
54     assert(vconn->class == &netlink_vconn_class);
55     return CONTAINER_OF(vconn, struct netlink_vconn, vconn); 
56 }
57
58 static int
59 netlink_open(const char *name, char *suffix, struct vconn **vconnp)
60 {
61     struct netlink_vconn *netlink;
62     int dp_idx;
63     int retval;
64
65     if (sscanf(suffix, "%d", &dp_idx) != 1) {
66         fatal(0, "%s: bad peer name format", name);
67     }
68
69     netlink = xmalloc(sizeof *netlink);
70     netlink->vconn.class = &netlink_vconn_class;
71     netlink->vconn.connect_status = 0;
72     retval = dpif_open(dp_idx, true, &netlink->dp);
73     if (retval) {
74         free(netlink);
75         *vconnp = NULL;
76         return retval;
77     }
78     *vconnp = &netlink->vconn;
79     return 0;
80 }
81
82 static void
83 netlink_close(struct vconn *vconn) 
84 {
85     struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
86     dpif_close(&netlink->dp);
87     free(netlink);
88 }
89
90 static int
91 netlink_recv(struct vconn *vconn, struct buffer **bufferp)
92 {
93     struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
94     return dpif_recv_openflow(&netlink->dp, bufferp, false);
95 }
96
97 static int
98 netlink_send(struct vconn *vconn, struct buffer *buffer) 
99 {
100     struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
101     int retval = dpif_send_openflow(&netlink->dp, buffer, false);
102     if (!retval) {
103         buffer_delete(buffer);
104     }
105     return retval;
106 }
107
108 static void
109 netlink_wait(struct vconn *vconn, enum vconn_wait_type wait) 
110 {
111     struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
112     short int events = 0;
113     switch (wait) {
114     case WAIT_RECV:
115         events = POLLIN;
116         break;
117
118     case WAIT_SEND:
119         events = 0;
120         break;
121
122     default:
123         NOT_REACHED();
124     }
125     poll_fd_wait(nl_sock_fd(netlink->dp.sock), events, NULL);
126 }
127
128 struct vconn_class netlink_vconn_class = {
129     .name = "nl",
130     .open = netlink_open,
131     .close = netlink_close,
132     .recv = netlink_recv,
133     .send = netlink_send,
134     .wait = netlink_wait,
135 };