mirror of
https://github.com/openvswitch/ovs
synced 2025-09-04 08:15:25 +00:00
vswitchd: Add --cleanup option to the 'appctl exit' command
'appctl exit' stops the running vswitchd daemon, without releasing the datapath resources (such as bridges and ports) that vswitchd has created. This is expected when vswitchd is to be relaunched, to reduce the perturbation of exiting traffic and connections. However, when vswitchd is intended to be shutdown permanently, it is desirable not to leak datapath resources. In theory, this can be achieved by removing the corresponding configurations from OVSDB before shutting down vswitchd. However it is not always possible in practice. Sometimes it is convenient and robust for vswitchd to release all datapath resources that it has configured. Add 'appctl exit --cleanup' option for this use case. Signed-off-by: Andy Zhou <azhou@ovn.org> Acked-by: Jarno Rajahalme <jarno@ovn.org>
This commit is contained in:
1
NEWS
1
NEWS
@@ -36,6 +36,7 @@ Post-v2.7.0
|
|||||||
* The port status bit OFPPS_LIVE now reflects link aliveness.
|
* The port status bit OFPPS_LIVE now reflects link aliveness.
|
||||||
- Fedora Packaging:
|
- Fedora Packaging:
|
||||||
* OVN services are no longer restarted automatically after upgrade.
|
* OVN services are no longer restarted automatically after upgrade.
|
||||||
|
- Add --cleanup option to command 'ovs-appctl exit' (see ovs-vswitchd(8)).
|
||||||
|
|
||||||
v2.7.0 - 21 Feb 2017
|
v2.7.0 - 21 Feb 2017
|
||||||
---------------------
|
---------------------
|
||||||
|
@@ -645,7 +645,7 @@ dealloc(struct ofproto *ofproto_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_dpif_backer(struct dpif_backer *backer)
|
close_dpif_backer(struct dpif_backer *backer, bool del)
|
||||||
{
|
{
|
||||||
ovs_assert(backer->refcount > 0);
|
ovs_assert(backer->refcount > 0);
|
||||||
|
|
||||||
@@ -661,6 +661,9 @@ close_dpif_backer(struct dpif_backer *backer)
|
|||||||
shash_find_and_delete(&all_dpif_backers, backer->type);
|
shash_find_and_delete(&all_dpif_backers, backer->type);
|
||||||
free(backer->type);
|
free(backer->type);
|
||||||
free(backer->dp_version_string);
|
free(backer->dp_version_string);
|
||||||
|
if (del) {
|
||||||
|
dpif_delete(backer->dpif);
|
||||||
|
}
|
||||||
dpif_close(backer->dpif);
|
dpif_close(backer->dpif);
|
||||||
id_pool_destroy(backer->meter_ids);
|
id_pool_destroy(backer->meter_ids);
|
||||||
free(backer);
|
free(backer);
|
||||||
@@ -773,7 +776,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
|
|||||||
if (error) {
|
if (error) {
|
||||||
VLOG_ERR("failed to listen on datapath of type %s: %s",
|
VLOG_ERR("failed to listen on datapath of type %s: %s",
|
||||||
type, ovs_strerror(error));
|
type, ovs_strerror(error));
|
||||||
close_dpif_backer(backer);
|
close_dpif_backer(backer, false);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1525,7 +1528,7 @@ add_internal_flows(struct ofproto_dpif *ofproto)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destruct(struct ofproto *ofproto_)
|
destruct(struct ofproto *ofproto_, bool del)
|
||||||
{
|
{
|
||||||
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
|
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
|
||||||
struct ofproto_async_msg *am;
|
struct ofproto_async_msg *am;
|
||||||
@@ -1578,7 +1581,7 @@ destruct(struct ofproto *ofproto_)
|
|||||||
|
|
||||||
seq_destroy(ofproto->ams_seq);
|
seq_destroy(ofproto->ams_seq);
|
||||||
|
|
||||||
close_dpif_backer(ofproto->backer);
|
close_dpif_backer(ofproto->backer, del);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@@ -829,7 +829,7 @@ struct ofproto_class {
|
|||||||
*/
|
*/
|
||||||
struct ofproto *(*alloc)(void);
|
struct ofproto *(*alloc)(void);
|
||||||
int (*construct)(struct ofproto *ofproto);
|
int (*construct)(struct ofproto *ofproto);
|
||||||
void (*destruct)(struct ofproto *ofproto);
|
void (*destruct)(struct ofproto *ofproto, bool del);
|
||||||
void (*dealloc)(struct ofproto *ofproto);
|
void (*dealloc)(struct ofproto *ofproto);
|
||||||
|
|
||||||
/* Performs any periodic activity required by 'ofproto'. It should:
|
/* Performs any periodic activity required by 'ofproto'. It should:
|
||||||
|
@@ -1649,7 +1649,7 @@ ofproto_destroy(struct ofproto *p, bool del)
|
|||||||
free(usage);
|
free(usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
p->ofproto_class->destruct(p);
|
p->ofproto_class->destruct(p, del);
|
||||||
|
|
||||||
/* We should not postpone this because it involves deleting a listening
|
/* We should not postpone this because it involves deleting a listening
|
||||||
* socket which we may want to reopen soon. 'connmgr' may be used by other
|
* socket which we may want to reopen soon. 'connmgr' may be used by other
|
||||||
|
@@ -496,14 +496,14 @@ bridge_init(const char *remote)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bridge_exit(void)
|
bridge_exit(bool delete_datapath)
|
||||||
{
|
{
|
||||||
struct bridge *br, *next_br;
|
struct bridge *br, *next_br;
|
||||||
|
|
||||||
if_notifier_destroy(ifnotifier);
|
if_notifier_destroy(ifnotifier);
|
||||||
seq_destroy(ifaces_changed);
|
seq_destroy(ifaces_changed);
|
||||||
HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
|
HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
|
||||||
bridge_destroy(br, false);
|
bridge_destroy(br, delete_datapath);
|
||||||
}
|
}
|
||||||
ovsdb_idl_destroy(idl);
|
ovsdb_idl_destroy(idl);
|
||||||
}
|
}
|
||||||
|
@@ -16,10 +16,12 @@
|
|||||||
#ifndef VSWITCHD_BRIDGE_H
|
#ifndef VSWITCHD_BRIDGE_H
|
||||||
#define VSWITCHD_BRIDGE_H 1
|
#define VSWITCHD_BRIDGE_H 1
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct simap;
|
struct simap;
|
||||||
|
|
||||||
void bridge_init(const char *remote);
|
void bridge_init(const char *remote);
|
||||||
void bridge_exit(void);
|
void bridge_exit(bool delete_datapath);
|
||||||
|
|
||||||
void bridge_run(void);
|
void bridge_run(void);
|
||||||
void bridge_wait(void);
|
void bridge_wait(void);
|
||||||
|
@@ -109,8 +109,11 @@ configuration.
|
|||||||
described below. The command descriptions assume an understanding of
|
described below. The command descriptions assume an understanding of
|
||||||
how to configure Open vSwitch.
|
how to configure Open vSwitch.
|
||||||
.SS "GENERAL COMMANDS"
|
.SS "GENERAL COMMANDS"
|
||||||
.IP "\fBexit\fR"
|
.IP "\fBexit\fR \fI--cleanup\fR"
|
||||||
Causes \fBovs\-vswitchd\fR to gracefully terminate.
|
Causes \fBovs\-vswitchd\fR to gracefully terminate. If \fI--cleanup\fR
|
||||||
|
is specified, release datapath resources configured by \fBovs\-vswitchd\fR.
|
||||||
|
Otherwise, datapath flows and other resources remains undeleted.
|
||||||
|
.
|
||||||
.IP "\fBqos/show-types\fR \fIinterface\fR"
|
.IP "\fBqos/show-types\fR \fIinterface\fR"
|
||||||
Queries the interface for a list of Quality of Service types that are
|
Queries the interface for a list of Quality of Service types that are
|
||||||
configurable via Open vSwitch for the given \fIinterface\fR.
|
configurable via Open vSwitch for the given \fIinterface\fR.
|
||||||
|
@@ -60,13 +60,19 @@ static unixctl_cb_func ovs_vswitchd_exit;
|
|||||||
static char *parse_options(int argc, char *argv[], char **unixctl_path);
|
static char *parse_options(int argc, char *argv[], char **unixctl_path);
|
||||||
OVS_NO_RETURN static void usage(void);
|
OVS_NO_RETURN static void usage(void);
|
||||||
|
|
||||||
|
struct ovs_vswitchd_exit_args {
|
||||||
|
bool *exiting;
|
||||||
|
bool *cleanup;
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *unixctl_path = NULL;
|
char *unixctl_path = NULL;
|
||||||
struct unixctl_server *unixctl;
|
struct unixctl_server *unixctl;
|
||||||
char *remote;
|
char *remote;
|
||||||
bool exiting;
|
bool exiting, cleanup;
|
||||||
|
struct ovs_vswitchd_exit_args exit_args = {&exiting, &cleanup};
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
set_program_name(argv[0]);
|
set_program_name(argv[0]);
|
||||||
@@ -92,12 +98,14 @@ main(int argc, char *argv[])
|
|||||||
if (retval) {
|
if (retval) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
unixctl_command_register("exit", "", 0, 0, ovs_vswitchd_exit, &exiting);
|
unixctl_command_register("exit", "[--cleanup]", 0, 1,
|
||||||
|
ovs_vswitchd_exit, &exit_args);
|
||||||
|
|
||||||
bridge_init(remote);
|
bridge_init(remote);
|
||||||
free(remote);
|
free(remote);
|
||||||
|
|
||||||
exiting = false;
|
exiting = false;
|
||||||
|
cleanup = false;
|
||||||
while (!exiting) {
|
while (!exiting) {
|
||||||
memory_run();
|
memory_run();
|
||||||
if (memory_should_report()) {
|
if (memory_should_report()) {
|
||||||
@@ -124,7 +132,7 @@ main(int argc, char *argv[])
|
|||||||
exiting = true;
|
exiting = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bridge_exit();
|
bridge_exit(cleanup);
|
||||||
unixctl_server_destroy(unixctl);
|
unixctl_server_destroy(unixctl);
|
||||||
service_stop();
|
service_stop();
|
||||||
|
|
||||||
@@ -265,10 +273,11 @@ usage(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ovs_vswitchd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
ovs_vswitchd_exit(struct unixctl_conn *conn, int argc,
|
||||||
const char *argv[] OVS_UNUSED, void *exiting_)
|
const char *argv[], void *exit_args_)
|
||||||
{
|
{
|
||||||
bool *exiting = exiting_;
|
struct ovs_vswitchd_exit_args *exit_args = exit_args_;
|
||||||
*exiting = true;
|
*exit_args->exiting = true;
|
||||||
|
*exit_args->cleanup = argc == 2 && !strcmp(argv[1], "--cleanup");
|
||||||
unixctl_command_reply(conn, NULL);
|
unixctl_command_reply(conn, NULL);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user