[ovs-dev] [PATCH] ovs-vswitchd: Preserve datapath ports across graceful shutdown.
Guru Shetty
guru at ovn.org
Thu Feb 4 20:25:48 UTC 2016
On 4 February 2016 at 09:49, Ben Pfaff <blp at ovn.org> wrote:
> Until now, asking ovs-vswitchd to shut down gracefully, e.g. with
> "ovs-appctl exit", would cause it to first remove all the ports from
> kernel-based datapaths. This has the unfortunate side effect that IP
> addresses on any removed "internal" ports are lost, even if the ports are
> added again when ovs-vswitchd is restarted. This is long-standing
> behavior, but it only became important when the OVS control scripts were
> changed to try to do graceful shutdown first instead of using a signal.
>
> This commit changes graceful shutdown so that it leaves ports in the
> datapath, fixing the problem.
>
> Fixes: 9b5422a98f8 (ovs-lib: Try to call exit before killing.)
> Signed-off-by: Ben Pfaff <blp at ovn.org>
>
Acked-by: Gurucharan Shetty <guru at ovn.org>
> ---
> ofproto/ofproto-dpif.c | 4 ++--
> ofproto/ofproto-provider.h | 28 ++++++++++++++++++++++++++--
> ofproto/ofproto.c | 12 ++++++------
> ofproto/ofproto.h | 4 ++--
> vswitchd/bridge.c | 14 +++++++-------
> 5 files changed, 43 insertions(+), 19 deletions(-)
>
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 89e06aa..2b75c76 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -1802,7 +1802,7 @@ port_construct(struct ofport *port_)
> }
>
> static void
> -port_destruct(struct ofport *port_)
> +port_destruct(struct ofport *port_, bool del)
> {
> struct ofport_dpif *port = ofport_dpif_cast(port_);
> struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
> @@ -1817,7 +1817,7 @@ port_destruct(struct ofport *port_)
>
> dp_port_name = netdev_vport_get_dpif_port(port->up.netdev, namebuf,
> sizeof namebuf);
> - if (dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
> + if (del && dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
> /* The underlying device is still there, so delete it. This
> * happens when the ofproto is being destroyed, since the caller
> * assumes that removal of attached ports will happen as part of
> diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
> index b6aac0a..004335b 100644
> --- a/ofproto/ofproto-provider.h
> +++ b/ofproto/ofproto-provider.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
> + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira,
> Inc.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -899,12 +899,36 @@ struct ofproto_class {
> * initialization, and construct and destruct ofports to reflect
> all of
> * the changes.
> *
> + * - On graceful shutdown, the base ofproto code will destruct all
> + * the ports.
> + *
> * ->port_construct() returns 0 if successful, otherwise a positive
> errno
> * value.
> + *
> + *
> + * ->port_destruct()
> + * =================
> + *
> + * ->port_destruct() takes a 'del' parameter. If the provider
> implements
> + * the datapath itself (e.g. dpif-netdev, it can ignore 'del'. On the
> + * other hand, if the provider is an interface to an external datapath
> + * (e.g. to a kernel module that implement the datapath) then 'del'
> should
> + * influence destruction behavior in the following way:
> + *
> + * - If 'del' is true, it should remove the port from the underlying
> + * implementation. This is the common case.
> + *
> + * - If 'del' is false, it should leave the port in the underlying
> + * implementation. This is used when Open vSwitch is performing a
> + * graceful shutdown and ensures that, across Open vSwitch
> restarts,
> + * the underlying ports are not removed and recreated. That
> makes an
> + * important difference for, e.g., "internal" ports that have
> + * configured IP addresses; without this distinction, the IP
> address
> + * and other configured state for the port is lost.
> */
> struct ofport *(*port_alloc)(void);
> int (*port_construct)(struct ofport *ofport);
> - void (*port_destruct)(struct ofport *ofport);
> + void (*port_destruct)(struct ofport *ofport, bool del);
> void (*port_dealloc)(struct ofport *ofport);
>
> /* Called after 'ofport->netdev' is replaced by a new netdev object.
> If
> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index bba30ae..6d21155 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -217,7 +217,7 @@ static void learned_cookies_flush(struct ofproto *,
> struct ovs_list *dead_cookie
>
> /* ofport. */
> static void ofport_destroy__(struct ofport *) OVS_EXCLUDED(ofproto_mutex);
> -static void ofport_destroy(struct ofport *);
> +static void ofport_destroy(struct ofport *, bool del);
>
> static int update_port(struct ofproto *, const char *devname);
> static int init_ports(struct ofproto *);
> @@ -1580,7 +1580,7 @@ ofproto_destroy_defer__(struct ofproto *ofproto)
> }
>
> void
> -ofproto_destroy(struct ofproto *p)
> +ofproto_destroy(struct ofproto *p, bool del)
> OVS_EXCLUDED(ofproto_mutex)
> {
> struct ofport *ofport, *next_ofport;
> @@ -1599,7 +1599,7 @@ ofproto_destroy(struct ofproto *p)
>
> ofproto_flush__(p);
> HMAP_FOR_EACH_SAFE (ofport, next_ofport, hmap_node, &p->ports) {
> - ofport_destroy(ofport);
> + ofport_destroy(ofport, del);
> }
>
> HMAP_FOR_EACH_SAFE (usage, next_usage, hmap_node, &p->ofport_usage) {
> @@ -2399,7 +2399,7 @@ ofport_remove(struct ofport *ofport)
> {
> connmgr_send_port_status(ofport->ofproto->connmgr, NULL, &ofport->pp,
> OFPPR_DELETE);
> - ofport_destroy(ofport);
> + ofport_destroy(ofport, true);
> }
>
> /* If 'ofproto' contains an ofport named 'name', removes it from
> 'ofproto' and
> @@ -2485,11 +2485,11 @@ ofport_destroy__(struct ofport *port)
> }
>
> static void
> -ofport_destroy(struct ofport *port)
> +ofport_destroy(struct ofport *port, bool del)
> {
> if (port) {
> dealloc_ofp_port(port->ofproto, port->ofp_port);
> - port->ofproto->ofproto_class->port_destruct(port);
> + port->ofproto->ofproto_class->port_destruct(port, del);
> ofport_destroy__(port);
> }
> }
> diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
> index 7504027..ebeb590 100644
> --- a/ofproto/ofproto.h
> +++ b/ofproto/ofproto.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
> + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira,
> Inc.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -239,7 +239,7 @@ void ofproto_type_wait(const char *datapath_type);
>
> int ofproto_create(const char *datapath, const char *datapath_type,
> struct ofproto **ofprotop);
> -void ofproto_destroy(struct ofproto *);
> +void ofproto_destroy(struct ofproto *, bool del);
> int ofproto_delete(const char *name, const char *type);
>
> int ofproto_run(struct ofproto *);
> diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> index f8324a2..3f3054e 100644
> --- a/vswitchd/bridge.c
> +++ b/vswitchd/bridge.c
> @@ -227,7 +227,7 @@ static bool ifaces_changed = false;
> static void add_del_bridges(const struct ovsrec_open_vswitch *);
> static void bridge_run__(void);
> static void bridge_create(const struct ovsrec_bridge *);
> -static void bridge_destroy(struct bridge *);
> +static void bridge_destroy(struct bridge *, bool del);
> static struct bridge *bridge_lookup(const char *name);
> static unixctl_cb_func bridge_unixctl_dump_flows;
> static unixctl_cb_func bridge_unixctl_reconnect;
> @@ -500,7 +500,7 @@ bridge_exit(void)
>
> if_notifier_destroy(ifnotifier);
> HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
> - bridge_destroy(br);
> + bridge_destroy(br, false);
> }
> ovsdb_idl_destroy(idl);
> }
> @@ -635,7 +635,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch
> *ovs_cfg)
> VLOG_ERR("failed to create bridge %s: %s", br->name,
> ovs_strerror(error));
> shash_destroy(&br->wanted_ports);
> - bridge_destroy(br);
> + bridge_destroy(br, true);
> } else {
> /* Trigger storing datapath version. */
> seq_change(connectivity_seq_get());
> @@ -1714,7 +1714,7 @@ add_del_bridges(const struct ovsrec_open_vswitch
> *cfg)
> br->cfg = shash_find_data(&new_br, br->name);
> if (!br->cfg || strcmp(br->type, ofproto_normalize_type(
> br->cfg->datapath_type))) {
> - bridge_destroy(br);
> + bridge_destroy(br, true);
> }
> }
>
> @@ -2910,7 +2910,7 @@ bridge_run(void)
> (long int) getpid());
>
> HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
> - bridge_destroy(br);
> + bridge_destroy(br, false);
> }
> /* Since we will not be running system_stats_run() in this process
> * with the current situation of multiple ovs-vswitchd daemons,
> @@ -3195,7 +3195,7 @@ bridge_create(const struct ovsrec_bridge *br_cfg)
> }
>
> static void
> -bridge_destroy(struct bridge *br)
> +bridge_destroy(struct bridge *br, bool del)
> {
> if (br) {
> struct mirror *mirror, *next_mirror;
> @@ -3209,7 +3209,7 @@ bridge_destroy(struct bridge *br)
> }
>
> hmap_remove(&all_bridges, &br->node);
> - ofproto_destroy(br->ofproto);
> + ofproto_destroy(br->ofproto, del);
> hmap_destroy(&br->ifaces);
> hmap_destroy(&br->ports);
> hmap_destroy(&br->iface_by_name);
> --
> 2.1.3
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
More information about the dev
mailing list