Initial import
[openvswitch] / lib / dpif.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 "dpif.h"
23
24 #include <ctype.h>
25 #include <errno.h>
26 #include <inttypes.h>
27 #include <netinet/in.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "buffer.h"
32 #include "mac.h"
33 #include "netlink.h"
34 #include "ofp-print.h"
35 #include "openflow-netlink.h"
36 #include "openflow.h"
37 #include "util.h"
38 #include "xtoxll.h"
39
40 #include "vlog.h"
41 #define THIS_MODULE VLM_dpif
42
43 /* The Generic Netlink family number used for OpenFlow. */
44 static int openflow_family;
45
46 static int lookup_openflow_multicast_group(int dp_idx, int *multicast_group);
47 static int send_mgmt_command(struct dpif *, int command,
48                              const char *netdev);
49
50 /* Opens the local datapath numbered 'dp_idx', initializing 'dp'.  If
51  * 'subscribe' is true, listens for asynchronous messages (packet-in, etc.)
52  * from the datapath; otherwise, 'dp' will receive only replies to explicitly
53  * initiated requests. */
54 int
55 dpif_open(int dp_idx, bool subscribe, struct dpif *dp)
56 {
57     struct nl_sock *sock;
58     int multicast_group = 0;
59     int retval;
60
61     retval = nl_lookup_genl_family(DP_GENL_FAMILY_NAME, &openflow_family);
62     if (retval) {
63         return retval;
64     }
65
66     if (subscribe) {
67         retval = lookup_openflow_multicast_group(dp_idx, &multicast_group);
68         if (retval) {
69             return retval;
70         }
71     }
72
73     /* Specify a large so_rcvbuf size because we occasionally need to be able
74      * to retrieve large collections of flow records. */
75     retval = nl_sock_create(NETLINK_GENERIC, multicast_group, 0,
76                             4 * 1024u * 1024, &sock);
77     if (retval) {
78         return retval;
79     }
80
81     dp->dp_idx = dp_idx;
82     dp->sock = sock;
83     return 0;
84 }
85
86 /* Closes 'dp'. */
87 void
88 dpif_close(struct dpif *dp) 
89 {
90     nl_sock_destroy(dp->sock);
91 }
92
93 static const struct nl_policy openflow_policy[] = {
94     [DP_GENL_A_DP_IDX] = { .type = NL_A_U32 },
95     [DP_GENL_A_OPENFLOW] = { .type = NL_A_UNSPEC,
96                               .min_len = sizeof(struct ofp_header),
97                               .max_len = OFP_MAXLEN },
98 };
99
100 /* Tries to receive an openflow message from the kernel on 'sock'.  If
101  * successful, stores the received message into '*msgp' and returns 0.  The
102  * caller is responsible for destroying the message with buffer_delete().  On
103  * failure, returns a positive errno value and stores a null pointer into
104  * '*msgp'.
105  *
106  * Only Netlink messages with embedded OpenFlow messages are accepted.  Other
107  * Netlink messages provoke errors.
108  *
109  * If 'wait' is true, dpif_recv_openflow waits for a message to be ready;
110  * otherwise, returns EAGAIN if the 'sock' receive buffer is empty. */
111 int
112 dpif_recv_openflow(struct dpif *dp, struct buffer **bufferp,
113                         bool wait) 
114 {
115     struct nlattr *attrs[ARRAY_SIZE(openflow_policy)];
116     struct buffer *buffer;
117     struct ofp_header *oh;
118     size_t ofp_len;
119     int retval;
120
121     *bufferp = NULL;
122     do {
123         retval = nl_sock_recv(dp->sock, &buffer, wait);
124     } while (retval == ENOBUFS || (!retval && nl_msg_nlmsgerr(buffer, NULL)));
125     if (retval) {
126         if (retval != EAGAIN) {
127             VLOG_WARN("dpif_recv_openflow: %s", strerror(retval)); 
128         }
129         return retval;
130     }
131
132     if (nl_msg_genlmsghdr(buffer) == NULL) {
133         VLOG_DBG("received packet too short for Generic Netlink");
134         goto error;
135     }
136     if (nl_msg_nlmsghdr(buffer)->nlmsg_type != openflow_family) {
137         VLOG_DBG("received type (%"PRIu16") != openflow family (%d)",
138                  nl_msg_nlmsghdr(buffer)->nlmsg_type, openflow_family);
139         goto error;
140     }
141
142     if (!nl_policy_parse(buffer, openflow_policy, attrs,
143                          ARRAY_SIZE(openflow_policy))) {
144         goto error;
145     }
146     if (nl_attr_get_u32(attrs[DP_GENL_A_DP_IDX]) != dp->dp_idx) {
147         VLOG_WARN("received dp_idx (%"PRIu32") differs from expected (%d)",
148                   nl_attr_get_u32(attrs[DP_GENL_A_DP_IDX]), dp->dp_idx);
149         goto error;
150     }
151
152     oh = buffer->data = (void *) nl_attr_get(attrs[DP_GENL_A_OPENFLOW]);
153     buffer->size = nl_attr_get_size(attrs[DP_GENL_A_OPENFLOW]);
154     ofp_len = ntohs(oh->length);
155     if (ofp_len != buffer->size) {
156         VLOG_WARN("ofp_header.length %"PRIu16" != attribute length %zu\n",
157                   ofp_len, buffer->size);
158         buffer->size = MIN(ofp_len, buffer->size);
159     }
160     *bufferp = buffer;
161     return 0;
162
163 error:
164     buffer_delete(buffer);
165     return EPROTO;
166 }
167
168 /* Encapsulates 'msg', which must contain an OpenFlow message, in a Netlink
169  * message, and sends it to the OpenFlow kernel module via 'sock'.
170  *
171  * Returns 0 if successful, otherwise a positive errno value.  If
172  * 'wait' is true, then the send will wait until buffer space is ready;
173  * otherwise, returns EAGAIN if the 'sock' send buffer is full.
174  *
175  * If the send is successful, then the kernel module will receive it, but there
176  * is no guarantee that any reply will not be dropped (see nl_sock_transact()
177  * for details). 
178  */
179 int
180 dpif_send_openflow(struct dpif *dp, struct buffer *buffer, bool wait) 
181 {
182     struct buffer hdr;
183     struct nlattr *nla;
184     uint32_t fixed_buffer[64 / 4];
185     struct iovec iov[3];
186     int pad_bytes;
187     int n_iov;
188     int retval;
189
190     buffer_use(&hdr, fixed_buffer, sizeof fixed_buffer);
191     nl_msg_put_genlmsghdr(&hdr, dp->sock, 32, openflow_family,
192                           NLM_F_REQUEST, DP_GENL_C_OPENFLOW, 1);
193     nl_msg_put_u32(&hdr, DP_GENL_A_DP_IDX, dp->dp_idx);
194     nla = buffer_put_uninit(&hdr, sizeof nla);
195     nla->nla_len = sizeof nla + buffer->size;
196     nla->nla_type = DP_GENL_A_OPENFLOW;
197     pad_bytes = NLA_ALIGN(nla->nla_len) - nla->nla_len;
198     nl_msg_nlmsghdr(&hdr)->nlmsg_len = hdr.size + buffer->size + pad_bytes;
199     n_iov = 2;
200     iov[0].iov_base = hdr.data;
201     iov[0].iov_len = hdr.size;
202     iov[1].iov_base = buffer->data;
203     iov[1].iov_len = buffer->size;
204     if (pad_bytes) {
205         static char zeros[NLA_ALIGNTO];
206         n_iov++;
207         iov[2].iov_base = zeros;
208         iov[2].iov_len = pad_bytes; 
209     }
210     retval = nl_sock_sendv(dp->sock, iov, n_iov, false);
211     if (retval && retval != EAGAIN) {
212         VLOG_WARN("dpif_send_openflow: %s", strerror(retval));
213     }
214     return retval;
215 }
216
217 /* Creates the datapath represented by 'dp'.  Returns 0 if successful,
218  * otherwise a positive errno value. */
219 int
220 dpif_add_dp(struct dpif *dp)
221 {
222     return send_mgmt_command(dp, DP_GENL_C_ADD_DP, NULL);
223 }
224
225 /* Destroys the datapath represented by 'dp'.  Returns 0 if successful,
226  * otherwise a positive errno value. */
227 int
228 dpif_del_dp(struct dpif *dp) 
229 {
230     return send_mgmt_command(dp, DP_GENL_C_DEL_DP, NULL);
231 }
232
233 /* Adds the Ethernet device named 'netdev' to this datapath.  Returns 0 if
234  * successful, otherwise a positive errno value. */
235 int
236 dpif_add_port(struct dpif *dp, const char *netdev)
237 {
238     return send_mgmt_command(dp, DP_GENL_C_ADD_PORT, netdev);
239 }
240
241 /* Removes the Ethernet device named 'netdev' from this datapath.  Returns 0
242  * if successful, otherwise a positive errno value. */
243 int
244 dpif_del_port(struct dpif *dp, const char *netdev)
245 {
246     return send_mgmt_command(dp, DP_GENL_C_DEL_PORT, netdev);
247 }
248
249 /* Prints a description of 'dp' to stdout.  Returns 0 if successful, otherwise
250  * a positive errno value. */
251 int
252 dpif_show(struct dpif *dp) 
253 {
254     static const struct nl_policy show_policy[] = {
255         [DP_GENL_A_DP_INFO] = { .type = NL_A_UNSPEC,
256                                 .min_len = sizeof(struct ofp_data_hello),
257                                 .max_len = SIZE_MAX },
258     };
259
260     struct buffer request, *reply;
261     struct nlattr *attrs[ARRAY_SIZE(show_policy)];
262     struct ofp_data_hello *odh;
263     int retval;
264     size_t len;
265
266     buffer_init(&request, 0);
267     nl_msg_put_genlmsghdr(&request, dp->sock, 0, openflow_family,
268                           NLM_F_REQUEST, DP_GENL_C_SHOW_DP, 1);
269     nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp->dp_idx);
270     retval = nl_sock_transact(dp->sock, &request, &reply);
271     buffer_uninit(&request);
272     if (retval) {
273         return retval;
274     }
275     if (!nl_policy_parse(reply, show_policy, attrs,
276                          ARRAY_SIZE(show_policy))) {
277         buffer_delete(reply);
278         return EPROTO;
279     }
280
281     odh = (void *) nl_attr_get(attrs[DP_GENL_A_DP_INFO]);
282     if (odh->header.version != OFP_VERSION
283         || odh->header.type != OFPT_DATA_HELLO) {
284         VLOG_ERR("bad show query response (%"PRIu8",%"PRIu8")",
285                  odh->header.version, odh->header.type);
286         buffer_delete(reply);
287         return EPROTO;
288     }
289
290     len = nl_attr_get_size(attrs[DP_GENL_A_DP_INFO]);
291     ofp_print_data_hello(stdout, odh, len, 1);
292
293     return retval;
294 }
295
296 static const struct nl_policy table_policy[] = {
297     [DP_GENL_A_NUMTABLES] = { .type = NL_A_U32 },
298     [DP_GENL_A_TABLE] = { .type = NL_A_UNSPEC },
299 };
300
301 /* Writes a description of 'dp''s tables to stdout.  Returns 0 if successful,
302  * otherwise a positive errno value. */
303 int
304 dpif_dump_tables(struct dpif *dp) 
305 {
306     struct buffer request, *reply;
307     struct nlattr *attrs[ARRAY_SIZE(table_policy)];
308     const struct ofp_table *tables;
309     int n_tables;
310     int i;
311     int retval;
312
313     buffer_init(&request, 0);
314     nl_msg_put_genlmsghdr(&request, dp->sock, 0, openflow_family,
315                           NLM_F_REQUEST, DP_GENL_C_QUERY_TABLE, 1);
316     nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp->dp_idx);
317     retval = nl_sock_transact(dp->sock, &request, &reply);
318     buffer_uninit(&request);
319     if (retval) {
320         return retval;
321     }
322     if (!nl_policy_parse(reply, table_policy, attrs,
323                          ARRAY_SIZE(table_policy))) {
324         buffer_delete(reply);
325         return EPROTO;
326     }
327
328     tables = nl_attr_get(attrs[DP_GENL_A_TABLE]);
329     n_tables = (nl_attr_get_size(attrs[DP_GENL_A_TABLE])
330                 / sizeof(struct ofp_table));
331     n_tables = MIN(n_tables, nl_attr_get_u32(attrs[DP_GENL_A_NUMTABLES]));
332     for (i = 0; i < n_tables; i++) {
333         const struct ofp_table *ot = &tables[i];
334         if (ot->header.version != 1 || ot->header.type != OFPT_TABLE) {
335             VLOG_DBG("bad table query response (%"PRIu8",%"PRIu8")",
336                      ot->header.version, ot->header.type);
337             retval = EPROTO;
338             break;
339         }
340
341         ofp_print_table(stdout, ot);
342         fprintf(stdout,"\n");
343     }
344     buffer_delete(reply);
345
346     return retval;
347 }
348
349 static const struct nl_policy flow_policy[] = {
350     [DP_GENL_A_TABLEIDX] = { .type = NL_A_U16 },
351     [DP_GENL_A_NUMFLOWS] = { .type = NL_A_U32 },
352     [DP_GENL_A_FLOW] = { .type = NL_A_UNSPEC },
353 };
354
355 struct _dump_ofp_flow_mod
356 {
357     struct ofp_flow_mod ofm;
358     struct ofp_action   oa;
359 };
360
361 /* Writes a description of flows in the given 'table' in 'dp' to stdout.  If
362  * 'match' is null, all flows in the table are written; otherwise, only
363  * matching flows are written.  Returns 0 if successful, otherwise a positive
364  * errno value. */
365 int
366 dpif_dump_flows(struct dpif *dp, int table, struct ofp_match *match)
367 {
368     struct buffer request, *reply;
369     struct ofp_flow_mod *ofm;
370     int retval;
371
372     buffer_init(&request, 0);
373     nl_msg_put_genlmsghdr(&request, dp->sock, 0, openflow_family, NLM_F_REQUEST,
374                           DP_GENL_C_QUERY_FLOW, 1);
375     nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp->dp_idx);
376     nl_msg_put_u16(&request, DP_GENL_A_TABLEIDX, table);
377     ofm = nl_msg_put_unspec_uninit(&request, DP_GENL_A_FLOW, sizeof *ofm);
378     memset(ofm, 0, sizeof *ofm);
379     ofm->header.version = 1;
380     ofm->header.type = OFPT_FLOW_MOD;
381     ofm->header.length = htons(sizeof ofm);
382     if (match) {
383         ofm->match = *match;
384     } else {
385         ofm->match.wildcards = htons(OFPFW_ALL);
386     }
387     retval = nl_sock_transact(dp->sock, &request, &reply);
388     buffer_uninit(&request);
389     if (retval) {
390         return retval;
391     }
392
393     for (;;) {
394         struct nlattr *attrs[ARRAY_SIZE(flow_policy)];
395         const struct _dump_ofp_flow_mod *flows, *ofm;
396         int n_flows;
397
398         if (!nl_policy_parse(reply, flow_policy, attrs,
399                              ARRAY_SIZE(flow_policy))) {
400             buffer_delete(reply);
401             return EPROTO;
402         }
403         n_flows = (nl_attr_get_size(attrs[DP_GENL_A_FLOW])
404                    / sizeof(struct ofp_flow_mod));
405         n_flows = MIN(n_flows, nl_attr_get_u32(attrs[DP_GENL_A_NUMFLOWS]));
406         if (n_flows <= 0) {
407             break;
408         }
409
410         flows = nl_attr_get(attrs[DP_GENL_A_FLOW]);
411         for (ofm = flows; ofm < &flows[n_flows]; ofm++) {
412             if (ofm->ofm.header.version != 1){
413                 VLOG_DBG("recv_dp_flow incorrect version");
414                 buffer_delete(reply);
415                 return EPROTO;
416             } else if (ofm->ofm.header.type != OFPT_FLOW_MOD) {
417                 VLOG_DBG("recv_fp_flow bad return message type");
418                 buffer_delete(reply);
419                 return EPROTO;
420             }
421
422             ofp_print_flow_mod(stdout, &ofm->ofm, 
423                     sizeof(struct ofp_flow_mod), 1);
424             putc('\n', stdout);
425         }
426
427         buffer_delete(reply);
428         retval = nl_sock_recv(dp->sock, &reply, true);
429         if (retval) {
430             return retval;
431         }
432     }
433     return 0;
434 }
435
436 /* Tells dp to send num_packets up through netlink for benchmarking*/
437 int
438 dpif_benchmark_nl(struct dpif *dp, uint32_t num_packets, uint32_t packet_size)
439 {
440     struct buffer request;
441     int retval;
442
443     buffer_init(&request, 0);
444     nl_msg_put_genlmsghdr(&request, dp->sock, 0, openflow_family,
445                           NLM_F_REQUEST, DP_GENL_C_BENCHMARK_NL, 1);
446     nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp->dp_idx);
447     nl_msg_put_u32(&request, DP_GENL_A_NPACKETS, num_packets);
448     nl_msg_put_u32(&request, DP_GENL_A_PSIZE, packet_size);
449     retval = nl_sock_send(dp->sock, &request, true);
450     buffer_uninit(&request);
451
452     return retval;
453 }
454 \f
455 static const struct nl_policy openflow_multicast_policy[] = {
456     [DP_GENL_A_DP_IDX] = { .type = NL_A_U32 },
457     [DP_GENL_A_MC_GROUP] = { .type = NL_A_U32 },
458 };
459
460 /* Looks up the Netlink multicast group used by datapath 'dp_idx'.  If
461  * successful, stores the multicast group in '*multicast_group' and returns 0.
462  * Otherwise, returns a positve errno value. */
463 static int
464 lookup_openflow_multicast_group(int dp_idx, int *multicast_group) 
465 {
466     struct nl_sock *sock;
467     struct buffer request, *reply;
468     struct nlattr *attrs[ARRAY_SIZE(openflow_multicast_policy)];
469     int retval;
470
471     retval = nl_sock_create(NETLINK_GENERIC, 0, 0, 0, &sock);
472     if (retval) {
473         return retval;
474     }
475     buffer_init(&request, 0);
476     nl_msg_put_genlmsghdr(&request, sock, 0, openflow_family, NLM_F_REQUEST,
477                           DP_GENL_C_QUERY_DP, 1);
478     nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp_idx);
479     retval = nl_sock_transact(sock, &request, &reply);
480     buffer_uninit(&request);
481     if (retval) {
482         nl_sock_destroy(sock);
483         return retval;
484     }
485     if (!nl_policy_parse(reply, openflow_multicast_policy, attrs,
486                          ARRAY_SIZE(openflow_multicast_policy))) {
487         nl_sock_destroy(sock);
488         buffer_delete(reply);
489         return EPROTO;
490     }
491     *multicast_group = nl_attr_get_u32(attrs[DP_GENL_A_MC_GROUP]);
492     nl_sock_destroy(sock);
493     buffer_delete(reply);
494
495     return 0;
496 }
497
498 /* Sends the given 'command' to datapath 'dp'.  If 'netdev' is nonnull, adds it
499  * to the command as the port name attribute.  Returns 0 if successful,
500  * otherwise a positive errno value. */
501 static int
502 send_mgmt_command(struct dpif *dp, int command, const char *netdev) 
503 {
504     struct buffer request, *reply;
505     int retval;
506
507     buffer_init(&request, 0);
508     nl_msg_put_genlmsghdr(&request, dp->sock, 32, openflow_family,
509                           NLM_F_REQUEST | NLM_F_ACK, command, 1);
510     nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp->dp_idx);
511     if (netdev) {
512         nl_msg_put_string(&request, DP_GENL_A_PORTNAME, netdev);
513     }
514     retval = nl_sock_transact(dp->sock, &request, &reply);
515     buffer_uninit(&request);
516     buffer_delete(reply);
517
518     return retval;
519 }