On Tue, Nov 2, 2021 at 4:29 AM Frode Nordahl <[email protected]> wrote: > > When OVN is linked with an appropriate VIF plug provider, > CMS can request an OVN controller to plug individual lports into > the Open vSwitch instance it manages. > > The port and interface record will be maintained throughout the > lifetime of the lport and it will be removed on release of lport. > > Signed-off-by: Frode Nordahl <[email protected]> > --- > controller/ovn-controller.c | 61 +++++++++++++++++- > ovn-nb.xml | 21 +++++++ > tests/ovn-macros.at | 2 +- > tests/ovn.at | 121 ++++++++++++++++++++++++++++++++++++ > 4 files changed, 203 insertions(+), 2 deletions(-) > > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > index dd09d57e2..b4d4636d8 100644 > --- a/controller/ovn-controller.c > +++ b/controller/ovn-controller.c > @@ -106,6 +106,7 @@ static unixctl_cb_func debug_delay_nb_cfg_report; > #define IF_STATUS_MGR_UPDATE_STOPWATCH_NAME "if-status-mgr-update" > #define OFCTRL_SEQNO_RUN_STOPWATCH_NAME "ofctrl-seqno-run" > #define BFD_RUN_STOPWATCH_NAME "bfd-run" > +#define VIF_PLUG_RUN_STOPWATCH_NAME "vif-plug-run" > > #define OVS_NB_CFG_NAME "ovn-nb-cfg" > #define OVS_NB_CFG_TS_NAME "ovn-nb-cfg-ts" > @@ -937,6 +938,7 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) > binding_register_ovs_idl(ovs_idl); > bfd_register_ovs_idl(ovs_idl); > physical_register_ovs_idl(ovs_idl); > + vif_plug_register_ovs_idl(ovs_idl); > } > > #define SB_NODES \ > @@ -3205,6 +3207,7 @@ main(int argc, char *argv[]) > stopwatch_create(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME, SW_MS); > stopwatch_create(OFCTRL_SEQNO_RUN_STOPWATCH_NAME, SW_MS); > stopwatch_create(BFD_RUN_STOPWATCH_NAME, SW_MS); > + stopwatch_create(VIF_PLUG_RUN_STOPWATCH_NAME, SW_MS); > > /* Define inc-proc-engine nodes. */ > ENGINE_NODE_CUSTOM_WITH_CLEAR_TRACK_DATA(ct_zones, "ct_zones"); > @@ -3440,6 +3443,11 @@ main(int argc, char *argv[]) > }; > struct if_status_mgr *if_mgr = ctrl_engine_ctx.if_mgr; > > + struct shash vif_plug_deleted_iface_ids = > + SHASH_INITIALIZER(&vif_plug_deleted_iface_ids); > + struct shash vif_plug_changed_iface_ids = > + SHASH_INITIALIZER(&vif_plug_changed_iface_ids); > + > char *ovn_version = ovn_get_internal_version(); > VLOG_INFO("OVN internal version is : [%s]", ovn_version); > > @@ -3650,6 +3658,37 @@ main(int argc, char *argv[]) > ovsrec_port_table_get(ovs_idl_loop.idl), > br_int, chassis, &runtime_data->local_datapaths); > stopwatch_stop(PATCH_RUN_STOPWATCH_NAME, time_msec()); > + if (vif_plug_provider_has_providers() && ovs_idl_txn) { > + struct vif_plug_ctx_in vif_plug_ctx_in = { > + .ovs_idl_txn = ovs_idl_txn, > + .sbrec_port_binding_by_name = > + sbrec_port_binding_by_name, > + .sbrec_port_binding_by_requested_chassis = > + sbrec_port_binding_by_requested_chassis, > + .ovsrec_port_by_interfaces = > + ovsrec_port_by_interfaces, > + .ovs_table = ovs_table, > + .br_int = br_int, > + .iface_table = > + ovsrec_interface_table_get( > + ovs_idl_loop.idl), > + .chassis_rec = chassis, > + .local_bindings = > + &runtime_data->lbinding_data.bindings, > + }; > + struct vif_plug_ctx_out vif_plug_ctx_out = { > + .deleted_iface_ids = > + &vif_plug_deleted_iface_ids, > + .changed_iface_ids = > + &vif_plug_changed_iface_ids, > + }; > + stopwatch_start(VIF_PLUG_RUN_STOPWATCH_NAME, > + time_msec()); > + vif_plug_run(&vif_plug_ctx_in, > + &vif_plug_ctx_out); > + stopwatch_stop(VIF_PLUG_RUN_STOPWATCH_NAME, > + time_msec()); > + } > stopwatch_start(PINCTRL_RUN_STOPWATCH_NAME, > time_msec()); > pinctrl_run(ovnsb_idl_txn, > @@ -3806,7 +3845,16 @@ main(int argc, char *argv[]) > engine_set_force_recompute(true); > } > > - if (ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop) == 1) { > + int ovs_txn_status = ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop); > + if (!ovs_txn_status) { > + /* The transaction failed. */ > + vif_plug_clear_deleted( > + &vif_plug_deleted_iface_ids); > + vif_plug_clear_changed( > + &vif_plug_changed_iface_ids); > + } else if (ovs_txn_status == 1) { > + /* The transaction committed successfully > + * (or it did not change anything in the database). */ > ct_zones_data = engine_get_data(&en_ct_zones); > if (ct_zones_data) { > struct shash_node *iter, *iter_next; > @@ -3819,6 +3867,15 @@ main(int argc, char *argv[]) > } > } > } > + > + vif_plug_finish_deleted( > + &vif_plug_deleted_iface_ids); > + vif_plug_finish_changed( > + &vif_plug_changed_iface_ids); > + } else if (ovs_txn_status == -1) { > + /* The commit is still in progress */ > + } else { > + OVS_NOT_REACHED(); > } > > ovsdb_idl_track_clear(ovnsb_idl_loop.idl); > @@ -3894,6 +3951,8 @@ loop_done: > pinctrl_destroy(); > patch_destroy(); > if_status_mgr_destroy(if_mgr); > + shash_destroy(&vif_plug_deleted_iface_ids); > + shash_destroy(&vif_plug_changed_iface_ids); > vif_plug_provider_destroy_all(); > > ovsdb_idl_loop_destroy(&ovs_idl_loop); > diff --git a/ovn-nb.xml b/ovn-nb.xml > index e31578fb6..036ffa64f 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -1031,6 +1031,27 @@ > DHCP reply. > </p> > </column> > + > + <group title="VIF Plugging Options"> > + <column name="options" key="vif-plug-type"> > + If set, OVN will attempt to perform plugging of this VIF. In order > + to get this port plugged by the OVN controller, OVN must be built > + with support for VIF plugging. The default behavior is for the CMS > + to do the VIF plugging. Each VIF plug provider have their own > + options namespaced by name, for example "vif-plug:representor:key". > + > + Please refer to the VIF plug provider documentation located in > + Documentation/topics/vif-plug-providers/ for more information. > + </column> > + > + <column name="options" key="vif-plug-mtu-request"> > + Requested MTU for plugged interfaces. When set the OVN controller > + will fill the <ref table="Interface" column="mtu_request"/> column > + of the Open vSwitch database's > + <ref table="Interface" db="vswitch"/> table. This in turn will > + make OVS vswitchd update the MTU of the linked interface. > + </column> > + </group> > </group> > > <group title="Virtual port Options"> > diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at > index f06f2e68e..21b7d985e 100644 > --- a/tests/ovn-macros.at > +++ b/tests/ovn-macros.at > @@ -327,7 +327,7 @@ ovn_az_attach() { > -- --may-exist add-br br-int \ > -- set bridge br-int fail-mode=secure other-config:disable-in-band=true \ > || return 1 > - start_daemon ovn-controller || return 1 > + start_daemon ovn-controller --enable-dummy-vif-plug || return 1 > } > > # ovn_attach NETWORK BRIDGE IP [MASKLEN] > diff --git a/tests/ovn.at b/tests/ovn.at > index 7cfdede77..b93dbdcff 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -28789,3 +28789,124 @@ AT_CHECK([grep -q "Not claiming" hv1/ovn-controller.log], [1], []) > OVN_CLEANUP([hv1]) > AT_CLEANUP > ]) > + > +OVN_FOR_EACH_NORTHD([ > +AT_SETUP([ovn-controller - VIF plugging]) > +AT_KEYWORDS([vif-plug]) > + > +ovn_start > + > +net_add n1 > +sim_add hv1 > +ovs-vsctl add-br br-phys > +ovn_attach n1 br-phys 192.168.0.1 > + > +sim_add hv2 > +ovs-vsctl add-br br-phys > +ovn_attach n1 br-phys 192.168.0.2 > + > +check ovn-nbctl ls-add lsw0 > + > +check ovn-nbctl lsp-add lsw0 lsp1 > +check ovn-nbctl lsp-set-addresses lsp1 "f0:00:00:00:00:01 172.16.0.101" > +check ovn-nbctl lsp-set-options lsp1 \ > + requested-chassis=hv1 \ > + vif-plug-type=dummy \ > + vif-plug-mtu-request=42 > + > +check ovn-nbctl lsp-add lsw0 lsp2 > +check ovn-nbctl lsp-set-addresses lsp2 "f0:00:00:00:00:02 172.16.0.102" > +check ovn-nbctl lsp-set-options lsp2 \ > + requested-chassis=hv2 \ > + vif-plug-type=dummy \ > + vif-plug-mtu-request=42 > + > +wait_for_ports_up lsp1 lsp2 > + > +lsp1_uuid=$(ovn-nbctl --bare --columns _uuid find Logical_Switch_Port name=lsp1) > +iface1_uuid=$(as hv1 ovs-vsctl --bare --columns _uuid find Interface name=lsp1) > + > +lsp2_uuid=$(ovn-nbctl --bare --columns _uuid find Logical_Switch_Port name=lsp2) > +iface2_uuid=$(as hv2 ovs-vsctl --bare --columns _uuid find Interface name=lsp2) > + > +# Check that the lport was plugged > +AT_CHECK([test xvalue = x$(as hv1 ovs-vsctl get Interface ${iface1_uuid} options:vif-plug-dummy-option)], [0], []) > +AT_CHECK([test x42 = x$(as hv1 ovs-vsctl get Interface ${iface1_uuid} mtu_request)], [0], []) > + > +# Check that updating the lport updates the local iface > +check ovn-nbctl --wait=hv lsp-set-options lsp1 \ > + requested-chassis=hv1 \ > + vif-plug-type=dummy \ > + vif-plug-mtu-request=43 > +OVS_WAIT_UNTIL([ > + test x43 = x$(as hv1 ovs-vsctl get Interface ${iface1_uuid} mtu_request) > +]) > + > +# Check that local modification of iface will trigger ovn-controller to update > +# the iface record > +check as hv1 ovs-vsctl set interface ${iface1_uuid} mtu_request=44 > +OVS_WAIT_UNTIL([ > + test x43 = x$(as hv1 ovs-vsctl get Interface ${iface1_uuid} mtu_request) > +]) > + > +# Check that pointing requested-chassis somewhere else will unplug the port > +check ovn-nbctl --wait=hv set Logical_Switch_Port lsp1 \ > + options:requested-chassis=non-existent-chassis > +OVS_WAIT_UNTIL([ > + ! as hv1 ovs-vsctl get Interface ${iface1_uuid} _uuid > +]) > + > +# Check that removing an lport will unplug it > +AT_CHECK([test x${iface2_uuid} = x$(as hv2 ovs-vsctl get Interface ${iface2_uuid} _uuid)], [0], []) > +check ovn-nbctl --wait=hv lsp-del ${lsp2_uuid} > +OVS_WAIT_UNTIL([ > + ! as hv2 ovs-vsctl get Interface ${iface2_uuid} _uuid > +]) > + > +# Check that port is unplugged when we simulate presence of a port previously > +# plugged by us in local OVSDB with no record in SB DB. > +check as hv2 ovs-vsctl \ > + -- add-port br-int vif1 > + > +# From one moment it's there... > +vif1_uuid=$(as hv2 ovs-vsctl --bare --columns _uuid find Interface name=vif1) > +OVS_WAIT_UNTIL([ > + as hv2 ovs-vsctl get Interface ${vif1_uuid} _uuid > +]) > + > +# Add the external-ids we expect > +check as hv2 ovs-vsctl \ > + -- set Interface ${vif1_uuid} \ > + external-ids:ovn-plugged=dummy \ > + external-ids:iface-id=non-existing-lsp > + > +# ...to the next moment it's gone. > +OVS_WAIT_UNTIL([ > + ! as hv2 ovs-vsctl get Interface ${vif1_uuid} _uuid > +]) > + > +# Check that a warning is logged when CMS requests plugging of an interface > +# with lbinding already plugged by someone else. > +check as hv2 ovs-vsctl \ > + -- add-port br-int vif3 \ > + -- set Interface vif3 \ > + external-ids:iface-id=lsp3 > + > +check ovn-nbctl lsp-add lsw0 lsp3 > +check ovn-nbctl lsp-set-addresses lsp3 "f0:00:00:00:00:03 172.16.0.103" > +check ovn-nbctl lsp-set-options lsp3 \ > + requested-chassis=hv2 > + > +wait_for_ports_up lsp3 > + > +check ovn-nbctl --wait=hv lsp-set-options lsp3 \ > + requested-chassis=hv2 \ > + vif-plug-type=dummy > + > +OVS_WAIT_UNTIL([ > + grep -q "CMS requested plugging of lport lsp3" hv2/ovn-controller.log > +]) > + > +OVN_CLEANUP([hv1],[hv2]) > +AT_CLEANUP > +]) > -- > 2.32.0 >
Acked-by: Han Zhou <[email protected]> _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
