On Wed, May 29, 2013 at 1:23 PM, Jing Ai <ai_jing2...@hotmail.com> wrote:
> > While upgrading openvswitch, it helps to restore openflow flows before > > starting packet processing. Typically we want to restart openvswitch, > > add the openflow flows and then start packet processing. > > > > To do this, we look for the other_config:flow-restore-wait column > > in the Open_vSwitch table during startup. If set as true, we disable > > receiving packets from the datapath, expiring or flushing flows and > > running any periodic ofproto activities. This option does not prevent > > the addition and deletion of ports. Once this option is set to false, > > we return to normal processing. > > > > An upcoming commit will use this feature in Open vSwitch startup scripts. > > Will this patch leave ongoing traffic not disturbed while upgrading OVS? > Yes. That is one intent for just a "restart --save-flows=yes". The other intent is to not setup new flows till the userspace flows are restored. For force-reload-kmod (when kernel module is replaced), the intent is not to setup new flows without having all the userspace flows replaced. > > I am asking since I notice that the existing ports, which keep packet > flowing, in the fast datapath (i.e., kernel) will be garbage collected in > open_dpif_backer. > I don't think that is true. The goal is to keep the datapath's ports to be the same as seen in OVSDB. A OVS upgrade can result in either just a "restart", in which case only userspace is restarted or a 'force-reload-kmod', in which case the kernel module is replaced too (in this case there will be traffic disruption for a few seconds). In both cases the expectation is that the kernel will have the ports for the interfaces in OVSDB. If not, we will add it. Tahnks, Guru > > Best, > Jing > > > > > Bug #16086. > > Signed-off-by: Gurucharan Shetty <gshe...@nicira.com> > > --- > > ofproto/ofproto-dpif.c | 55 > +++++++++++++++++++++++++++++++++++++++++++++--- > > vswitchd/bridge.c | 11 ++++++++++ > > vswitchd/vswitch.xml | 17 +++++++++++++++ > > 3 files changed, 80 insertions(+), 3 deletions(-) > > > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > > index c4f7d25..31f04f3 100644 > > --- a/ofproto/ofproto-dpif.c > > +++ b/ofproto/ofproto-dpif.c > > @@ -72,6 +72,8 @@ COVERAGE_DEFINE(facet_suppress); > > * flow translation. */ > > #define MAX_RESUBMIT_RECURSION 64 > > > > +extern bool flow_restore_wait; > > + > > /* Number of implemented OpenFlow tables. */ > > enum { N_TABLES = 255 }; > > enum { TBL_INTERNAL = N_TABLES - 1 }; /* Used for internal hidden rules. > */ > > @@ -671,6 +673,7 @@ struct dpif_backer { > > struct tag_set revalidate_set; /* Revalidate only matching facets. */ > > > > struct hmap drop_keys; /* Set of dropped odp keys. */ > > + bool recv_set_enable; /* Enables or disables receiving packets. */ > > }; > > > > /* All existing ofproto_backer instances, indexed by ofproto->up.type. */ > > @@ -947,6 +950,21 @@ type_run(const char *type) > > push_all_stats(); > > } > > > > + /* If vswitchd started with other_config:flow_restore_wait set as > "true", > > + * and the configuration has now changed to "false", enable receiving > > + * packets from the datapath. */ > > + if (!backer->recv_set_enable && !flow_restore_wait) { > > + backer->recv_set_enable = true; > > + > > + error = dpif_recv_set(backer->dpif, backer->recv_set_enable); > > + if (error) { > > + VLOG_ERR("Failed to enable receiving packets in dpif."); > > + return error; > > + } > > + dpif_flow_flush(backer->dpif); > > + backer->need_revalidate = REV_RECONFIGURE; > > + } > > + > > if (backer->need_revalidate > > || !tag_set_is_empty(&backer->revalidate_set)) { > > struct tag_set revalidate_set = backer->revalidate_set; > > @@ -1040,7 +1058,10 @@ type_run(const char *type) > > } > > } > > > > - if (timer_expired(&backer->next_expiration)) { > > + if (!backer->recv_set_enable) { > > + /* A minimum of 1000 ms delay. */ > > + timer_set_duration(&backer->next_expiration, 1000); > > + } else if (timer_expired(&backer->next_expiration)) { > > int delay = expire(backer); > > timer_set_duration(&backer->next_expiration, delay); > > } > > @@ -1106,6 +1127,11 @@ dpif_backer_run_fast(struct dpif_backer *backer, > int max_batch) > > { > > unsigned int work; > > > > + /* If recv_set_enable is false, we should not handle upcalls. */ > > + if (!backer->recv_set_enable) { > > + return 0; > > + } > > + > > /* Handle one or more batches of upcalls, until there's nothing left to > do > > * or until we do a fixed total amount of work. > > * > > @@ -1305,9 +1331,16 @@ open_dpif_backer(const char *type, struct > dpif_backer **backerp) > > backer->need_revalidate = 0; > > simap_init(&backer->tnl_backers); > > tag_set_init(&backer->revalidate_set); > > + if (flow_restore_wait) { > > + backer->recv_set_enable = false; > > + } else { > > + backer->recv_set_enable = true; > > + } > > *backerp = backer; > > > > - dpif_flow_flush(backer->dpif); > > + if (backer->recv_set_enable) { > > + dpif_flow_flush(backer->dpif); > > + } > > > > /* Loop through the ports already on the datapath and remove any > > * that we don't need anymore. */ > > @@ -1331,7 +1364,7 @@ open_dpif_backer(const char *type, struct > dpif_backer **backerp) > > > > shash_add(&all_dpif_backers, type, backer); > > > > - error = dpif_recv_set(backer->dpif, true); > > + error = dpif_recv_set(backer->dpif, backer->recv_set_enable); > > if (error) { > > VLOG_ERR("failed to listen on datapath of type %s: %s", > > type, strerror(error)); > > @@ -1569,6 +1602,12 @@ run_fast(struct ofproto *ofproto_) > > struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); > > struct ofport_dpif *ofport; > > > > + /* Do not perform any periodic activity required by 'ofproto' while > > + * waiting for flow restore to complete. */ > > + if (flow_restore_wait) { > > + return 0; > > + } > > + > > HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) { > > port_run_fast(ofport); > > } > > @@ -1584,6 +1623,12 @@ run(struct ofproto *ofproto_) > > struct ofbundle *bundle; > > int error; > > > > + /* Do not perform any periodic activity required by 'ofproto' while > > + * waiting for flow restore to complete. */ > > + if (flow_restore_wait) { > > + return 0; > > + } > > + > > if (!clogged) { > > complete_operations(ofproto); > > } > > @@ -1658,6 +1703,10 @@ wait(struct ofproto *ofproto_) > > struct ofport_dpif *ofport; > > struct ofbundle *bundle; > > > > + if (flow_restore_wait) { > > + return; > > + } > > + > > if (!clogged && !list_is_empty(&ofproto->completions)) { > > poll_immediate_wake(); > > } > > diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c > > index e10036c..db70b77 100644 > > --- a/vswitchd/bridge.c > > +++ b/vswitchd/bridge.c > > @@ -183,6 +183,9 @@ static long long int iface_stats_timer = LLONG_MIN; > > #define OFP_PORT_ACTION_WINDOW 10 > > static bool reconfiguring = false; > > > > +/* The default value of true waits for flow restore. */ > > +bool flow_restore_wait = true; > > + > > static void add_del_bridges(const struct ovsrec_open_vswitch *); > > static void bridge_update_ofprotos(void); > > static void bridge_create(const struct ovsrec_bridge *); > > @@ -2321,6 +2324,14 @@ bridge_run(void) > > * returns immediately. */ > > bridge_init_ofproto(cfg); > > > > + /* bridge_run(), when called for the first time will always have > > + * flow_restore_wait as true. Once the value is false, we no longer > > + * need to check its value. */ > > + if (flow_restore_wait) { > > + flow_restore_wait = smap_get_bool(&cfg->other_config, > > + "flow-restore-wait", false); > > + } > > + > > /* Let each datapath type do the work that it needs to do. */ > > sset_init(&types); > > ofproto_enumerate_types(&types); > > diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml > > index 4396779..3896946 100644 > > --- a/vswitchd/vswitch.xml > > +++ b/vswitchd/vswitch.xml > > @@ -104,6 +104,23 @@ > > column or to <code>false</code> to explicitly disable it. > > </column> > > > > + <column name="other_config" key="flow-restore-wait" > > + type='{"type": "boolean"}'> > > + <p> > > + When <code>ovs-vswitchd</code> is started with this value set as > > + <code>true</code>, it will neither flush or expire previously set > > + datapath flows nor will it send and receive any packets to or from > > + the datapath. When this value is later set to <code>false</code>, > > + <code>ovs-vswitchd</code> will start receiving packets from the > > + datapath and re-setup the flows. > > + </p> > > + <p> > > + This option is only useful when used during Open vSwitch upgrades or > > + restarts and flow restoration is needed before processing any new > > + packets. > > + </p> > > + </column> > > + > > <column name="statistics" key="cpu" > > type='{"type": "integer", "minInteger": 1}'> > > <p> > > -- > > 1.7.9.5 > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev > >
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev