> 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? 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. 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