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)
{
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 *);
/* 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,
* 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);
}
/* 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 (;;) {
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);
}
}
}
}
}
-static int child_fd;
-
static void
sigchld_handler(int signr UNUSED)
{
- write(child_fd, "", 1);
+ write(signal_fds[1], "", 1);
}
struct executer *
{
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. */
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);
+ }
+}
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 *);
#include <config.h>
#include "fail-open.h"
#include <inttypes.h>
+#include <stdlib.h>
#include "flow.h"
#include "mac-learning.h"
#include "ofproto.h"
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);
+ }
+}
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 *,
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. */
+ }
+}
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 *,
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);
+ }
+}
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 *,
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;
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)
{
};
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 *);
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);
+ }
+}
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);
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
+#include <stdlib.h>
#include <unistd.h>
#include "dynamic-string.h"
#include "ofpbuf.h"
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,
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 *);