On Tue, Apr 2, 2024 at 2:47 PM Mark Michelson <mmich...@redhat.com> wrote:
> On 4/2/24 01:50, Ales Musil wrote: > > > > > > On Mon, Apr 1, 2024 at 10:36 PM Mark Michelson <mmich...@redhat.com > > <mailto:mmich...@redhat.com>> wrote: > > > > Hi Ales, > > > > I have some high-level suggestions/questions. > > > > > > Hi Mark, > > thank you for the discussion. > > > > > > 1) The units for the probe interval should be milliseconds. All other > > configurable probe intervals use milliseconds, as far as I can tell. > I > > realize the rconn API in OVS uses seconds, but all *configuration* I > > could find uses milliseconds. > > > > > > It can definitely be in milliseconds instead, it's just slightly strange > > because OvS simply doesn't have this granularity. > > I 100% agree. I don't know why the configuration options are all > milliseconds, but introducing a new probe interval that uses different > units from all the rest is confusing. > You are right, I'll update it in v2 for the sake of consistency. > > > > > > > 2) Let's say a user starts ovn-controller. They set a > > "--br-int-probe-interval" but they do not set a "--br-int-remote". > > Should we honor the configured probe interval? We don't have the same > > worries about liveness with a unix socket. Plus, ovs-vswitchd sets a > > hard-coded 60 second probe interval on its unix mgmt socket. > > > > > > I would say we should honor it, in the end it's up to the user to set it > > up correctly. I know there were some problems with probe intervals being > > set but that was due to the fact the we had hardcoded 5 seconds in > > multiple places. This option now controls all of them so it can be used > > independently of the remote connection which is a good thing IMO. > > > > > > 3) Should the default probe interval depend on the remote connection > > type? For unix, it makes sense to default to 0. But if someone > > specifies > > a tcp target but does not set a probe interval, should we default to > a > > finite interval instead? > > > > > > I'm kinda hesitant to be smart in those scenarios. The deployments might > > be different with different needs, consider for example connection via > > localhost that is a completely valid scenario or connection that doesn't > > leave the host at all (container network). In those examples it should > > be reliable enough, but in the end the user should know the best if and > > when to use the probe. > > Thanks for answering (2) and (3). I'm totally fine with your reasoning > behind those answers. > > I'll give the patch a more detailed review today. > Ack, thanks, I'll wait with v2 until then. > > > > > > > On 3/28/24 04:53, Ales Musil wrote: > > > The br-int connection is hardcoded to use unix socket, which > requires > > > for the socket to be visible for ovn-controller. This is > > achievable in > > > container by mounting the socket, but in turn the container > requires > > > additional privileges. > > > > > > Add option to ovn-controller that allows to specify remote target > for > > > br-int. This gives the user possibility to connect to br-int in > > different > > > manner than unix socket, defaulting to the unix socket when not > > specified. > > > In addition, there is an option to specify inactivity probe for > this > > > connection, disabled by default. > > > > > > Reported-at: https://issues.redhat.com/browse/FDP-243 > > <https://issues.redhat.com/browse/FDP-243> > > > Signed-off-by: Ales Musil <amu...@redhat.com > > <mailto:amu...@redhat.com>> > > > --- > > > NEWS | 6 +++ > > > controller/ofctrl.c | 10 +---- > > > controller/ofctrl.h | 5 ++- > > > controller/ovn-controller.8.xml | 12 ++++++ > > > controller/ovn-controller.c | 68 > > ++++++++++++++++++++++++++------- > > > controller/pinctrl.c | 56 ++++++--------------------- > > > controller/pinctrl.h | 6 ++- > > > controller/statctrl.c | 66 > > ++++++-------------------------- > > > controller/statctrl.h | 3 +- > > > include/ovn/features.h | 2 +- > > > lib/features.c | 35 +++++------------ > > > lib/ovn-util.c | 26 +++++++++++++ > > > lib/ovn-util.h | 4 ++ > > > lib/test-ovn-features.c | 6 +-- > > > tests/ovn-controller.at <http://ovn-controller.at> | 31 > > +++++++++++++++ > > > utilities/ovn-ctl | 10 +++++ > > > 16 files changed, 192 insertions(+), 154 deletions(-) > > > > > > diff --git a/NEWS b/NEWS > > > index 4d6ebea89..4979bb806 100644 > > > --- a/NEWS > > > +++ b/NEWS > > > @@ -12,6 +12,12 @@ Post v24.03.0 > > > flow table id. > > > "lflow-stage-to-oftable STAGE_NAME" that converts stage > > name into OpenFlow > > > table id. > > > + - Add option to ovn-controller called "--br-int-remote=REMOTE" > > that allows > > > + to specify connection method to integration bridge for > > ovn-controller, > > > + defaulting to the unix socket. > > > + - Add option to ovn-controller called > > "--br-int-probe-interval=INTERVAL" > > > + that sets probe interval for integration bridge connection, > > > + disabled by default. > > > > > > OVN v24.03.0 - 01 Mar 2024 > > > -------------------------- > > > diff --git a/controller/ofctrl.c b/controller/ofctrl.c > > > index 6ca2ea4ce..83532bc96 100644 > > > --- a/controller/ofctrl.c > > > +++ b/controller/ofctrl.c > > > @@ -772,19 +772,13 @@ ofctrl_get_mf_field_id(void) > > > * Returns 'true' if an OpenFlow reconnect happened; 'false' > > otherwise. > > > */ > > > bool > > > -ofctrl_run(const struct ovsrec_bridge *br_int, > > > +ofctrl_run(const char *conn_target, int probe_interval, > > > const struct ovsrec_open_vswitch_table *ovs_table, > > > struct shash *pending_ct_zones) > > > { > > > - char *target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), > > br_int->name); > > > bool reconnected = false; > > > > > > - if (strcmp(target, rconn_get_target(swconn))) { > > > - VLOG_INFO("%s: connecting to switch", target); > > > - rconn_connect(swconn, target, target); > > > - } > > > - free(target); > > > - > > > + ovn_update_swconn_at(swconn, conn_target, probe_interval, > > "ofctrl"); > > > rconn_run(swconn); > > > > > > if (!rconn_is_connected(swconn) || !pending_ct_zones) { > > > diff --git a/controller/ofctrl.h b/controller/ofctrl.h > > > index 502c73da6..7df0a24ea 100644 > > > --- a/controller/ofctrl.h > > > +++ b/controller/ofctrl.h > > > @@ -50,8 +50,9 @@ struct ovn_desired_flow_table { > > > /* Interface for OVN main loop. */ > > > void ofctrl_init(struct ovn_extend_table *group_table, > > > struct ovn_extend_table *meter_table); > > > -bool ofctrl_run(const struct ovsrec_bridge *br_int, > > > - const struct ovsrec_open_vswitch_table *, > > > + > > > +bool ofctrl_run(const char *conn_target, int probe_interval, > > > + const struct ovsrec_open_vswitch_table > *ovs_table, > > > struct shash *pending_ct_zones); > > > enum mf_field_id ofctrl_get_mf_field_id(void); > > > void ofctrl_put(struct ovn_desired_flow_table *lflow_table, > > > diff --git a/controller/ovn-controller.8.xml > > b/controller/ovn-controller.8.xml > > > index 5ebef048d..a86b41eea 100644 > > > --- a/controller/ovn-controller.8.xml > > > +++ b/controller/ovn-controller.8.xml > > > @@ -30,6 +30,18 @@ > > > </p> > > > > > > <h1>Options</h1> > > > + <dl> > > > + > <dt><code>--br-int-remote=<var>remote-socket</var></code></dt> > > > + <dd> > > > + Connection to the br-int management interface. > > Otherwise, the default > > > + is <code>unix:@RUNDIR > @/<var>BR_INT_NAME</var>.mgmt</code>. > > > + </dd> > > > + > > > <dt><code>--br-int-remote-probe-interval=<var>interval</var></code></dt> > > > + <dd> > > > + Probe interval in seconds, with <code>0</code> meaning > > disabled. > > > + Otherwise, the default is <code>0</code>. > > > + </dd> > > > + </dl> > > > > > > <h2>Daemon Options</h2> > > > <xi:include href="lib/daemon.xml" > > xmlns:xi="http://www.w3.org/2003/XInclude > > <http://www.w3.org/2003/XInclude>"/> > > > diff --git a/controller/ovn-controller.c > > b/controller/ovn-controller.c > > > index c9ff5967a..657574fa8 100644 > > > --- a/controller/ovn-controller.c > > > +++ b/controller/ovn-controller.c > > > @@ -122,7 +122,13 @@ static unixctl_cb_func > > debug_ignore_startup_delay; > > > #define OVS_NB_CFG_TS_NAME "ovn-nb-cfg-ts" > > > #define OVS_STARTUP_TS_NAME "ovn-startup-ts" > > > > > > -static char *parse_options(int argc, char *argv[]); > > > +struct br_int_remote { > > > + char *target; > > > + int probe_interval; > > > + bool use_unix_socket; > > > +}; > > > + > > > +static char *parse_options(int argc, char *argv[], struct > > br_int_remote *); > > > OVS_NO_RETURN static void usage(void); > > > > > > /* SSL options */ > > > @@ -5052,11 +5058,30 @@ check_northd_version(struct ovsdb_idl > > *ovs_idl, struct ovsdb_idl *ovnsb_idl, > > > return true; > > > } > > > > > > +static void > > > +br_int_remote_update(struct br_int_remote *remote, > > > + const struct ovsrec_bridge *br_int) > > > +{ > > > + if (!remote->use_unix_socket || !br_int) { > > > + return; > > > + } > > > + > > > + char *target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), > > br_int->name); > > > + if (!remote->target || strcmp(remote->target, target)) { > > > + free(remote->target); > > > + remote->target = xstrdup(target); > > > + } > > > + free(target); > > > +} > > > + > > > int > > > main(int argc, char *argv[]) > > > { > > > struct unixctl_server *unixctl; > > > struct ovn_exit_args exit_args = {0}; > > > + struct br_int_remote br_int_remote = (struct br_int_remote) { > > > + .use_unix_socket = true > > > + }; > > > int retval; > > > > > > /* Read from system-id-override file once on startup. */ > > > @@ -5065,7 +5090,7 @@ main(int argc, char *argv[]) > > > ovs_cmdl_proctitle_init(argc, argv); > > > ovn_set_program_name(argv[0]); > > > service_start(&argc, &argv); > > > - char *ovs_remote = parse_options(argc, argv); > > > + char *ovs_remote = parse_options(argc, argv, &br_int_remote); > > > fatal_ignore_sigpipe(); > > > > > > daemonize_start(true, false); > > > @@ -5666,6 +5691,11 @@ main(int argc, char *argv[]) > > > > > ovsrec_server_has_datapath_table(ovs_idl_loop.idl) > > > ? &br_int_dp > > > : NULL); > > > + br_int_remote_update(&br_int_remote, br_int); > > > + statctrl_update_swconn(br_int_remote.target, > > > + br_int_remote.probe_interval); > > > + pinctrl_update_swconn(br_int_remote.target, > > > + br_int_remote.probe_interval); > > > > > > /* Enable ACL matching for double tagged traffic. */ > > > if (ovs_idl_txn) { > > > @@ -5720,7 +5750,8 @@ main(int argc, char *argv[]) > > > if (ovs_idl_txn > > > && ovs_feature_support_run(br_int_dp ? > > > > > &br_int_dp->capabilities : NULL, > > > - br_int ? br_int->name > > : NULL)) { > > > + br_int_remote.target, > > > + > > br_int_remote.probe_interval)) { > > > VLOG_INFO("OVS feature set changed, force > > recompute."); > > > engine_set_force_recompute(true); > > > if (ovs_feature_set_discovered()) { > > > @@ -5738,7 +5769,8 @@ main(int argc, char *argv[]) > > > > > > if (br_int) { > > > ct_zones_data = engine_get_data(&en_ct_zones); > > > - if (ofctrl_run(br_int, ovs_table, > > > + if (ofctrl_run(br_int_remote.target, > > > + br_int_remote.probe_interval, > > ovs_table, > > > ct_zones_data ? > > &ct_zones_data->pending > > > : NULL)) { > > > static struct vlog_rate_limit rl > > > @@ -5855,7 +5887,7 @@ main(int argc, char *argv[]) > > > } > > > > stopwatch_start(PINCTRL_RUN_STOPWATCH_NAME, > > > time_msec()); > > > - pinctrl_update(ovnsb_idl_loop.idl, > > br_int->name); > > > + pinctrl_update(ovnsb_idl_loop.idl); > > > pinctrl_run(ovnsb_idl_txn, > > > > sbrec_datapath_binding_by_key, > > > > sbrec_port_binding_by_datapath, > > > @@ -5909,7 +5941,6 @@ main(int argc, char *argv[]) > > > } > > > > > > if (mac_cache_data) { > > > - statctrl_update(br_int->name); > > > statctrl_run(ovnsb_idl_txn, > > mac_cache_data); > > > } > > > > > > @@ -6030,13 +6061,6 @@ main(int argc, char *argv[]) > > > binding_wait(); > > > } > > > > > > - if (!northd_version_match && br_int) { > > > - /* Set the integration bridge name to pinctrl so > > that the pinctrl > > > - * thread can handle any packet-ins when we are not > > processing > > > - * any DB updates due to version mismatch. */ > > > - pinctrl_set_br_int_name(br_int->name); > > > - } > > > - > > > unixctl_server_run(unixctl); > > > > > > unixctl_server_wait(unixctl); > > > @@ -6169,6 +6193,7 @@ loop_done: > > > ovsdb_idl_loop_destroy(&ovnsb_idl_loop); > > > > > > ovs_feature_support_destroy(); > > > + free(br_int_remote.target); > > > free(ovs_remote); > > > free(file_system_id); > > > free(cli_system_id); > > > @@ -6181,7 +6206,7 @@ loop_done: > > > } > > > > > > static char * > > > -parse_options(int argc, char *argv[]) > > > +parse_options(int argc, char *argv[], struct br_int_remote > > *br_int_remote) > > > { > > > enum { > > > OPT_PEER_CA_CERT = UCHAR_MAX + 1, > > > @@ -6190,6 +6215,8 @@ parse_options(int argc, char *argv[]) > > > OVN_DAEMON_OPTION_ENUMS, > > > SSL_OPTION_ENUMS, > > > OPT_ENABLE_DUMMY_VIF_PLUG, > > > + BR_INT_REMOTE, > > > + BR_INT_PROBE_INTERVAL, > > > }; > > > > > > static struct option long_options[] = { > > > @@ -6203,6 +6230,9 @@ parse_options(int argc, char *argv[]) > > > {"chassis", required_argument, NULL, 'n'}, > > > {"enable-dummy-vif-plug", no_argument, NULL, > > > OPT_ENABLE_DUMMY_VIF_PLUG}, > > > + {"br-int-remote", required_argument, NULL, > BR_INT_REMOTE}, > > > + {"br-int-probe-interval", required_argument, NULL, > > > + BR_INT_PROBE_INTERVAL}, > > > {NULL, 0, NULL, 0} > > > }; > > > char *short_options = > > ovs_cmdl_long_options_to_short_options(long_options); > > > @@ -6264,6 +6294,16 @@ parse_options(int argc, char *argv[]) > > > cli_system_id = xstrdup(optarg); > > > break; > > > > > > + case BR_INT_REMOTE: > > > + free(br_int_remote->target); > > > + br_int_remote->target = xstrdup(optarg); > > > + br_int_remote->use_unix_socket = false; > > > + break; > > > + > > > + case BR_INT_PROBE_INTERVAL: > > > + str_to_int(optarg, 10, > &br_int_remote->probe_interval); > > > + break; > > > + > > > case '?': > > > exit(EXIT_FAILURE); > > > > > > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > > > index 2d3595cd2..27c47d02b 100644 > > > --- a/controller/pinctrl.c > > > +++ b/controller/pinctrl.c > > > @@ -173,7 +173,8 @@ static bool garp_rarp_continuous; > > > static void *pinctrl_handler(void *arg); > > > > > > struct pinctrl { > > > - char *br_int_name; > > > + /* OpenFlow connection to the switch. */ > > > + struct rconn *swconn; > > > pthread_t pinctrl_thread; > > > /* Latch to destroy the 'pinctrl_thread' */ > > > struct latch pinctrl_thread_exit; > > > @@ -563,7 +564,7 @@ pinctrl_init(void) > > > init_svc_monitors(); > > > bfd_monitor_init(); > > > init_fdb_entries(); > > > - pinctrl.br_int_name = NULL; > > > + pinctrl.swconn = rconn_create(0, 0, DSCP_DEFAULT, 1 << > > OFP15_VERSION); > > > pinctrl.mac_binding_can_timestamp = false; > > > pinctrl_handler_seq = seq_create(); > > > pinctrl_main_seq = seq_create(); > > > @@ -3537,30 +3538,13 @@ notify_pinctrl_main(void) > > > seq_change(pinctrl_main_seq); > > > } > > > > > > -static void > > > -pinctrl_rconn_setup(struct rconn *swconn, const char > *br_int_name) > > > - OVS_REQUIRES(pinctrl_mutex) > > > -{ > > > - if (br_int_name) { > > > - char *target = xasprintf("unix:%s/%s.mgmt", > > ovs_rundir(), br_int_name); > > > - > > > - if (strcmp(target, rconn_get_target(swconn))) { > > > - VLOG_INFO("%s: connecting to switch", target); > > > - rconn_connect(swconn, target, target); > > > - } > > > - free(target); > > > - } else { > > > - rconn_disconnect(swconn); > > > - } > > > -} > > > - > > > /* pinctrl_handler pthread function. */ > > > static void * > > > pinctrl_handler(void *arg_) > > > { > > > struct pinctrl *pctrl = arg_; > > > /* OpenFlow connection to the switch. */ > > > - struct rconn *swconn; > > > + struct rconn *swconn = pctrl->swconn; > > > /* Last seen sequence number for 'swconn'. When this > > differs from > > > * rconn_get_connection_seqno(rconn), 'swconn' has > > reconnected. */ > > > unsigned int conn_seq_no = 0; > > > @@ -3576,13 +3560,10 @@ pinctrl_handler(void *arg_) > > > static long long int svc_monitors_next_run_time = LLONG_MAX; > > > static long long int send_prefixd_time = LLONG_MAX; > > > > > > - swconn = rconn_create(0, 0, DSCP_DEFAULT, 1 << > OFP15_VERSION); > > > - > > > while (!latch_is_set(&pctrl->pinctrl_thread_exit)) { > > > long long int bfd_time = LLONG_MAX; > > > > > > ovs_mutex_lock(&pinctrl_mutex); > > > - pinctrl_rconn_setup(swconn, pctrl->br_int_name); > > > ip_mcast_snoop_run(); > > > ovs_mutex_unlock(&pinctrl_mutex); > > > > > > @@ -3640,37 +3621,24 @@ pinctrl_handler(void *arg_) > > > poll_block(); > > > } > > > > > > - rconn_destroy(swconn); > > > return NULL; > > > } > > > > > > -static void > > > -pinctrl_set_br_int_name_(const char *br_int_name) > > > - OVS_REQUIRES(pinctrl_mutex) > > > +void > > > +pinctrl_update_swconn(const char *target, int probe_interval) > > > { > > > - if (br_int_name && (!pinctrl.br_int_name || > > strcmp(pinctrl.br_int_name, > > > - > > br_int_name))) { > > > - free(pinctrl.br_int_name); > > > - pinctrl.br_int_name = xstrdup(br_int_name); > > > - /* Notify pinctrl_handler that integration bridge is > > > - * set/changed. */ > > > + if (ovn_update_swconn_at(pinctrl.swconn, target, > > > + probe_interval, "pinctrl")) { > > > + /* Notify pinctrl_handler that integration bridge > > > + * target is set/changed. */ > > > notify_pinctrl_handler(); > > > } > > > } > > > > > > void > > > -pinctrl_set_br_int_name(const char *br_int_name) > > > -{ > > > - ovs_mutex_lock(&pinctrl_mutex); > > > - pinctrl_set_br_int_name_(br_int_name); > > > - ovs_mutex_unlock(&pinctrl_mutex); > > > -} > > > - > > > -void > > > -pinctrl_update(const struct ovsdb_idl *idl, const char > *br_int_name) > > > +pinctrl_update(const struct ovsdb_idl *idl) > > > { > > > ovs_mutex_lock(&pinctrl_mutex); > > > - pinctrl_set_br_int_name_(br_int_name); > > > > > > bool can_mb_timestamp = > > > > sbrec_server_has_mac_binding_table_col_timestamp(idl); > > > @@ -4292,7 +4260,7 @@ pinctrl_destroy(void) > > > latch_set(&pinctrl.pinctrl_thread_exit); > > > pthread_join(pinctrl.pinctrl_thread, NULL); > > > latch_destroy(&pinctrl.pinctrl_thread_exit); > > > - free(pinctrl.br_int_name); > > > + rconn_destroy(pinctrl.swconn); > > > destroy_send_garps_rarps(); > > > destroy_ipv6_ras(); > > > destroy_ipv6_prefixd(); > > > diff --git a/controller/pinctrl.h b/controller/pinctrl.h > > > index 23343f097..3462b670c 100644 > > > --- a/controller/pinctrl.h > > > +++ b/controller/pinctrl.h > > > @@ -62,8 +62,10 @@ void pinctrl_run(struct ovsdb_idl_txn > > *ovnsb_idl_txn, > > > const struct ovsrec_open_vswitch_table > > *ovs_table); > > > void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn); > > > void pinctrl_destroy(void); > > > -void pinctrl_set_br_int_name(const char *br_int_name); > > > -void pinctrl_update(const struct ovsdb_idl *idl, const char > > *br_int_name); > > > + > > > +void pinctrl_update_swconn(const char *target, int > probe_interval); > > > + > > > +void pinctrl_update(const struct ovsdb_idl *idl); > > > > > > struct activated_port { > > > uint32_t dp_key; > > > diff --git a/controller/statctrl.c b/controller/statctrl.c > > > index 8cce97df8..6e6d7d799 100644 > > > --- a/controller/statctrl.c > > > +++ b/controller/statctrl.c > > > @@ -80,7 +80,8 @@ struct stats_node { > > > }; > > > > > > struct statctrl_ctx { > > > - char *br_int; > > > + /* OpenFlow connection to the switch. */ > > > + struct rconn *swconn; > > > > > > pthread_t thread; > > > struct latch exit_latch; > > > @@ -95,8 +96,6 @@ static struct statctrl_ctx statctrl_ctx; > > > static struct ovs_mutex mutex; > > > > > > static void *statctrl_thread_handler(void *arg); > > > -static void statctrl_rconn_setup(struct rconn *swconn, char > > *conn_target) > > > - OVS_REQUIRES(mutex); > > > static void statctrl_handle_rconn_msg(struct rconn *swconn, > > > struct statctrl_ctx *ctx, > > > struct ofpbuf *msg); > > > @@ -109,8 +108,6 @@ static void statctrl_send_request(struct > > rconn *swconn, > > > struct statctrl_ctx *ctx) > > > OVS_REQUIRES(mutex); > > > static void statctrl_notify_main_thread(struct statctrl_ctx > *ctx); > > > -static void statctrl_set_conn_target(const char *br_int_name) > > > - OVS_REQUIRES(mutex); > > > static void statctrl_wait_next_request(struct statctrl_ctx *ctx) > > > OVS_REQUIRES(mutex); > > > static bool statctrl_update_next_request_timestamp(struct > > stats_node *node, > > > @@ -121,7 +118,7 @@ static bool > > statctrl_update_next_request_timestamp(struct stats_node *node, > > > void > > > statctrl_init(void) > > > { > > > - statctrl_ctx.br_int = NULL; > > > + statctrl_ctx.swconn = rconn_create(0, 0, DSCP_DEFAULT, 1 << > > OFP15_VERSION); > > > latch_init(&statctrl_ctx.exit_latch); > > > ovs_mutex_init(&mutex); > > > statctrl_ctx.thread_seq = seq_create(); > > > @@ -185,11 +182,14 @@ statctrl_run(struct ovsdb_idl_txn > > *ovnsb_idl_txn, > > > } > > > > > > void > > > -statctrl_update(const char *br_int_name) > > > +statctrl_update_swconn(const char *target, int probe_interval) > > > { > > > - ovs_mutex_lock(&mutex); > > > - statctrl_set_conn_target(br_int_name); > > > - ovs_mutex_unlock(&mutex); > > > + if (ovn_update_swconn_at(statctrl_ctx.swconn, target, > > > + probe_interval, "statctrl")) { > > > + /* Notify statctrl thread that integration bridge > > > + * target is set/changed. */ > > > + seq_change(statctrl_ctx.thread_seq); > > > + } > > > } > > > > > > void > > > @@ -217,7 +217,7 @@ statctrl_destroy(void) > > > latch_set(&statctrl_ctx.exit_latch); > > > pthread_join(statctrl_ctx.thread, NULL); > > > latch_destroy(&statctrl_ctx.exit_latch); > > > - free(statctrl_ctx.br_int); > > > + rconn_destroy(statctrl_ctx.swconn); > > > seq_destroy(statctrl_ctx.thread_seq); > > > seq_destroy(statctrl_ctx.main_seq); > > > > > > @@ -233,14 +233,9 @@ statctrl_thread_handler(void *arg) > > > struct statctrl_ctx *ctx = arg; > > > > > > /* OpenFlow connection to the switch. */ > > > - struct rconn *swconn = rconn_create(0, 0, DSCP_DEFAULT, > > > - 1 << OFP15_VERSION); > > > + struct rconn *swconn = ctx->swconn; > > > > > > while (!latch_is_set(&ctx->exit_latch)) { > > > - ovs_mutex_lock(&mutex); > > > - statctrl_rconn_setup(swconn, ctx->br_int); > > > - ovs_mutex_unlock(&mutex); > > > - > > > rconn_run(swconn); > > > uint64_t new_seq = seq_read(ctx->thread_seq); > > > > > > @@ -273,29 +268,9 @@ statctrl_thread_handler(void *arg) > > > poll_block(); > > > } > > > > > > - rconn_destroy(swconn); > > > return NULL; > > > } > > > > > > -static void > > > -statctrl_rconn_setup(struct rconn *swconn, char *br_int) > > > - OVS_REQUIRES(mutex) > > > -{ > > > - if (!br_int) { > > > - rconn_disconnect(swconn); > > > - return; > > > - } > > > - > > > - char *conn_target = xasprintf("unix:%s/%s.mgmt", > > ovs_rundir(), br_int); > > > - > > > - if (strcmp(conn_target, rconn_get_target(swconn))) { > > > - VLOG_INFO("%s: connecting to switch", conn_target); > > > - rconn_connect(swconn, conn_target, conn_target); > > > - } > > > - > > > - free(conn_target); > > > -} > > > - > > > static void > > > statctrl_handle_rconn_msg(struct rconn *swconn, struct > > statctrl_ctx *ctx, > > > struct ofpbuf *msg) > > > @@ -400,23 +375,6 @@ statctrl_notify_main_thread(struct > > statctrl_ctx *ctx) > > > } > > > } > > > > > > -static void > > > -statctrl_set_conn_target(const char *br_int_name) > > > - OVS_REQUIRES(mutex) > > > -{ > > > - if (!br_int_name) { > > > - return; > > > - } > > > - > > > - > > > - if (!statctrl_ctx.br_int || strcmp(statctrl_ctx.br_int, > > br_int_name)) { > > > - free(statctrl_ctx.br_int); > > > - statctrl_ctx.br_int = xstrdup(br_int_name); > > > - /* Notify statctrl thread that integration bridge is > > set/changed. */ > > > - seq_change(statctrl_ctx.thread_seq); > > > - } > > > -} > > > - > > > static void > > > statctrl_wait_next_request(struct statctrl_ctx *ctx) > > > OVS_REQUIRES(mutex) > > > diff --git a/controller/statctrl.h b/controller/statctrl.h > > > index c5cede353..026ff387f 100644 > > > --- a/controller/statctrl.h > > > +++ b/controller/statctrl.h > > > @@ -21,7 +21,8 @@ > > > void statctrl_init(void); > > > void statctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > > > struct mac_cache_data *mac_cache_data); > > > -void statctrl_update(const char *br_int_name); > > > + > > > +void statctrl_update_swconn(const char *target, int > probe_interval); > > > void statctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn); > > > void statctrl_destroy(void); > > > > > > diff --git a/include/ovn/features.h b/include/ovn/features.h > > > index 08f1d8288..9e7c88b2a 100644 > > > --- a/include/ovn/features.h > > > +++ b/include/ovn/features.h > > > @@ -49,7 +49,7 @@ enum ovs_feature_value { > > > void ovs_feature_support_destroy(void); > > > bool ovs_feature_is_supported(enum ovs_feature_value feature); > > > bool ovs_feature_support_run(const struct smap > *ovs_capabilities, > > > - const char *br_name); > > > + const char *conn_target, int > > probe_interval); > > > bool ovs_feature_set_discovered(void); > > > uint32_t ovs_feature_max_meters_get(void); > > > uint32_t ovs_feature_max_select_groups_get(void); > > > diff --git a/lib/features.c b/lib/features.c > > > index b04437235..607e4bd31 100644 > > > --- a/lib/features.c > > > +++ b/lib/features.c > > > @@ -29,8 +29,10 @@ > > > #include "openvswitch/ofp-meter.h" > > > #include "openvswitch/ofp-group.h" > > > #include "openvswitch/ofp-util.h" > > > +#include "openvswitch/rconn.h" > > > #include "ovn/features.h" > > > #include "controller/ofctrl.h" > > > +#include "ovn-util.h" > > > > > > VLOG_DEFINE_THIS_MODULE(features); > > > > > > @@ -120,34 +122,12 @@ ovs_feature_is_supported(enum > > ovs_feature_value feature) > > > return supported_ovs_features & feature; > > > } > > > > > > -static void > > > -ovs_feature_rconn_setup(const char *br_name) > > > -{ > > > - if (!swconn) { > > > - swconn = rconn_create(0, 0, DSCP_DEFAULT, 1 << > > OFP15_VERSION); > > > - } > > > - > > > - if (!rconn_is_connected(swconn)) { > > > - char *target = xasprintf("unix:%s/%s.mgmt", > > ovs_rundir(), br_name); > > > - if (strcmp(target, rconn_get_target(swconn))) { > > > - VLOG_INFO("%s: connecting to switch", target); > > > - rconn_connect(swconn, target, target); > > > - } > > > - free(target); > > > - } > > > -} > > > > > > static bool > > > -ovs_feature_get_openflow_cap(const char *br_name) > > > +ovs_feature_get_openflow_cap(void) > > > { > > > struct ofpbuf *msg; > > > > > > - if (!br_name) { > > > - return false; > > > - } > > > - > > > - ovs_feature_rconn_setup(br_name); > > > - > > > rconn_run(swconn); > > > if (!rconn_is_connected(swconn)) { > > > rconn_run_wait(swconn); > > > @@ -231,7 +211,7 @@ ovs_feature_support_destroy(void) > > > /* Returns 'true' if the set of tracked OVS features has been > > updated. */ > > > bool > > > ovs_feature_support_run(const struct smap *ovs_capabilities, > > > - const char *br_name) > > > + const char *conn_target, int > probe_interval) > > > { > > > static struct smap empty_caps = > SMAP_INITIALIZER(&empty_caps); > > > bool updated = false; > > > @@ -240,7 +220,12 @@ ovs_feature_support_run(const struct smap > > *ovs_capabilities, > > > ovs_capabilities = &empty_caps; > > > } > > > > > > - if (ovs_feature_get_openflow_cap(br_name)) { > > > + if (!swconn) { > > > + swconn = rconn_create(0, 0, DSCP_DEFAULT, 1 << > > OFP15_VERSION); > > > + } > > > + ovn_update_swconn_at(swconn, conn_target, probe_interval, > > "features"); > > > + > > > + if (ovs_feature_get_openflow_cap()) { > > > updated = true; > > > } > > > > > > diff --git a/lib/ovn-util.c b/lib/ovn-util.c > > > index ee5cbcdc3..4f50606c0 100644 > > > --- a/lib/ovn-util.c > > > +++ b/lib/ovn-util.c > > > @@ -22,6 +22,7 @@ > > > #include "daemon.h" > > > #include "include/ovn/actions.h" > > > #include "openvswitch/ofp-parse.h" > > > +#include "openvswitch/rconn.h" > > > #include "openvswitch/vlog.h" > > > #include "lib/vswitch-idl.h" > > > #include "ovn-dirs.h" > > > @@ -1284,3 +1285,28 @@ ovn_exit_args_finish(struct ovn_exit_args > > *exit_args) > > > } > > > free(exit_args->conns); > > > } > > > + > > > +bool > > > +ovn_update_swconn_at(struct rconn *swconn, const char *target, > > > + int probe_interval, const char *where) > > > +{ > > > + if (!target) { > > > + rconn_disconnect(swconn); > > > + return true; > > > + } > > > + > > > + bool notify = false; > > > + > > > + if (strcmp(target, rconn_get_target(swconn))) { > > > + VLOG_INFO("%s: connecting to switch: \"%s\"", where, > > target); > > > + rconn_connect(swconn, target, target); > > > + notify = true; > > > + } > > > + > > > + if (probe_interval != rconn_get_probe_interval(swconn)) { > > > + rconn_set_probe_interval(swconn, probe_interval); > > > + notify = true; > > > + } > > > + > > > + return notify; > > > +} > > > diff --git a/lib/ovn-util.h b/lib/ovn-util.h > > > index 042e6bf82..f75b821b6 100644 > > > --- a/lib/ovn-util.h > > > +++ b/lib/ovn-util.h > > > @@ -48,6 +48,7 @@ struct smap; > > > struct svec; > > > struct uuid; > > > struct unixctl_conn; > > > +struct rconn; > > > > > > struct ipv4_netaddr { > > > ovs_be32 addr; /* 192.168.10.123 */ > > > @@ -477,4 +478,7 @@ void ovn_exit_command_callback(struct > > unixctl_conn *conn, int argc, > > > const char *argv[], void > > *exit_args_); > > > void ovn_exit_args_finish(struct ovn_exit_args *exit_args); > > > > > > +bool ovn_update_swconn_at(struct rconn *swconn, const char > *target, > > > + int probe_interval, const char *where); > > > + > > > #endif /* OVN_UTIL_H */ > > > diff --git a/lib/test-ovn-features.c b/lib/test-ovn-features.c > > > index aabc547e6..cddeae779 100644 > > > --- a/lib/test-ovn-features.c > > > +++ b/lib/test-ovn-features.c > > > @@ -26,15 +26,15 @@ test_ovn_features(struct ovs_cmdl_context > > *ctx OVS_UNUSED) > > > struct smap features = SMAP_INITIALIZER(&features); > > > > > > smap_add(&features, "ct_zero_snat", "false"); > > > - ovs_assert(!ovs_feature_support_run(&features, NULL)); > > > + ovs_assert(!ovs_feature_support_run(&features, NULL, 0)); > > > > > ovs_assert(!ovs_feature_is_supported(OVS_CT_ZERO_SNAT_SUPPORT)); > > > > > > smap_replace(&features, "ct_zero_snat", "true"); > > > - ovs_assert(ovs_feature_support_run(&features, NULL)); > > > + ovs_assert(ovs_feature_support_run(&features, NULL, 0)); > > > > ovs_assert(ovs_feature_is_supported(OVS_CT_ZERO_SNAT_SUPPORT)); > > > > > > smap_add(&features, "unknown_feature", "true"); > > > - ovs_assert(!ovs_feature_support_run(&features, NULL)); > > > + ovs_assert(!ovs_feature_support_run(&features, NULL, 0)); > > > > > > smap_destroy(&features); > > > } > > > diff --git a/tests/ovn-controller.at <http://ovn-controller.at> > > b/tests/ovn-controller.at <http://ovn-controller.at> > > > index fdcc5aab2..e15cd02b0 100644 > > > --- a/tests/ovn-controller.at <http://ovn-controller.at> > > > +++ b/tests/ovn-controller.at <http://ovn-controller.at> > > > @@ -2874,3 +2874,34 @@ AT_CHECK([test x"$port_uuid"=$(ovs-vsctl > > get port $fakech_tunnel _uuid)]) > > > OVN_CLEANUP([hv1]) > > > AT_CLEANUP > > > ]) > > > + > > > +AT_SETUP([ovn-controller - br-int remote]) > > > +AT_KEYWORDS([ovn]) > > > +ovn_start > > > + > > > +net_add n1 > > > +sim_add hv1 > > > +ovs-vsctl add-br br-phys > > > +ovn_attach n1 br-phys 192.168.0.20 > > > +ovs-vsctl -- add-port br-int vif1 -- \ > > > + set interface vif1 external-ids:iface-id=vif1 > > > + > > > +OVS_APP_EXIT_AND_WAIT([ovn-controller]) > > > + > > > +# Set the br-int remote and wait for the connection > > > +ovs-vsctl set-controller br-int ptcp:1234 > > > +start_daemon ovn-controller --br-int-remote="tcp:127.0.0.1:1234 > > <http://127.0.0.1:1234>" --br-int-probe-interval=5 > > > + > > > +OVS_WAIT_UNTIL([test $(grep -c 'connecting to switch: > > "tcp:127.0.0.1:1234 <http://127.0.0.1:1234>"' > > hv1/ovn-controller.log) = 4]) > > > +OVS_WAIT_UNTIL([test $(grep -c 'tcp:127.0.0.1:1234 > > <http://127.0.0.1:1234>: connected' hv1/ovn-controller.log) = 4]) > > > + > > > +ovn-nbctl ls-add sw0 > > > + > > > +check ovn-nbctl lsp-add sw0 vif1 > > > +check ovn-nbctl lsp-set-addresses vif1 "00:00:00:00:00:01 > > 192.168.0.10 1000::10" > > > + > > > +wait_for_ports_up > > > +ovn-nbctl --wait=hv sync > > > + > > > +OVN_CLEANUP([hv1]) > > > +AT_CLEANUP > > > diff --git a/utilities/ovn-ctl b/utilities/ovn-ctl > > > index 700efe35a..ce83889d8 100755 > > > --- a/utilities/ovn-ctl > > > +++ b/utilities/ovn-ctl > > > @@ -617,6 +617,12 @@ start_controller () { > > > if test X"$OVN_CONTROLLER_SSL_CIPHERS" != X; then > > > set "$@" --ssl-ciphers=$OVN_CONTROLLER_SSL_CIPHERS > > > fi > > > + if test X"$OVN_CONTROLLER_BR_INT_REMOTE" != X; then > > > + set "$@" --br-int-remote=$OVN_CONTROLLER_BR_INT_REMOTE > > > + fi > > > + if test "$OVN_CONTROLLER_BR_INT_PROBE_INTERVAL" != 0; then > > > + set "$@" > > --br-int-probe-interval=$OVN_CONTROLLER_BR_INT_PROBE_INTERVAL > > > + fi > > > > > > [ "$OVN_USER" != "" ] && set "$@" --user "$OVN_USER" > > > > > > @@ -831,6 +837,8 @@ set_defaults () { > > > OVN_USER= > > > > > > OVN_CONTROLLER_LOG="-vconsole:emer -vsyslog:err -vfile:info" > > > + OVN_CONTROLLER_BR_INT_REMOTE="" > > > + OVN_CONTROLLER_BR_INT_PROBE_INTERVAL=0 > > > OVN_NORTHD_LOG="-vconsole:emer -vsyslog:err -vfile:info" > > > OVN_NORTHD_LOGFILE="" > > > OVN_NORTHD_N_THREADS=1 > > > @@ -1041,6 +1049,8 @@ Options: > > > --ovn-controller-ssl-bootstrap-ca-cert=CERT Bootstrapped OVN > > Southbound SSL CA certificate file > > > --ovn-controller-ssl-protocols=PROTOCOLS OVN Southbound SSL > > protocols > > > --ovn-controller-ssl-ciphers=CIPHERS OVN Southbound SSL > > cipher list > > > + --ovn-controller-br-int-remote=REMOTE Active or passive > > connection to br-int > > > + --ovn-controller-br-int-probe-interval=INTERVAL Probe interval > > in seconds for the br-int connection > > > --ovn-nb-db-ssl-key=KEY OVN Northbound DB SSL private key file > > > --ovn-nb-db-ssl-cert=CERT OVN Northbound DB SSL certificate > file > > > --ovn-nb-db-ssl-ca-cert=CERT OVN Northbound DB SSL CA > > certificate file > > > > > > Thanks, > > Ales > > -- > > > > Ales Musil > > > > Senior Software Engineer - OVN Core > > > > Red Hat EMEA <https://www.redhat.com> > > > > amu...@redhat.com <mailto:amu...@redhat.com> > > > > <https://red.ht/sig> > > > > Thanks, Ales -- Ales Musil Senior Software Engineer - OVN Core Red Hat EMEA <https://www.redhat.com> amu...@redhat.com <https://red.ht/sig> _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev