a65934b6e40de6e61c5e0c9f41f7c16d75882890
[cascardo/ovs.git] / vswitchd / mgmt.c
1 /* Copyright (c) 2009 Nicira Networks
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17
18 #include <arpa/inet.h>
19 #include <assert.h>
20 #include <errno.h>
21 #include <stdlib.h>
22
23 #include "bridge.h"
24 #include "cfg.h"
25 #include "coverage.h"
26 #include "list.h"
27 #include "mgmt.h"
28 #include "openflow/nicira-ext.h"
29 #include "openflow/openflow.h"
30 #include "openflow/openflow-mgmt.h"
31 #include "ofpbuf.h"
32 #include "ovs-vswitchd.h"
33 #include "packets.h"
34 #include "rconn.h"
35 #include "svec.h"
36 #include "vconn.h"
37 #include "vconn-ssl.h"
38 #include "xenserver.h"
39 #include "xtoxll.h"
40
41 #define THIS_MODULE VLM_mgmt
42 #include "vlog.h"
43
44 #define MAX_BACKOFF_DEFAULT 15
45 #define INACTIVITY_PROBE_DEFAULT 15
46
47 static struct svec mgmt_cfg;
48 static uint8_t cfg_cookie[CFG_COOKIE_LEN];
49 static bool need_reconfigure = false;
50 static struct rconn *mgmt_rconn;
51 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60);
52 static struct svec capabilities;
53 static struct ofpbuf ext_data_buffer;
54 uint64_t mgmt_id;
55
56
57 #define TXQ_LIMIT 128         /* Max number of packets to queue for tx. */
58 struct rconn_packet_counter *txqlen; /* # pkts queued for tx on mgmt_rconn. */
59
60 static uint64_t pick_fallback_mgmt_id(void);
61 static void send_config_update(uint32_t xid, bool use_xid);
62 static void send_resources_update(uint32_t xid, bool use_xid);
63 static int recv_ofmp(uint32_t xid, struct ofmp_header *ofmph, size_t len);
64
65 void
66 mgmt_init(void)
67 {
68     txqlen = rconn_packet_counter_create();
69
70     svec_init(&mgmt_cfg);
71     svec_init(&capabilities);
72     svec_add_nocopy(&capabilities, 
73             xasprintf("com.nicira.mgmt.manager=true\n"));
74
75     mgmt_id = cfg_get_dpid(0, "mgmt.id");
76     if (!mgmt_id) {
77         /* Randomly generate a mgmt id */
78         mgmt_id = pick_fallback_mgmt_id();
79     }
80
81     ofpbuf_init(&ext_data_buffer, 0);
82 }
83
84 #ifdef HAVE_OPENSSL
85 static bool
86 config_string_change(const char *key, char **valuep)
87 {
88     const char *value = cfg_get_string(0, "%s", key);
89     if (value && (!*valuep || strcmp(value, *valuep))) {
90         free(*valuep);
91         *valuep = xstrdup(value);
92         return true;
93     } else {
94         return false;
95     }
96 }
97
98 static void
99 mgmt_configure_ssl(void)
100 {
101     static char *private_key_file;
102     static char *certificate_file;
103     static char *cacert_file;
104
105     /* XXX SSL should be configurable separate from the bridges.
106      * XXX should be possible to de-configure SSL. */
107     if (config_string_change("ssl.private-key", &private_key_file)) {
108         vconn_ssl_set_private_key_file(private_key_file);
109     }
110
111     if (config_string_change("ssl.certificate", &certificate_file)) {
112         vconn_ssl_set_certificate_file(certificate_file);
113     }
114
115     if (config_string_change("ssl.ca-cert", &cacert_file)) {
116         vconn_ssl_set_ca_cert_file(cacert_file,
117                 cfg_get_bool(0, "ssl.bootstrap-ca-cert"));
118     }
119 }
120 #endif
121
122 void
123 mgmt_reconfigure(void)
124 {
125     struct svec new_cfg;
126     uint8_t new_cookie[CFG_COOKIE_LEN];
127     bool cfg_updated = false;
128     const char *controller_name;
129     int max_backoff;
130     int inactivity_probe;
131     int retval;
132
133     if (!cfg_has_section("mgmt")) {
134         if (mgmt_rconn) {
135             rconn_destroy(mgmt_rconn);
136             mgmt_rconn = NULL;
137         }
138         return;
139     }
140
141     /* If this is an established connection, send a resources update. */
142     /* xxx This is wasteful if there were no resource changes!!! */
143     if (mgmt_rconn) {
144         send_resources_update(0, false);
145     }
146
147     cfg_get_cookie(new_cookie);
148     if (memcmp(cfg_cookie, new_cookie, sizeof(cfg_cookie))) {
149         memcpy(cfg_cookie, new_cookie, sizeof(cfg_cookie));
150         cfg_updated = true;
151     }
152
153     svec_init(&new_cfg);
154     cfg_get_section(&new_cfg, "mgmt");
155     if (svec_equal(&mgmt_cfg, &new_cfg)) {
156         /* Reconnecting to the controller causes the config file to be
157          * resent automatically.  If we're not reconnecting and the
158          * config file has changed, we need to notify the controller of
159          * changes. */
160         if (cfg_updated && mgmt_rconn) {
161             send_config_update(0, false);
162         }
163         svec_destroy(&new_cfg);
164         return;
165     }
166
167     controller_name = cfg_get_string(0, "mgmt.controller");
168     if (!controller_name) {
169         VLOG_ERR("no controller specified for managment");
170         svec_destroy(&new_cfg);
171         return;
172     }
173
174     max_backoff = cfg_get_int(0, "mgmt.max-backoff");
175     if (max_backoff < 1) {
176         max_backoff = MAX_BACKOFF_DEFAULT;
177     } else if (max_backoff > 3600) {
178         max_backoff = 3600;
179     }
180
181     inactivity_probe = cfg_get_int(0, "mgmt.inactivity-probe");
182     if (inactivity_probe < 5) {
183         inactivity_probe = INACTIVITY_PROBE_DEFAULT;
184     }
185
186     /* xxx If this changes, we need to restart bridges to use new id,
187      * xxx but they need the id before the connect to controller, but we
188      * xxx need their dpids. */
189     /* Check if a different mgmt id has been assigned. */
190     if (cfg_has("mgmt.id")) {
191         uint64_t cfg_mgmt_id = cfg_get_dpid(0, "mgmt.id");
192         if (cfg_mgmt_id != mgmt_id) {
193             mgmt_id = cfg_mgmt_id;
194         }
195     }
196
197     svec_swap(&new_cfg, &mgmt_cfg);
198     svec_destroy(&new_cfg);
199
200 #ifdef HAVE_OPENSSL
201     /* Configure SSL. */
202     mgmt_configure_ssl();
203 #endif
204
205     if (mgmt_rconn) {
206         rconn_destroy(mgmt_rconn);
207         mgmt_rconn = NULL;
208     }
209     mgmt_rconn = rconn_create(inactivity_probe, max_backoff);
210     retval = rconn_connect(mgmt_rconn, controller_name);
211     if (retval == EAFNOSUPPORT) {
212         VLOG_ERR("no support for %s vconn", controller_name);
213     }
214 }
215
216 static void *
217 make_ofmp_xid(size_t ofmp_len, uint16_t type, uint32_t xid,
218         struct ofpbuf **bufferp)
219 {
220     struct ofmp_header *oh;
221
222     oh = make_openflow_xid(ofmp_len, OFPT_VENDOR, xid, bufferp);
223     oh->header.vendor = htonl(NX_VENDOR_ID);
224     oh->header.subtype = htonl(NXT_MGMT);
225     oh->type = htons(type);
226
227     return oh;
228 }
229
230 static void *
231 make_ofmp(size_t ofmp_len, uint16_t type, struct ofpbuf **bufferp)
232 {
233     struct ofmp_header *oh;
234
235     oh = make_openflow(ofmp_len, OFPT_VENDOR, bufferp);
236     oh->header.vendor = htonl(NX_VENDOR_ID);
237     oh->header.subtype = htonl(NXT_MGMT);
238     oh->type = htons(type);
239
240     return oh;
241 }
242
243 static int
244 send_openflow_buffer(struct ofpbuf *buffer)
245 {               
246     int retval;
247
248     if (!mgmt_rconn) {
249         VLOG_ERR("attempt to send openflow packet with no rconn\n");
250         return EINVAL;
251     }
252
253     /* OpenFlow messages use a 16-bit length field, so messages over 64K
254      * must be broken into multiple pieces. 
255      */
256     if (buffer->size <= 65535) {
257         update_openflow_length(buffer);
258         retval = rconn_send_with_limit(mgmt_rconn, buffer, txqlen, TXQ_LIMIT);
259         if (retval) {
260             VLOG_WARN_RL(&rl, "send to %s failed: %s",
261                          rconn_get_name(mgmt_rconn), strerror(retval));
262         }   
263         return retval;
264     } else {
265         struct ofmp_header *header = (struct ofmp_header *)buffer->data;
266         uint32_t xid = header->header.header.xid;
267         size_t remain = buffer->size;
268         uint8_t *ptr = buffer->data;
269         
270         /* Mark the OpenFlow header with a zero length to indicate some
271          * funkiness. 
272          */
273         header->header.header.length = 0;
274
275         while (remain > 0) {
276             struct ofpbuf *new_buffer;
277             struct ofmp_extended_data *oed;
278             size_t new_len = MIN(65535 - sizeof *oed, remain);
279
280             oed = make_ofmp_xid(sizeof *oed, OFMPT_EXTENDED_DATA, xid, 
281                     &new_buffer);
282             oed->type = header->type;
283
284             if (remain > 65535) {
285                 oed->flags |= OFMPEDF_MORE_DATA;
286             }
287
288             printf("xxx SENDING LEN: %d\n", new_len);
289
290             /* Copy the entire original message, including the OpenFlow
291              * header, since management protocol structure definitions
292              * include these headers.
293              */
294             ofpbuf_put(new_buffer, ptr, new_len);
295
296             update_openflow_length(new_buffer);
297             retval = rconn_send_with_limit(mgmt_rconn, new_buffer, txqlen, 
298                     TXQ_LIMIT);
299             if (retval) {
300                 VLOG_WARN_RL(&rl, "send to %s failed: %s",
301                              rconn_get_name(mgmt_rconn), strerror(retval));
302                 ofpbuf_delete(buffer);
303                 return retval;
304             }   
305
306             remain -= new_len;
307             ptr += new_len;
308         }
309
310         ofpbuf_delete(buffer);
311         return 0;
312     }
313 }   
314     
315 static void
316 send_features_reply(uint32_t xid)
317 {
318     struct ofpbuf *buffer;
319     struct ofp_switch_features *ofr;
320
321     ofr = make_openflow_xid(sizeof *ofr, OFPT_FEATURES_REPLY, xid, &buffer);
322     ofr->datapath_id  = 0;
323     ofr->n_tables     = 0;
324     ofr->n_buffers    = 0;
325     ofr->capabilities = 0;
326     ofr->actions      = 0;
327     send_openflow_buffer(buffer);
328 }
329
330 static void 
331 send_capability_reply(uint32_t xid)
332 {
333     int i;
334     struct ofpbuf *buffer;
335     struct ofmp_capability_reply *ofmpcr;
336
337     ofmpcr = make_ofmp_xid(sizeof *ofmpcr, OFMPT_CAPABILITY_REPLY, 
338             xid, &buffer);
339     ofmpcr->format = htonl(OFMPCOF_SIMPLE);
340     ofmpcr->mgmt_id = htonll(mgmt_id);
341     for (i=0; i<capabilities.n; i++) {
342         ofpbuf_put(buffer, capabilities.names[i], 
343                 strlen(capabilities.names[i]));
344     }
345     send_openflow_buffer(buffer);
346 }
347
348 static void 
349 send_resources_update(uint32_t xid, bool use_xid)
350 {
351     struct ofpbuf *buffer;
352     struct ofmp_resources_update *ofmpru;
353     struct ofmp_tlv *tlv;
354     struct svec br_list;
355     struct svec port_list;
356     const char *host_uuid;
357     int i;
358
359     if (use_xid) {
360         ofmpru = make_ofmp_xid(sizeof *ofmpru, OFMPT_RESOURCES_UPDATE, 
361                 xid, &buffer);
362     } else {
363         ofmpru = make_ofmp(sizeof *ofmpru, OFMPT_RESOURCES_UPDATE, &buffer);
364     }
365
366     /* On XenServer systems, each host has its own UUID, which we provide
367      * to the controller. 
368      */ 
369     host_uuid = xenserver_get_host_uuid();
370     if (host_uuid) {
371         struct ofmptsr_mgmt_uuid *mgmt_uuid_tlv;
372
373         mgmt_uuid_tlv = ofpbuf_put_zeros(buffer, sizeof(*mgmt_uuid_tlv));
374         mgmt_uuid_tlv->type = htons(OFMPTSR_MGMT_UUID);
375         mgmt_uuid_tlv->len = htons(sizeof(*mgmt_uuid_tlv));
376         mgmt_uuid_tlv->mgmt_id = htonll(mgmt_id);
377         memcpy(mgmt_uuid_tlv->uuid, host_uuid, OFMP_UUID_LEN);
378     }
379
380     svec_init(&br_list);
381     cfg_get_subsections(&br_list, "bridge");
382     for (i=0; i < br_list.n; i++) {
383         struct ofmptsr_dp *dp_tlv;
384         uint64_t dp_id;
385         int n_uuid;
386
387         dp_id = bridge_get_datapathid(br_list.names[i]);
388         if (!dp_id) {
389             VLOG_WARN_RL(&rl, "bridge %s doesn't seem to exist", 
390                     br_list.names[i]);
391             continue;
392         }
393         dp_tlv = ofpbuf_put_zeros(buffer, sizeof(*dp_tlv));
394         dp_tlv->type = htons(OFMPTSR_DP);
395         dp_tlv->len = htons(sizeof(*dp_tlv));
396
397         dp_tlv->dp_id = htonll(dp_id);
398         memcpy(dp_tlv->name, br_list.names[i], strlen(br_list.names[i])+1);
399
400         /* On XenServer systems, each network has one or more UUIDs
401          * associated with it, which we provide to the controller. 
402          */
403         n_uuid = cfg_count("bridge.%s.xs-network-uuids", br_list.names[i]);
404         if (n_uuid) {
405             struct ofmptsr_dp_uuid *dp_uuid_tlv;
406             size_t tlv_len = sizeof(*dp_uuid_tlv) + n_uuid * OFMP_UUID_LEN;
407             int j;
408
409             dp_uuid_tlv = ofpbuf_put_zeros(buffer, sizeof(*dp_uuid_tlv));
410             dp_uuid_tlv->type = htons(OFMPTSR_DP_UUID);
411             dp_uuid_tlv->len = htons(tlv_len);
412             dp_uuid_tlv->dp_id = htonll(dp_id);
413
414             for (j=0; j<n_uuid; j++) {
415                 const char *dp_uuid = cfg_get_string(j, 
416                         "bridge.%s.xs-network-uuids", br_list.names[i]);
417
418                 /* The UUID list could change underneath us, so just
419                  * fill with zeros in that case.  Another update will be
420                  * initiated shortly, which should contain corrected data.
421                  */
422                 if (dp_uuid) {
423                     ofpbuf_put(buffer, dp_uuid, OFMP_UUID_LEN);
424                 } else {
425                     ofpbuf_put_zeros(buffer, OFMP_UUID_LEN);
426                 }
427             }
428         }
429     }
430     svec_destroy(&br_list);
431
432     /* On XenServer systems, extended information about virtual interfaces 
433      * (VIFs) is available, which is needed by the controller. 
434      */ 
435     svec_init(&port_list);
436     bridge_get_ifaces(&port_list);
437     for (i=0; i < port_list.n; i++) {
438         const char *vif_uuid, *vm_uuid, *net_uuid;
439         uint64_t vif_mac;
440         struct ofmptsr_vif *vif_tlv;
441
442         vif_uuid = cfg_get_string(0, "port.%s.vif-uuid", port_list.names[i]);
443         if (!vif_uuid) {
444             continue;
445         }
446
447         vif_tlv = ofpbuf_put_zeros(buffer, sizeof(*vif_tlv));
448         vif_tlv->type = htons(OFMPTSR_VIF);
449         vif_tlv->len = htons(sizeof(*vif_tlv));
450
451         memcpy(vif_tlv->name, port_list.names[i], strlen(port_list.names[i])+1);
452         memcpy(vif_tlv->vif_uuid, vif_uuid, sizeof(vif_tlv->vif_uuid));
453
454         vm_uuid = cfg_get_string(0, "port.%s.vm-uuid", port_list.names[i]);
455         if (vm_uuid) {
456             memcpy(vif_tlv->vm_uuid, vm_uuid, sizeof(vif_tlv->vm_uuid));
457         } else {
458             /* In case the vif disappeared underneath us. */
459             memset(vif_tlv->vm_uuid, '\0', sizeof(vif_tlv->vm_uuid));
460         }
461
462         net_uuid = cfg_get_string(0, "port.%s.net-uuid", port_list.names[i]);
463         if (net_uuid) {
464             memcpy(vif_tlv->net_uuid, net_uuid, sizeof(vif_tlv->net_uuid));
465         } else {
466             /* In case the vif disappeared underneath us. */
467             memset(vif_tlv->net_uuid, '\0', sizeof(vif_tlv->net_uuid));
468         }
469
470         vif_mac = cfg_get_mac(0, "port.%s.vif-mac", port_list.names[i]);
471         vif_tlv->vif_mac = htonll(vif_mac);
472     }
473     svec_destroy(&port_list);
474
475     /* Put end marker. */
476     tlv = ofpbuf_put_zeros(buffer, sizeof(*tlv));
477     tlv->type = htons(OFMPTSR_END);
478     tlv->len = htons(sizeof(*tlv));
479     send_openflow_buffer(buffer);
480 }
481
482 static void 
483 send_config_update(uint32_t xid, bool use_xid)
484 {
485     struct ofpbuf *buffer;
486     struct ofmp_config_update *ofmpcu;
487
488     if (use_xid) {
489         ofmpcu = make_ofmp_xid(sizeof *ofmpcu, OFMPT_CONFIG_UPDATE, 
490                 xid, &buffer);
491     } else {
492         ofmpcu = make_ofmp(sizeof *ofmpcu, OFMPT_CONFIG_UPDATE, &buffer);
493     }
494
495     ofmpcu->format = htonl(OFMPCOF_SIMPLE);
496     memcpy(ofmpcu->cookie, cfg_cookie, sizeof(ofmpcu->cookie));
497     cfg_buf_put(buffer);
498     send_openflow_buffer(buffer);
499 }
500
501 static void 
502 send_config_update_ack(uint32_t xid, bool success)
503 {
504     struct ofpbuf *buffer;
505     struct ofmp_config_update_ack *ofmpcua;
506
507     ofmpcua = make_ofmp_xid(sizeof *ofmpcua, OFMPT_CONFIG_UPDATE_ACK, 
508             xid, &buffer);
509
510     ofmpcua->format = htonl(OFMPCOF_SIMPLE);
511     if (success) {
512         ofmpcua->flags = htonl(OFMPCUAF_SUCCESS);
513     }
514     cfg_get_cookie(ofmpcua->cookie);
515     send_openflow_buffer(buffer);
516 }
517
518 static void
519 send_ofmp_error_msg(uint32_t xid, uint16_t type, uint16_t code, 
520             const void *data, size_t len)
521 {
522     struct ofpbuf *buffer;
523     struct ofmp_error_msg *oem;
524
525     oem = make_ofmp_xid(sizeof(*oem)+len, OFMPT_ERROR, xid, &buffer);
526     oem->type = htons(type);
527     oem->code = htons(code);
528     memcpy(oem->data, data, len);
529     send_openflow_buffer(buffer);
530 }
531
532 static void
533 send_error_msg(uint32_t xid, uint16_t type, uint16_t code, 
534             const void *data, size_t len)
535 {
536     struct ofpbuf *buffer;
537     struct ofp_error_msg *oem;
538
539     oem = make_openflow_xid(sizeof(*oem)+len, OFPT_ERROR, xid, &buffer);
540     oem->type = htons(type);
541     oem->code = htons(code);
542     memcpy(oem->data, data, len);
543     send_openflow_buffer(buffer);
544 }
545
546 static int
547 recv_echo_request(uint32_t xid UNUSED, const void *msg)
548 {
549     const struct ofp_header *rq = msg;
550     send_openflow_buffer(make_echo_reply(rq));
551     return 0;
552 }
553
554 static int
555 recv_features_request(uint32_t xid, const void *msg UNUSED)
556 {
557     send_features_reply(xid);
558     return 0;
559 }
560
561 static int
562 recv_set_config(uint32_t xid UNUSED, const void *msg UNUSED)
563 {
564     /* Nothing to configure! */
565     return 0;
566 }
567
568 static int
569 recv_ofmp_capability_request(uint32_t xid, const struct ofmp_header *ofmph,
570         size_t len)
571 {
572     struct ofmp_capability_request *ofmpcr;
573
574     if (len != sizeof(*ofmpcr)) {
575         /* xxx Send error */
576         return -EINVAL;
577     }
578
579     ofmpcr = (struct ofmp_capability_request *)ofmph;
580     if (ofmpcr->format != htonl(OFMPCAF_SIMPLE)) {
581         /* xxx Send error */
582         return -EINVAL;
583     }
584
585     send_capability_reply(xid);
586
587     return 0;
588 }
589
590 static int
591 recv_ofmp_resources_request(uint32_t xid, const void *msg UNUSED, 
592         size_t len UNUSED)
593 {
594     send_resources_update(xid, true);
595     return 0;
596 }
597
598 static int
599 recv_ofmp_config_request(uint32_t xid, const struct ofmp_header *ofmph, 
600         size_t len)
601 {
602     struct ofmp_config_request *ofmpcr;
603
604     if (len != sizeof(*ofmpcr)) {
605         /* xxx Send error */
606         return -EINVAL;
607     }
608
609     ofmpcr = (struct ofmp_config_request *)ofmph;
610     if (ofmpcr->format != htonl(OFMPCOF_SIMPLE)) {
611         /* xxx Send error */
612         return -EINVAL;
613     }
614
615     send_config_update(xid, true);
616
617     return 0;
618 }
619
620 static int
621 recv_ofmp_config_update(uint32_t xid, const struct ofmp_header *ofmph,
622         size_t len)
623 {
624     struct ofmp_config_update *ofmpcu;
625     int data_len;
626
627     data_len = len - sizeof(*ofmpcu);
628     if (data_len <= sizeof(*ofmpcu)) {
629         /* xxx Send error. */
630         return -EINVAL;
631     }
632
633     ofmpcu = (struct ofmp_config_update *)ofmph;
634     if (ofmpcu->format != htonl(OFMPCOF_SIMPLE)) {
635         /* xxx Send error */
636         return -EINVAL;
637     }
638
639     /* Check if the supplied cookie matches our current understanding of
640      * it.  If they don't match, tell the controller and let it sort
641      * things out. */
642     if (cfg_lock(ofmpcu->cookie, 0)) {  
643         /* xxx cfg_lock can fail for other reasons, such as being
644          * xxx locked... */
645         VLOG_WARN_RL(&rl, "config update failed due to bad cookie\n");
646         send_config_update_ack(xid, false);
647         return 0;
648     }
649
650     /* xxx We should probably do more sanity checking than this. */
651
652     cfg_write_data(ofmpcu->data, data_len);
653     cfg_unlock();
654
655     /* Send the ACK before running reconfigure, since our management
656      * connection settings may have changed. */
657     send_config_update_ack(xid, true);
658
659     need_reconfigure = true;
660
661     return 0;
662 }
663
664 static int
665 recv_ofmp_extended_data(uint32_t xid, const struct ofmp_header *ofmph,
666         size_t len)
667 {
668     size_t data_len;
669     struct ofmp_extended_data *ofmped;
670     uint8_t *ptr;
671
672     data_len = len - sizeof(*ofmped);
673     if (data_len <= sizeof(*ofmped)) {
674         /* xxx Send error. */
675         return -EINVAL;
676     }
677
678     ofmped = (struct ofmp_extended_data *)ofmph;
679
680     ptr = ofpbuf_put(&ext_data_buffer, ofmped->data, data_len);
681
682     if (!ofmped->flags & OFMPEDF_MORE_DATA) {
683         recv_ofmp(xid, ext_data_buffer.data, ext_data_buffer.size);
684         ofpbuf_clear(&ext_data_buffer);
685     }
686
687     return 0;
688 }
689
690 /* Handles receiving a management message.  Generally, this function
691  * will be called 'len' set to zero, and the length will be derived by
692  * the OpenFlow header.  With the extended data message, management
693  * messages are not constrained by OpenFlow's 64K message length limit.  
694  * The extended data handler calls this function with the 'len' set to
695  * the total message length and the OpenFlow header's length field is 
696  * ignored.
697  */
698 static
699 int recv_ofmp(uint32_t xid, struct ofmp_header *ofmph, size_t len)
700 {
701     if (!len) {
702         len = ntohs(ofmph->header.header.length);
703     }
704
705     /* xxx Should sanity-check for min/max length */
706     switch (ntohs(ofmph->type)) 
707     {
708         case OFMPT_CAPABILITY_REQUEST:
709             return recv_ofmp_capability_request(xid, ofmph, len);
710         case OFMPT_RESOURCES_REQUEST:
711             return recv_ofmp_resources_request(xid, ofmph, len);
712         case OFMPT_CONFIG_REQUEST:
713             return recv_ofmp_config_request(xid, ofmph, len);
714         case OFMPT_CONFIG_UPDATE:
715             return recv_ofmp_config_update(xid, ofmph, len);
716         case OFMPT_EXTENDED_DATA:
717             return recv_ofmp_extended_data(xid, ofmph, len);
718         default:
719             VLOG_WARN_RL(&rl, "unknown mgmt message: %d", 
720                     ntohs(ofmph->type));
721             return -EINVAL;
722     }
723 }
724
725 static int 
726 recv_nx_msg(uint32_t xid, const void *oh)
727 {
728     const struct nicira_header *nh = oh;
729
730     switch (ntohl(nh->subtype)) {
731
732     case NXT_MGMT:
733         return recv_ofmp(xid, (struct ofmp_header *)oh, 0);
734
735     default:
736         send_error_msg(xid, OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE, 
737                 oh, ntohs(nh->header.length));
738         return -EINVAL;
739     }
740 }
741
742 static int
743 recv_vendor(uint32_t xid, const void *oh)
744 {
745     const struct ofp_vendor_header *ovh = oh;
746
747     switch (ntohl(ovh->vendor))
748     {
749     case NX_VENDOR_ID:
750         return recv_nx_msg(xid, oh);
751
752     default:
753         VLOG_WARN_RL(&rl, "unknown vendor: 0x%x", ntohl(ovh->vendor));
754         send_error_msg(xid, OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR, 
755                 oh, ntohs(ovh->header.length));
756         return -EINVAL; 
757     }
758 }
759
760 static int
761 handle_msg(uint32_t xid, const void *msg, size_t length)
762 {
763     int (*handler)(uint32_t, const void *);
764     struct ofp_header *oh;
765     size_t min_size;
766
767     COVERAGE_INC(mgmt_received);
768
769     /* Check encapsulated length. */
770     oh = (struct ofp_header *) msg;
771     if (ntohs(oh->length) > length) {
772         return -EINVAL;
773     }
774     assert(oh->version == OFP_VERSION);
775
776     /* Figure out how to handle it. */
777     switch (oh->type) {
778     case OFPT_ECHO_REQUEST:
779         min_size = sizeof(struct ofp_header);
780         handler = recv_echo_request;
781         break;
782     case OFPT_ECHO_REPLY:
783         return 0;
784     case OFPT_FEATURES_REQUEST:
785         min_size = sizeof(struct ofp_header);
786         handler = recv_features_request;
787         break;
788     case OFPT_SET_CONFIG:
789         min_size = sizeof(struct ofp_switch_config);
790         handler = recv_set_config;
791         break;
792     case OFPT_VENDOR:
793         min_size = sizeof(struct ofp_vendor_header);
794         handler = recv_vendor;
795         break;
796     default:
797         VLOG_WARN_RL(&rl, "unknown openflow type: %d", oh->type);
798         send_error_msg(xid, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE,
799                 msg, length);
800         return -EINVAL;
801     }
802
803     /* Handle it. */
804     if (length < min_size) {
805         return -EFAULT;
806     }
807     return handler(xid, msg);
808 }
809
810 bool 
811 mgmt_run(void)
812 {
813     int i;
814
815     if (!mgmt_rconn) {
816         return false;
817     }
818
819     need_reconfigure = false;
820     rconn_run(mgmt_rconn);
821
822     /* Do some processing, but cap it at a reasonable amount so that
823      * other processing doesn't starve. */
824     for (i=0; i<50; i++) {
825         struct ofpbuf *buffer;
826         struct ofp_header *oh;
827
828         buffer = rconn_recv(mgmt_rconn);
829         if (!buffer) {
830             break;
831         }
832
833         if (buffer->size >= sizeof *oh) {
834             oh = buffer->data;
835             handle_msg(oh->xid, buffer->data, buffer->size);
836             ofpbuf_delete(buffer);
837         } else {
838             VLOG_WARN_RL(&rl, "received too-short OpenFlow message");
839         }
840     }
841
842     return need_reconfigure;
843 }
844
845 void
846 mgmt_wait(void)
847 {
848     if (!mgmt_rconn) {
849         return;
850     }
851
852     rconn_run_wait(mgmt_rconn);
853     rconn_recv_wait(mgmt_rconn);
854 }
855
856 static uint64_t
857 pick_fallback_mgmt_id(void)
858 {
859     uint8_t ea[ETH_ADDR_LEN];
860     eth_addr_random(ea);
861     ea[0] = 0x00;               /* Set Nicira OUI. */
862     ea[1] = 0x23;
863     ea[2] = 0x20;
864     return eth_addr_to_uint64(ea);
865 }