Initial import
[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 "socket-util.h"
38 #include "util.h"
39 #include "openflow.h"
40
41 #include "vlog.h"
42 #define THIS_MODULE VLM_VCONN_NETLINK
43
44 struct netlink_vconn
45 {
46     struct vconn vconn;
47     struct dpif dp;
48 };
49
50 static struct netlink_vconn *
51 netlink_vconn_cast(struct vconn *vconn) 
52 {
53     assert(vconn->class == &netlink_vconn_class);
54     return CONTAINER_OF(vconn, struct netlink_vconn, vconn); 
55 }
56
57 static int
58 netlink_open(const char *name, char *suffix, struct vconn **vconnp)
59 {
60     struct netlink_vconn *netlink;
61     int dp_idx;
62     int retval;
63
64     if (sscanf(suffix, "%d", &dp_idx) != 1) {
65         fatal(0, "%s: bad peer name format", name);
66     }
67
68     netlink = xmalloc(sizeof *netlink);
69     netlink->vconn.class = &netlink_vconn_class;
70     retval = dpif_open(dp_idx, true, &netlink->dp);
71     if (retval) {
72         free(netlink);
73         *vconnp = NULL;
74         return retval;
75     }
76     *vconnp = &netlink->vconn;
77     return 0;
78 }
79
80 static void
81 netlink_close(struct vconn *vconn) 
82 {
83     struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
84     dpif_close(&netlink->dp);
85     free(netlink);
86 }
87
88 static void
89 netlink_prepoll(struct vconn *vconn, int want, struct pollfd *pfd) 
90 {
91     struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
92     pfd->fd = nl_sock_fd(netlink->dp.sock);
93     if (want & WANT_RECV) {
94         pfd->events |= POLLIN;
95     }
96     if (want & WANT_SEND) {
97         pfd->events |= POLLOUT;
98     }
99 }
100
101 static int
102 netlink_recv(struct vconn *vconn, struct buffer **bufferp)
103 {
104     struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
105     return dpif_recv_openflow(&netlink->dp, bufferp, false);
106 }
107
108 static int
109 netlink_send(struct vconn *vconn, struct buffer *buffer) 
110 {
111     struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
112     int retval = dpif_send_openflow(&netlink->dp, buffer, false);
113     if (!retval) {
114         buffer_delete(buffer);
115     }
116     return retval;
117 }
118
119 struct vconn_class netlink_vconn_class = {
120     .name = "nl",
121     .open = netlink_open,
122     .close = netlink_close,
123     .prepoll = netlink_prepoll,
124     .recv = netlink_recv,
125     .send = netlink_send,
126 };