secchan: Make it possible to destroy an ofproto.
authorBen Pfaff <blp@nicira.com>
Tue, 3 Mar 2009 01:30:32 +0000 (17:30 -0800)
committerBen Pfaff <blp@nicira.com>
Tue, 3 Mar 2009 01:30:32 +0000 (17:30 -0800)
16 files changed:
secchan/discovery.c
secchan/discovery.h
secchan/executer.c
secchan/executer.h
secchan/fail-open.c
secchan/fail-open.h
secchan/in-band.c
secchan/in-band.h
secchan/netflow.c
secchan/netflow.h
secchan/ofproto.c
secchan/ofproto.h
secchan/pinsched.c
secchan/pinsched.h
secchan/status.c
secchan/status.h

index 42f40f143f8c15848814b03592327a407423dfd3..56beed258e29b23dff89603b32a763417de578e5 100644 (file)
@@ -146,6 +146,17 @@ discovery_create(const char *accept_controller_re, bool update_resolv_conf,
     return d;
 }
 
+void
+discovery_destroy(struct discovery *d)
+{
+    if (d) {
+        /* We don't own d->accept_controller_re. */
+        regfree(&d->accept_controller_regex);
+        dhclient_destroy(d->dhcp);
+        free(d);
+    }
+}
+
 void
 discovery_question_connectivity(struct discovery *d)
 {
index c955d75b87434e4bdab0d0774f3b9a334709c1bc..ba6d988e19f8a885eeea7f2d9753e07c172968c3 100644 (file)
@@ -43,6 +43,7 @@ struct switch_status;
 struct discovery *discovery_create(const char *accept_controller_re,
                                    bool update_resolv_conf,
                                    struct dpif *, struct switch_status *);
+void discovery_destroy(struct discovery *);
 void discovery_question_connectivity(struct discovery *);
 bool discovery_run(struct discovery *, char **controller_name);
 void discovery_wait(struct discovery *);
index 5f59832c4c621f1892abac6f5944b8f5dd20725c..ab7ae58ca0616d02e6b5be79bd33d23be5c6d1fe 100644 (file)
@@ -84,12 +84,14 @@ struct executer {
     /* Children. */
     struct child children[MAX_CHILDREN];
     size_t n_children;
-
-    /* File descriptors. */
-    int wait_fd;                /* Pipe FD for wakeup when on SIGCHLD. */
-    int null_fd;                /* FD for /dev/null. */
 };
 
+/* File descriptors for waking up when a child dies. */
+static int signal_fds[2];
+
+/* File descriptor for /dev/null. */
+static int null_fd = -1;
+
 static void send_child_status(struct rconn *, uint32_t xid, uint32_t status,
                               const void *data, size_t size);
 static void send_child_message(struct rconn *, uint32_t xid, uint32_t status,
@@ -219,9 +221,9 @@ executer_handle_request(struct executer *e, struct rconn *rconn,
          * subprocesses at once?  Would also want to catch fatal signals and
          * kill them at the same time though. */
         fatal_signal_fork();
-        dup2(e->null_fd, 0);
+        dup2(null_fd, 0);
         dup2(output_fds[1], 1);
-        dup2(e->null_fd, 2);
+        dup2(null_fd, 2);
         max_fds = get_max_fds();
         for (i = 3; i < max_fds; i++) {
             close(i);
@@ -380,7 +382,7 @@ executer_run(struct executer *e)
     }
 
     /* If SIGCHLD was received, reap dead children. */
-    if (read(e->wait_fd, buffer, sizeof buffer) <= 0) {
+    if (read(signal_fds[0], buffer, sizeof buffer) <= 0) {
         return;
     }
     for (;;) {
@@ -420,13 +422,13 @@ executer_wait(struct executer *e)
         size_t i;
 
         /* Wake up on SIGCHLD. */
-        poll_fd_wait(e->wait_fd, POLLIN);
+        poll_fd_wait(signal_fds[0], POLLIN);
 
         /* Wake up when we get output from a child. */
         for (i = 0; i < e->n_children; i++) {
             struct child *child = &e->children[i];
             if (child->output_fd >= 0) {
-                poll_fd_wait(e->wait_fd, POLLIN);
+                poll_fd_wait(child->output_fd, POLLIN);
             }
         }
     }
@@ -448,12 +450,10 @@ executer_rconn_closing(struct executer *e, struct rconn *rconn)
     }
 }
 
-static int child_fd;
-
 static void
 sigchld_handler(int signr UNUSED)
 {
-    write(child_fd, "", 1);
+    write(signal_fds[1], "", 1);
 }
 
 struct executer *
@@ -461,20 +461,20 @@ executer_create(const char *command_acl, const char *command_dir)
 {
     struct executer *e;
     struct sigaction sa;
-    int fds[2], null_fd;
 
-    /* Create pipe for notifying us that SIGCHLD was invoked. */
-    if (pipe(fds)) {
-        ofp_fatal(errno, "pipe failed");
-    }
-    set_nonblocking(fds[0]);
-    set_nonblocking(fds[1]);
-    child_fd = fds[1];
-
-    /* Open /dev/null. */
-    null_fd = open("/dev/null", O_RDWR);
-    if (null_fd < 0) {
-        ofp_fatal(errno, "could not open /dev/null");
+    if (null_fd == -1) {
+        /* Create pipe for notifying us that SIGCHLD was invoked. */
+        if (pipe(signal_fds)) {
+            ofp_fatal(errno, "pipe failed");
+        }
+        set_nonblocking(signal_fds[0]);
+        set_nonblocking(signal_fds[1]);
+
+        /* Open /dev/null. */
+        null_fd = open("/dev/null", O_RDWR);
+        if (null_fd < 0) {
+            ofp_fatal(errno, "could not open /dev/null");
+        }
     }
 
     /* Set up signal handler. */
@@ -490,7 +490,25 @@ executer_create(const char *command_acl, const char *command_dir)
     e->command_acl = command_acl;
     e->command_dir = command_dir;
     e->n_children = 0;
-    e->wait_fd = fds[0];
-    e->null_fd = null_fd;
     return e;
 }
+
+void
+executer_destroy(struct executer *e)
+{
+    if (e) {
+        size_t i;
+
+        /* We don't own e->command_acl or e->command_dir. */
+        for (i = 0; i < e->n_children; i++) {
+            struct child *child = &e->children[i];
+
+            free(child->name);
+            kill(child->pid, SIGHUP);
+            /* We don't own child->rconn. */
+            free(child->output);
+            free(child);
+        }
+        free(e);
+    }
+}
index 0429a879a6c3172f1bda0f97d21c01c2c341dcfd..30bb0a286d9de123ee5a50778a2b694c4cda581b 100644 (file)
@@ -39,6 +39,7 @@ struct rconn;
 
 struct executer *executer_create(const char *command_acl,
                                  const char *command_dir);
+void executer_destroy(struct executer *);
 void executer_run(struct executer *);
 void executer_wait(struct executer *);
 void executer_rconn_closing(struct executer *, struct rconn *);
index 605e25bd573669c842ace1777ca5ced63519d2b6..203e0930cafacc33093a3441e926b7a060cd1c2e 100644 (file)
@@ -34,6 +34,7 @@
 #include <config.h>
 #include "fail-open.h"
 #include <inttypes.h>
+#include <stdlib.h>
 #include "flow.h"
 #include "mac-learning.h"
 #include "ofproto.h"
@@ -154,3 +155,13 @@ fail_open_create(int trigger_duration, struct switch_status *switch_status,
                                     fail_open_status_cb, fo);
     return fo;
 }
+
+void
+fail_open_destroy(struct fail_open *fo)
+{
+    if (fo) {
+        /* We don't own fo->controller. */
+        mac_learning_destroy(fo->mac_learning);
+        free(fo);
+    }
+}
index f8ac32c5359ccdb03a1ebad879bad5cd0a71f578..cb1ac761b23759b610966593a1676ab1acd07cab 100644 (file)
@@ -46,6 +46,7 @@ struct switch_status;
 struct fail_open *fail_open_create(int trigger_duration,
                                    struct switch_status *,
                                    struct rconn *controller);
+void fail_open_destroy(struct fail_open *);
 void fail_open_wait(struct fail_open *);
 void fail_open_run(struct fail_open *);
 bool fail_open_handle_flow_miss(struct fail_open *, struct ofproto *,
index bf5e904cb632cbddb81ef53eb741e081c55e6de6..5c223e96a9b122a8758d0d0a4e9d6a11093c007c 100644 (file)
@@ -268,3 +268,13 @@ in_band_create(struct dpif *dpif, struct switch_status *ss,
 
     return in_band;
 }
+
+void
+in_band_destroy(struct in_band *in_band)
+{
+    if (in_band) {
+        mac_learning_destroy(in_band->mac_learning);
+        netdev_close(in_band->netdev);
+        /* We don't own the rconn. */
+    }
+}
index 26636e2c23c94ff85225c403609342e9f1cf6347..5951692913815e1914becded8ecc3385479a79de 100644 (file)
@@ -45,6 +45,7 @@ struct switch_status;
 
 struct in_band *in_band_create(struct dpif *, struct switch_status *,
                                struct rconn *controller);
+void in_band_destroy(struct in_band *);
 void in_band_run(struct in_band *);
 void in_band_wait(struct in_band *);
 bool in_band_handle_flow_miss(struct in_band *, struct ofproto *,
index c08b3d8ce2bae108b98175892cc96f92438212b3..7f2d320f44ef746410aae4b415cc4f9723d50f6e 100644 (file)
@@ -310,3 +310,20 @@ netflow_create(const char *br_name)
     nf->netflow_cnt = 0;
     return nf;
 }
+
+void
+netflow_destroy(struct netflow *nf)
+{
+    if (nf) {
+        int i;
+
+        /* We don't own nf->br_name. */
+        for (i = 0; i < MAX_COLLECTORS; i++) {
+            int fd = nf->netflow_fds[i];
+            if (fd >= 0) {
+                close(fd);
+            }
+        }
+        free(nf);
+    }
+}
index 98dd7bcb7dbce635420837b6d9c0e34572190f8e..9c4987776fd12ae81a5e9ae732d1a34fe2b9760b 100644 (file)
@@ -39,6 +39,7 @@
 struct odp_flow_stats;
 
 struct netflow *netflow_create(const char *br_name);
+void netflow_destroy(struct netflow *);
 void netflow_reconfigure(struct netflow *);
 void netflow_expire(struct netflow *, const flow_t *,
                     const struct odp_flow_stats *,
index 00a1616736942d016e3b5245f2323d85fb1bd6b1..d019ad3a54bebd9998c21b3352b0b4fe7794f54c 100644 (file)
@@ -82,7 +82,8 @@ struct ofport {
     struct ofp_phy_port opp;    /* In host byte order. */
 };
 
-static void hton_ofp_phy_port(struct ofp_phy_port *opp);
+static void ofport_free(struct ofport *);
+static void hton_ofp_phy_port(struct ofp_phy_port *);
 
 struct odp_actions {
     union odp_action *actions;
@@ -306,6 +307,46 @@ ofproto_create(const struct ofsettings *settings)
     return p;
 }
 
+void
+ofproto_destroy(struct ofproto *p)
+{
+    struct ofconn *ofconn, *next_ofconn;
+    struct ofport *ofport;
+    unsigned int port_no;
+    size_t i;
+
+    if (!p) {
+        return;
+    }
+
+    LIST_FOR_EACH_SAFE (ofconn, next_ofconn, struct ofconn, node,
+                        &p->all_conns) {
+        ofconn_destroy(ofconn, p);
+    }
+
+    dpif_close(&p->dpif);
+    dpifmon_destroy(p->dpifmon);
+    PORT_ARRAY_FOR_EACH (ofport, &p->ports, port_no) {
+        ofport_free(ofport);
+    }
+    shash_destroy(&p->port_by_name);
+
+    switch_status_destroy(p->switch_status);
+    in_band_destroy(p->in_band);
+    discovery_destroy(p->discovery);
+    fail_open_destroy(p->fail_open);
+    pinsched_destroy(p->miss_sched);
+    pinsched_destroy(p->action_sched);
+    executer_destroy(p->executer);
+    netflow_destroy(p->netflow);
+
+    for (i = 0; i < p->n_listeners; i++) {
+        pvconn_close(p->listeners[i]);
+    }
+
+    free(p);
+}
+
 void
 ofproto_reconfigure(struct ofproto *p)
 {
index a9351c92975b1e043b1f47854bd1a884d631af84..a50be0de202e8e5a535dd24f7578ccc59e3bcf0b 100644 (file)
@@ -94,6 +94,7 @@ struct ofsettings {
 };
 
 struct ofproto *ofproto_create(const struct ofsettings *);
+void ofproto_destroy(struct ofproto *);
 void ofproto_reconfigure(struct ofproto *);
 void ofproto_run(struct ofproto *);
 void ofproto_wait(struct ofproto *);
index 31254fb9b3e0e343d5055f33adc899911ab846fa..09843937c28c0aee6d4df7560942e30d7507ed79 100644 (file)
@@ -257,3 +257,18 @@ pinsched_create(int rate_limit, int burst_limit, struct switch_status *ss)
     return ps;
 }
 
+void
+pinsched_destroy(struct pinsched *ps)
+{
+    if (ps) {
+        struct ofp_queue *queue;
+        unsigned int port_no;
+
+        PORT_ARRAY_FOR_EACH (queue, &ps->queues, port_no) {
+            queue_destroy(queue);
+            free(queue);
+        }
+        port_array_destroy(&ps->queues);
+        free(ps);
+    }
+}
index 76e9b0c4c474769add9fa8af1cbf5b8241584cea..237d4a2d117b38ff1fe2f1743e62fe84ea245872 100644 (file)
@@ -42,6 +42,7 @@ struct switch_status;
 typedef void pinsched_tx_cb(struct ofpbuf *, void *aux);
 struct pinsched *pinsched_create(int rate_limit, int burst_limit,
                                  struct switch_status *);
+void pinsched_destroy(struct pinsched *);
 void pinsched_send(struct pinsched *, uint16_t port_no, struct ofpbuf *,
                    pinsched_tx_cb *, void *aux);
 void pinsched_run(struct pinsched *, pinsched_tx_cb *, void *aux);
index 3f9b0f4bb1908ad66b9dfc5f36fce3d706957f76..bfe20ba27d9e2d30e52f3391f7d5ab8cb33eefac 100644 (file)
@@ -36,6 +36,7 @@
 #include <arpa/inet.h>
 #include <assert.h>
 #include <errno.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include "dynamic-string.h"
 #include "ofpbuf.h"
@@ -162,6 +163,15 @@ switch_status_create(const struct ofsettings *settings)
     return ss;
 }
 
+void
+switch_status_destroy(struct switch_status *ss)
+{
+    if (ss) {
+        free(ss->categories);
+        free(ss);
+    }
+}
+
 void
 switch_status_register_category(struct switch_status *ss,
                                 const char *category,
index f87662066940a4df007bf2f91239b8fe0dba17cc..da879be7fa9aba6c52f470dad17ec2b7c5f58a74 100644 (file)
@@ -43,6 +43,7 @@ struct ofsettings;
 struct status_reply;
 
 struct switch_status *switch_status_create(const struct ofsettings *);
+void switch_status_destroy(struct switch_status *);
 
 int switch_status_handle_request(struct switch_status *, struct rconn *,
                                  struct nicira_header *);