From: Ben Pfaff Date: Tue, 3 Mar 2009 01:30:32 +0000 (-0800) Subject: secchan: Make it possible to destroy an ofproto. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=24df8eca44deaf002bbad89e687d56bd114f2b5d;p=openvswitch secchan: Make it possible to destroy an ofproto. --- diff --git a/secchan/discovery.c b/secchan/discovery.c index 42f40f14..56beed25 100644 --- a/secchan/discovery.c +++ b/secchan/discovery.c @@ -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) { diff --git a/secchan/discovery.h b/secchan/discovery.h index c955d75b..ba6d988e 100644 --- a/secchan/discovery.h +++ b/secchan/discovery.h @@ -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 *); diff --git a/secchan/executer.c b/secchan/executer.c index 5f59832c..ab7ae58c 100644 --- a/secchan/executer.c +++ b/secchan/executer.c @@ -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); + } +} diff --git a/secchan/executer.h b/secchan/executer.h index 0429a879..30bb0a28 100644 --- a/secchan/executer.h +++ b/secchan/executer.h @@ -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 *); diff --git a/secchan/fail-open.c b/secchan/fail-open.c index 605e25bd..203e0930 100644 --- a/secchan/fail-open.c +++ b/secchan/fail-open.c @@ -34,6 +34,7 @@ #include #include "fail-open.h" #include +#include #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); + } +} diff --git a/secchan/fail-open.h b/secchan/fail-open.h index f8ac32c5..cb1ac761 100644 --- a/secchan/fail-open.h +++ b/secchan/fail-open.h @@ -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 *, diff --git a/secchan/in-band.c b/secchan/in-band.c index bf5e904c..5c223e96 100644 --- a/secchan/in-band.c +++ b/secchan/in-band.c @@ -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. */ + } +} diff --git a/secchan/in-band.h b/secchan/in-band.h index 26636e2c..59516929 100644 --- a/secchan/in-band.h +++ b/secchan/in-band.h @@ -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 *, diff --git a/secchan/netflow.c b/secchan/netflow.c index c08b3d8c..7f2d320f 100644 --- a/secchan/netflow.c +++ b/secchan/netflow.c @@ -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); + } +} diff --git a/secchan/netflow.h b/secchan/netflow.h index 98dd7bcb..9c498777 100644 --- a/secchan/netflow.h +++ b/secchan/netflow.h @@ -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 *, diff --git a/secchan/ofproto.c b/secchan/ofproto.c index 00a16167..d019ad3a 100644 --- a/secchan/ofproto.c +++ b/secchan/ofproto.c @@ -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) { diff --git a/secchan/ofproto.h b/secchan/ofproto.h index a9351c92..a50be0de 100644 --- a/secchan/ofproto.h +++ b/secchan/ofproto.h @@ -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 *); diff --git a/secchan/pinsched.c b/secchan/pinsched.c index 31254fb9..09843937 100644 --- a/secchan/pinsched.c +++ b/secchan/pinsched.c @@ -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); + } +} diff --git a/secchan/pinsched.h b/secchan/pinsched.h index 76e9b0c4..237d4a2d 100644 --- a/secchan/pinsched.h +++ b/secchan/pinsched.h @@ -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); diff --git a/secchan/status.c b/secchan/status.c index 3f9b0f4b..bfe20ba2 100644 --- a/secchan/status.c +++ b/secchan/status.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #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, diff --git a/secchan/status.h b/secchan/status.h index f8766206..da879be7 100644 --- a/secchan/status.h +++ b/secchan/status.h @@ -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 *);