[ovs-dev] [PATCH ovn] controller: Container lport install flows in MAIN chassis only.
If container lport parent_port has an additional chassis option set with multiple chassis in some cases the container lport flows in table 0 will be installed in all those chassis instead of the main chassis. This patch will limit the container port flows in table 0 to only the parent port main chassis. Rreported-at: https://issues.redhat.com/browse/FDP-772 Signed-off-by: Mohammad Heib --- controller/physical.c | 3 ++- tests/ovn.at | 51 ++- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/controller/physical.c b/controller/physical.c index 9e04ad5f2..184e5ef34 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -1658,7 +1658,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, sbrec_port_binding_by_name, binding->parent_port); if (parent_port -&& !lport_can_bind_on_this_chassis(chassis, parent_port)) { +&& (lport_can_bind_on_this_chassis(chassis, +parent_port) != CAN_BIND_AS_MAIN)) { /* Even though there is an ofport for this container * parent port, it is requested on different chassis ignore * this container port. diff --git a/tests/ovn.at b/tests/ovn.at index acf18c4e0..c4a1317d4 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -38238,49 +38238,60 @@ AT_CLEANUP OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-controller - cleanup VIF/CIF related flows/fields when updating requested-chassis]) ovn_start - net_add n1 -sim_add hv1 -ovs-vsctl add-br br-phys -ovn_attach n1 br-phys 192.168.0.1 -check ovs-vsctl -- add-port br-int vif1 -- \ -set Interface vif1 external-ids:iface-id=lsp1 \ -ofport-request=8 -check ovn-nbctl ls-add lsw0 +for i in 1 2; do +sim_add hv$i +as hv$i +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.$i +check ovs-vsctl -- add-port br-int vif1 -- \ +set Interface vif1 ofport-request=8 +done +check ovn-nbctl ls-add lsw0 +as hv1 +check ovs-vsctl set Interface vif1 external-ids:iface-id=lsp1 check ovn-nbctl lsp-add lsw0 lsp1 check ovn-nbctl lsp-add lsw0 sw0-port1.1 lsp1 7 # wait for the VIF to be claimed to this chassis wait_row_count Chassis 1 name=hv1 +wait_row_count Chassis 1 name=hv2 hv1_uuid=$(fetch_column Chassis _uuid name=hv1) +hv2_uuid=$(fetch_column Chassis _uuid name=hv2) + wait_for_ports_up lsp1 wait_for_ports_up sw0-port1.1 wait_column "$hv1_uuid" Port_Binding chassis logical_port=lsp1 wait_column "$hv1_uuid" Port_Binding chassis logical_port=sw0-port1.1 # check that flows is installed -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=100 | grep -c in_port=8], [0],[dnl +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [0],[dnl 1 ]) -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [0],[dnl -1 + +OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [1],[dnl +0 ]) -# set lport requested-chassis to differant chassis +# Add hv2 to lport Additional requested chassis as MAIN chassis +# and check that no flows installed in table 0 in hv1 check ovn-nbctl set Logical_Switch_Port lsp1 \ -options:requested-chassis=foo +options:requested-chassis=hv2,hv1 -OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding lsp1 up` = 'false']) -OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding sw0-port1.1 up` = 'false']) -wait_column "" Port_Binding chassis logical_port=lsp1 -wait_column "" Port_Binding chassis logical_port=sw0-port1.1 +as hv2 +check ovs-vsctl set Interface vif1 external-ids:iface-id=lsp1 +ovn-nbctl --wait=hv sync -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=100 |grep -c in_port=8], [1],[dnl -0 +wait_for_ports_up lsp1 +wait_for_ports_up sw0-port1.1 +wait_column "$hv2_uuid" Port_Binding chassis logical_port=lsp1 + +OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [0],[dnl +1 ]) -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [1],[dnl +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [1],[dnl 0 ]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] controller: Container lport install flows in MAIN chassis only.
If container lport parent_port has an additional chassis option set with multiple chassis in some cases the container lport flows in table 0 will be installed in all those chassis instead of the main chassis. This patch will limit the container port flows in table 0 to only the parent port main chassis. Rreported-at: https://issues.redhat.com/browse/FDP-772 Signed-off-by: Mohammad Heib --- controller/physical.c | 3 ++- tests/ovn.at | 51 ++- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/controller/physical.c b/controller/physical.c index 9e04ad5f2..184e5ef34 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -1658,7 +1658,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, sbrec_port_binding_by_name, binding->parent_port); if (parent_port -&& !lport_can_bind_on_this_chassis(chassis, parent_port)) { +&& (lport_can_bind_on_this_chassis(chassis, +parent_port) != CAN_BIND_AS_MAIN)) { /* Even though there is an ofport for this container * parent port, it is requested on different chassis ignore * this container port. diff --git a/tests/ovn.at b/tests/ovn.at index acf18c4e0..c4a1317d4 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -38238,49 +38238,60 @@ AT_CLEANUP OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-controller - cleanup VIF/CIF related flows/fields when updating requested-chassis]) ovn_start - net_add n1 -sim_add hv1 -ovs-vsctl add-br br-phys -ovn_attach n1 br-phys 192.168.0.1 -check ovs-vsctl -- add-port br-int vif1 -- \ -set Interface vif1 external-ids:iface-id=lsp1 \ -ofport-request=8 -check ovn-nbctl ls-add lsw0 +for i in 1 2; do +sim_add hv$i +as hv$i +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.$i +check ovs-vsctl -- add-port br-int vif1 -- \ +set Interface vif1 ofport-request=8 +done +check ovn-nbctl ls-add lsw0 +as hv1 +check ovs-vsctl set Interface vif1 external-ids:iface-id=lsp1 check ovn-nbctl lsp-add lsw0 lsp1 check ovn-nbctl lsp-add lsw0 sw0-port1.1 lsp1 7 # wait for the VIF to be claimed to this chassis wait_row_count Chassis 1 name=hv1 +wait_row_count Chassis 1 name=hv2 hv1_uuid=$(fetch_column Chassis _uuid name=hv1) +hv2_uuid=$(fetch_column Chassis _uuid name=hv2) + wait_for_ports_up lsp1 wait_for_ports_up sw0-port1.1 wait_column "$hv1_uuid" Port_Binding chassis logical_port=lsp1 wait_column "$hv1_uuid" Port_Binding chassis logical_port=sw0-port1.1 # check that flows is installed -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=100 | grep -c in_port=8], [0],[dnl +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [0],[dnl 1 ]) -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [0],[dnl -1 + +OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [1],[dnl +0 ]) -# set lport requested-chassis to differant chassis +# Add hv2 to lport Additional requested chassis as MAIN chassis +# and check that no flows installed in table 0 in hv1 check ovn-nbctl set Logical_Switch_Port lsp1 \ -options:requested-chassis=foo +options:requested-chassis=hv2,hv1 -OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding lsp1 up` = 'false']) -OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding sw0-port1.1 up` = 'false']) -wait_column "" Port_Binding chassis logical_port=lsp1 -wait_column "" Port_Binding chassis logical_port=sw0-port1.1 +as hv2 +check ovs-vsctl set Interface vif1 external-ids:iface-id=lsp1 +ovn-nbctl --wait=hv sync -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=100 |grep -c in_port=8], [1],[dnl -0 +wait_for_ports_up lsp1 +wait_for_ports_up sw0-port1.1 +wait_column "$hv2_uuid" Port_Binding chassis logical_port=lsp1 + +OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [0],[dnl +1 ]) -OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [1],[dnl +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [1],[dnl 0 ]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v2 3/3] controller: Drop binding requests for paused virtual port.
Drop the binding requests for a virtual port if that port set to pause in northd. Signed-off-by: Mohammad Heib --- controller/pinctrl.c | 39 ++- tests/ovn.at | 91 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 7cbb0cf81..7420f2009 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -7057,11 +7057,16 @@ struct put_vport_binding { /* This vport record Only relevant if "new_record" is true. */ bool new_record; +/* The creation time in pinctrl thread */ +long long int creation_time; }; /* Contains "struct put_vport_binding"s. */ static struct hmap put_vport_bindings; +/* pause duration for port that set puased in northd. */ +#define PAUSE_DURATION 1 + /* * Validate if the vport_binding record that was added * by the pinctrl thread is still relevant and needs @@ -7145,7 +7150,7 @@ run_put_vport_binding(struct ovsdb_idl_txn *ovnsb_idl_txn OVS_UNUSED, struct ovsdb_idl_index *sbrec_datapath_binding_by_key, struct ovsdb_idl_index *sbrec_port_binding_by_key, const struct sbrec_chassis *chassis, - const struct put_vport_binding *vpb) + struct put_vport_binding *vpb) { /* Convert logical datapath and logical port key into lport. */ const struct sbrec_port_binding *pb = lport_lookup_by_key( @@ -7159,6 +7164,35 @@ run_put_vport_binding(struct ovsdb_idl_txn *ovnsb_idl_txn OVS_UNUSED, return; } +if (smap_get(&pb->options, "binding_request_pause")) { +long long int p_time = smap_get_ullong(&pb->options, + "binding_request_pause_ts", 0); +/* Pause duration for this port still relevant, drop this + * binding request, and set vpb->new_record=false to make sure + * that it will be deleted from the list when flushing the list. + */ +if ((p_time + PAUSE_DURATION) > vpb->creation_time) { +vpb->new_record = false; +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); +VLOG_DBG_RL(&rl, + "Virtual lport %s drop binding request port " + "in pause state\n", pb->logical_port); + +return; +} else { +VLOG_INFO("Virtual lport %s binding requests paused " + "for 10 seconds, resume binding requests handling.", + pb->logical_port); +struct smap options; +smap_clone(&options, &pb->options); +smap_remove(&options, "binding_request_pause"); +smap_remove(&options, "binding_request_pause_ts"); +sbrec_port_binding_set_options(pb, &options); +smap_destroy(&options); + +} +} + /* pinctrl module updates the port binding only for type 'virtual'. */ if (!strcmp(pb->type, "virtual")) { const struct sbrec_port_binding *parent = lport_lookup_by_key( @@ -7187,7 +7221,7 @@ run_put_vport_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, return; } -const struct put_vport_binding *vpb; +struct put_vport_binding *vpb; HMAP_FOR_EACH (vpb, hmap_node, &put_vport_bindings) { run_put_vport_binding(ovnsb_idl_txn, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, chassis, vpb); @@ -7232,6 +7266,7 @@ pinctrl_handle_bind_vport( vpb->vport_key = vport_key; vpb->vport_parent_key = vport_parent_key; vpb->new_record = true; +vpb->creation_time = time_msec(); notify_pinctrl_main(); } diff --git a/tests/ovn.at b/tests/ovn.at index b31afbfb3..408505ee9 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -22442,6 +22442,97 @@ OVN_CLEANUP([hv1], [hv2]) AT_CLEANUP ]) +# Create 10 HV's each have 3 VIF ports that all +# sends Garp at the same time to bind vport sw0-vir +# this will create high pressure on SB/North and will +# lead to a transaction dropping by SB. +# +# Northd must be able to detect such cases and pause +# binding requests for this specific port for a certain +# amount of time. +# +OVN_FOR_EACH_NORTHD([ +AT_SETUP([virtual ports - binding requests storm]) +AT_KEYWORDS([virtual ports]) +ovn_start + +send_garp() { +local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6 +local request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa} +as hv$hv ovs-appctl netdev-dummy/receive vif$hv$inport $request +} + +net_add n1 +check ovn-nbctl ls-add sw0 +check ovn-nbctl ls-add sw1 +parents="" +for i in {1..9}; do +sim_add hv$i +as hv$i +ovs-vsctl add-br br
[ovs-dev] [PATCH ovn v2 2/3] Northd: Pause virtual port binding requests for crowded ports.
ovn-controller sends binding requests to update the virtual parent of a virtual port to northd, in some cases those requests are not handled immediately and ovn-controller keeps sending requests over and over which can lead to flooding northd with these requests. This patch add the ability to pause virtual ports that send so many binding requests to northd. Signed-off-by: Mohammad Heib --- northd/northd.c | 98 + 1 file changed, 98 insertions(+) diff --git a/northd/northd.c b/northd/northd.c index 89d5b2936..a2782031d 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -3093,6 +3093,15 @@ ovn_port_update_sbrec(struct ovsdb_idl_txn *ovnsb_txn, "qdisc_queue_id", "%d", queue_id); } +if (smap_get_bool(&op->sb->options, +"binding_request_pause", false)) { +long long int p_time = smap_get_ullong(&op->sb->options, +"binding_request_pause_ts", 0); +smap_add_format(&options, "binding_request_pause_ts", +"%lld", p_time); +smap_add(&options, "binding_request_pause", "true"); +} + if (smap_get_bool(&op->od->nbs->other_config, "vlan-passthru", false)) { smap_add(&options, "vlan-passthru", "true"); } @@ -3830,6 +3839,90 @@ void destroy_tracked_virtual_ports(void) { hmap_destroy(&tracked_virtual_ports); } +/* + * For every virtual port that send request to update thier virtual_parent + * This function will update the following Port_binding options if needed: + * + * 1. tracked_virtual_port record belongs to this virtual port was created + *when this port created. This tracked struct have two main Fields: + * + * a. First_bind_in_tframe: this field will be set to the time that + * binding request were reicved for this vport for the first time + * within a timeframe. + * + * b. Bind_request_cnt: this filed will be incresses every time a binding + * request recived for that virtual port. + * + * + * 2. For each binding request received for a specific virtual port + * check if the time diff between now and the first time that a + * binding request were recived for this port within a pre-define + * timeframe is less than that timeframe. + * + * 3. If the previous condition true increase Bind_request_cnt and + * check if the total recived binding request recived for this port + * within a time fram exceeded the VPORT_MAX_BINDING_REQUEST_TRESHOLD + * set the Port_binding options: + * + * PB:OPTIONS:binding_request_pause=true + * PB:OPTIONS:binding_request_pause_ts=time_now + * + * + * 4. When ovn-controller recived a new GARP for this virtual port + * before sending a binding request update to northd it will check + * if the port have binding_request_pause=true, ovn-controller will do + * the following: + * + * If the PB:OPTIONS:binding_request_pause_ts + 10 seconds greater + * than the time now (GARP processing time), drop the GARP packet. + * + * Otherwise, set the PB:OPTIONS:binding_request_pause=false and resume + * binding request handling on this virtual port. + * + * + */ +static void +vport_binding_request_exceed_threshold(struct ovn_port *op) +{ +struct tracked_virtual_port * vport = + find_tracked_virtual_port(op->key); +if (op->sb != NULL) { +/* This port already paused or not found ignore it */ +if ((smap_get_bool(&op->sb->options, "binding_request_pause", + false) == true) || !vport) { +return; +} +} + +long long int cur_time = time_msec(); + +/* Still in the range of the time frame. */ +if ((vport->First_bind_in_tframe + VPORT_BINDING_TIMEFRAME) > cur_time) { +if (++vport->Bind_request_cnt > VPORT_MAX_BINDING_REQUEST_TRESHOLD) { +if (op->sb != NULL) { +static struct vlog_rate_limit rl = +VLOG_RATE_LIMIT_INIT(1, 1); +VLOG_WARN_RL(&rl, "Pausing virtual port %s from sending" +" binding requests for few seconds. " +" This port was paused in order to reduce the load on the" +" network.\n" , vport->name); +struct smap options; +smap_clone(&options, &op->sb->options); +smap_add(&options, "binding_request_pause", "true"); +smap_add_format(&options, "binding_request_pause_ts", "%lld", +
[ovs-dev] [PATCH ovn v2 1/3] Northd: Start tracking virtual port binding requests.
Northd handles virtual port binding requests received by ovn-controllers without tracking those requests or saving any info about the last binding requests and the number of requests received for an individual virtual port. This patch adds a basic tracking mechanism for each virtual port that future patches will use to limit/pause the controller from sending binding requests for a specific virtual port if this port overflows the system by such requests. Signed-off-by: Mohammad Heib --- northd/northd.c | 88 + northd/northd.h | 2 ++ northd/ovn-northd.c | 3 ++ 3 files changed, 93 insertions(+) diff --git a/northd/northd.c b/northd/northd.c index a8a0b6f94..89d5b2936 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -3757,6 +3757,79 @@ build_lb_port_related_data( build_lswitch_lbs_from_lrouter(lr_datapaths, lb_dps_map, lb_group_dps_map); } +/* + * These functions implements the binding request tracking for a virtual + * port which can be used to limit virtual port binding requests + * and avoid system overflow. + * + * Virtual port binding requests must not exceed + * VPORT_MAX_BINDING_REQUEST_TRESHOLD within a VPORT_BINDING_TIMEFRAME, + * otherwise, this vport must be defined as overflowed and should limit + * the binding request in this port for a certain time. + */ +#define VPORT_BINDING_TIMEFRAME 1 +#define VPORT_MAX_BINDING_REQUEST_TRESHOLD 15 + +static struct hmap tracked_virtual_ports; + +struct tracked_virtual_port { +struct hmap_node node; +/* + * Use port name instaed of ovn_port refrence to make + * sure that virtual port tracking data will be permanent accross + * northd loops and we can keep track the target ports. + */ +char *name; +long long int First_bind_in_tframe; +size_t Bind_request_cnt; +}; + +static struct tracked_virtual_port * +find_tracked_virtual_port(const char *name) { +struct tracked_virtual_port *vport; +HMAP_FOR_EACH (vport, node, &tracked_virtual_ports) { +if (!strcmp(name, vport->name)) { +return vport; +} +} +return NULL; +} + +static void +add_to_tracked_virtual_ports(const char *name) { +struct tracked_virtual_port *vport = find_tracked_virtual_port(name); +if (!vport) { +vport = xmalloc(sizeof *vport); +vport->name = xstrdup(name); +vport->First_bind_in_tframe = 0; +vport->Bind_request_cnt = 0; +hmap_insert(&tracked_virtual_ports, &vport->node, +hash_string(name, 0)); +} +} + +static void +remove_from_tracked_virtual_ports(const char *name) { +struct tracked_virtual_port *vport = find_tracked_virtual_port(name); +if (vport) { +free(vport->name); +hmap_remove(&tracked_virtual_ports, &vport->node); +free(vport); +} +} + +void init_tracked_virtual_ports(void) { +hmap_init(&tracked_virtual_ports); +} + +void destroy_tracked_virtual_ports(void) { +struct tracked_virtual_port *vport; +HMAP_FOR_EACH_SAFE (vport, node, &tracked_virtual_ports) { +remove_from_tracked_virtual_ports(vport->name); +} +hmap_destroy(&tracked_virtual_ports); +} + /* Syncs the SB port binding for the ovn_port 'op' of a logical switch port. * Caller should make sure that the OVN SB IDL txn is not NULL. Presently it * only syncs the nat column of port binding corresponding to the 'op->nbsp' */ @@ -4163,6 +4236,9 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn, op, queue_id_bitmap, &active_ha_chassis_grps); sbrec_port_binding_set_logical_port(op->sb, op->key); +if (!strcmp(op->sb->type, "virtual")) { +add_to_tracked_virtual_ports(op->sb->logical_port); +} ovs_list_remove(&op->list); } @@ -4170,6 +4246,9 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn, if (!ovs_list_is_empty(&sb_only)) { LIST_FOR_EACH_SAFE (op, list, &sb_only) { ovs_list_remove(&op->list); +if (!strcmp(op->sb->type, "virtual")) { +remove_from_tracked_virtual_ports(op->sb->logical_port); +} sbrec_port_binding_delete(op->sb); ovn_port_destroy(ports, op); } @@ -4554,6 +4633,12 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, if (!op) { goto fail; } + +if (!strcmp(new_nbsp->type, "virtual")) { +/* Add to virtual port tracking map */ +add_to_tracked_virtual_ports(op->nbsp->name); +} + add_op_to_northd_tracked_ports(&trk_lsps->created, op); } else if (ls_port_has_changed(new_nbsp)) {
[ovs-dev] [PATCH ovn v2 0/3] Virtual ports add binding request auto-pausing mechanism.
This series implements virtual ports binding request auto-pausing that is needed to limit system overflow with binding requests packets when ovn-northd is busy. Currently ovn-controller sends binding requests to update the virtual parent of a virtual port to northd, in some cases those requests are not handled immediately and ovn-controller keeps sending requests over and over which can lead to flooding northd with these requests. This patch series fixes the above issue by measuring how many binding request packets are received from a specific virtual port within a particular time frame and if the number of received packets exceeds a pre-defined maximum, the northd will update this virtual port status to paused and limit the port ability to send a request for a certain amount of seconds. Reported-at: https://issues.redhat.com/browse/FDP-443 Mohammad Heib (3): Northd: Start tracking virtual port binding requests. Northd: Pause virtual port binding requests for crowded ports. controller: Drop binding requests for paused virtual port. controller/pinctrl.c | 39 - northd/northd.c | 186 +++ northd/northd.h | 2 + northd/ovn-northd.c | 3 + tests/ovn.at | 91 + 5 files changed, 319 insertions(+), 2 deletions(-) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn 3/3] controller: Drop binding requests for paused virtual port.
Drop the binding requests for a virtual port if that port set to pause in northd. Signed-off-by: Mohammad Heib --- controller/pinctrl.c | 39 ++- tests/ovn.at | 91 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 7cbb0cf81..7420f2009 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -7057,11 +7057,16 @@ struct put_vport_binding { /* This vport record Only relevant if "new_record" is true. */ bool new_record; +/* The creation time in pinctrl thread */ +long long int creation_time; }; /* Contains "struct put_vport_binding"s. */ static struct hmap put_vport_bindings; +/* pause duration for port that set puased in northd. */ +#define PAUSE_DURATION 1 + /* * Validate if the vport_binding record that was added * by the pinctrl thread is still relevant and needs @@ -7145,7 +7150,7 @@ run_put_vport_binding(struct ovsdb_idl_txn *ovnsb_idl_txn OVS_UNUSED, struct ovsdb_idl_index *sbrec_datapath_binding_by_key, struct ovsdb_idl_index *sbrec_port_binding_by_key, const struct sbrec_chassis *chassis, - const struct put_vport_binding *vpb) + struct put_vport_binding *vpb) { /* Convert logical datapath and logical port key into lport. */ const struct sbrec_port_binding *pb = lport_lookup_by_key( @@ -7159,6 +7164,35 @@ run_put_vport_binding(struct ovsdb_idl_txn *ovnsb_idl_txn OVS_UNUSED, return; } +if (smap_get(&pb->options, "binding_request_pause")) { +long long int p_time = smap_get_ullong(&pb->options, + "binding_request_pause_ts", 0); +/* Pause duration for this port still relevant, drop this + * binding request, and set vpb->new_record=false to make sure + * that it will be deleted from the list when flushing the list. + */ +if ((p_time + PAUSE_DURATION) > vpb->creation_time) { +vpb->new_record = false; +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); +VLOG_DBG_RL(&rl, + "Virtual lport %s drop binding request port " + "in pause state\n", pb->logical_port); + +return; +} else { +VLOG_INFO("Virtual lport %s binding requests paused " + "for 10 seconds, resume binding requests handling.", + pb->logical_port); +struct smap options; +smap_clone(&options, &pb->options); +smap_remove(&options, "binding_request_pause"); +smap_remove(&options, "binding_request_pause_ts"); +sbrec_port_binding_set_options(pb, &options); +smap_destroy(&options); + +} +} + /* pinctrl module updates the port binding only for type 'virtual'. */ if (!strcmp(pb->type, "virtual")) { const struct sbrec_port_binding *parent = lport_lookup_by_key( @@ -7187,7 +7221,7 @@ run_put_vport_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, return; } -const struct put_vport_binding *vpb; +struct put_vport_binding *vpb; HMAP_FOR_EACH (vpb, hmap_node, &put_vport_bindings) { run_put_vport_binding(ovnsb_idl_txn, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, chassis, vpb); @@ -7232,6 +7266,7 @@ pinctrl_handle_bind_vport( vpb->vport_key = vport_key; vpb->vport_parent_key = vport_parent_key; vpb->new_record = true; +vpb->creation_time = time_msec(); notify_pinctrl_main(); } diff --git a/tests/ovn.at b/tests/ovn.at index b31afbfb3..408505ee9 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -22442,6 +22442,97 @@ OVN_CLEANUP([hv1], [hv2]) AT_CLEANUP ]) +# Create 10 HV's each have 3 VIF ports that all +# sends Garp at the same time to bind vport sw0-vir +# this will create high pressure on SB/North and will +# lead to a transaction dropping by SB. +# +# Northd must be able to detect such cases and pause +# binding requests for this specific port for a certain +# amount of time. +# +OVN_FOR_EACH_NORTHD([ +AT_SETUP([virtual ports - binding requests storm]) +AT_KEYWORDS([virtual ports]) +ovn_start + +send_garp() { +local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6 +local request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa} +as hv$hv ovs-appctl netdev-dummy/receive vif$hv$inport $request +} + +net_add n1 +check ovn-nbctl ls-add sw0 +check ovn-nbctl ls-add sw1 +parents="" +for i in {1..9}; do +sim_add hv$i +as hv$i +ovs-vsctl add-br br
[ovs-dev] [PATCH ovn 1/3] Northd: Start tracking virtual port binding requests.
Northd handles virtual port binding requests received by ovn-controllers without tracking those requests or saving any info about the last binding requests and the number of requests received for an individual virtual port. This patch adds a basic tracking mechanism for each virtual port that future patches will use to limit/pause the controller from sending binding requests for a specific virtual port if this port overflows the system by such requests. Signed-off-by: Mohammad Heib --- northd/northd.c | 88 + northd/northd.h | 2 ++ northd/ovn-northd.c | 3 ++ 3 files changed, 93 insertions(+) diff --git a/northd/northd.c b/northd/northd.c index a8a0b6f94..7437b1dfe 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -3757,6 +3757,79 @@ build_lb_port_related_data( build_lswitch_lbs_from_lrouter(lr_datapaths, lb_dps_map, lb_group_dps_map); } +/* + * These functions implements the binding request tracking for a virtual + * port which can be used to limit virtual port binding requests + * and avoid system overflow. + * + * Virtual port binding requests must not exceed + * VPORT_MAX_BINDING_REQUEST_TRESHOLD within a VPORT_BINDING_TIMEFRAME, + * otherwise, this vport must be defined as overflowed and should limit + * the binding request in this port for a certain time. + */ +#define VPORT_BINDING_TIMEFRAME 1 +#define VPORT_MAX_BINDING_REQUEST_TRESHOLD 15 + +struct hmap tracked_virtual_ports; + +struct tracked_virtual_port { +struct hmap_node node; +/* + * Use port name instaed of ovn_port refrence to make + * sure that virtual port tracking data will be permanent accross + * northd loops and we can keep track the target ports. + */ +char *name; +long long int First_bind_in_tframe; +size_t Bind_request_cnt; +}; + +static struct tracked_virtual_port * +find_tracked_virtual_port(const char *name) { +struct tracked_virtual_port *vport; +HMAP_FOR_EACH (vport, node, &tracked_virtual_ports) { +if (!strcmp(name, vport->name)) { +return vport; +} +} +return NULL; +} + +static void +add_to_tracked_virtual_ports(const char *name) { +struct tracked_virtual_port *vport = find_tracked_virtual_port(name); +if (!vport) { +vport = xmalloc(sizeof *vport); +vport->name = xstrdup(name); +vport->First_bind_in_tframe = 0; +vport->Bind_request_cnt = 0; +hmap_insert(&tracked_virtual_ports, &vport->node, +hash_string(name, 0)); +} +} + +static void +remove_from_tracked_virtual_ports(const char *name) { +struct tracked_virtual_port *vport = find_tracked_virtual_port(name); +if (vport) { +free(vport->name); +hmap_remove(&tracked_virtual_ports, &vport->node); +free(vport); +} +} + +void init_tracked_virtual_ports(void) { +hmap_init(&tracked_virtual_ports); +} + +void destroy_tracked_virtual_ports(void) { +struct tracked_virtual_port *vport; +HMAP_FOR_EACH_SAFE (vport, node, &tracked_virtual_ports) { +remove_from_tracked_virtual_ports(vport->name); +} +hmap_destroy(&tracked_virtual_ports); +} + /* Syncs the SB port binding for the ovn_port 'op' of a logical switch port. * Caller should make sure that the OVN SB IDL txn is not NULL. Presently it * only syncs the nat column of port binding corresponding to the 'op->nbsp' */ @@ -4163,6 +4236,9 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn, op, queue_id_bitmap, &active_ha_chassis_grps); sbrec_port_binding_set_logical_port(op->sb, op->key); +if (!strcmp(op->sb->type, "virtual")) { +add_to_tracked_virtual_ports(op->sb->logical_port); +} ovs_list_remove(&op->list); } @@ -4170,6 +4246,9 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn, if (!ovs_list_is_empty(&sb_only)) { LIST_FOR_EACH_SAFE (op, list, &sb_only) { ovs_list_remove(&op->list); +if (!strcmp(op->sb->type, "virtual")) { +remove_from_tracked_virtual_ports(op->sb->logical_port); +} sbrec_port_binding_delete(op->sb); ovn_port_destroy(ports, op); } @@ -4554,6 +4633,12 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, if (!op) { goto fail; } + +if (!strcmp(new_nbsp->type, "virtual")) { +/* Add to virtual port tracking map */ +add_to_tracked_virtual_ports(op->nbsp->name); +} + add_op_to_northd_tracked_ports(&trk_lsps->created, op); } else if (ls_port_has_changed(new_nbsp)) { /* Existing port u
[ovs-dev] [PATCH ovn 0/3] Virtual ports add binding request auto-pausing mechanism.
This series implements virtual ports binding request auto-pausing that is needed to limit system overflow with binding requests packets when ovn-northd is busy. Currently ovn-controller sends binding requests to update the virtual parent of a virtual port to northd, in some cases those requests are not handled immediately and ovn-controller keeps sending requests over and over which can lead to flooding northd with these requests. This patch series fixes the above issue by measuring how many binding request packets are received from a specific virtual port within a particular time frame and if the number of received packets exceeds a pre-defined maximum, the northd will update this virtual port status to paused and limit the port ability to send a request for a certain amount of seconds. Reported-at: https://issues.redhat.com/browse/FDP-443 Mohammad Heib (3): Northd: Start tracking virtual port binding requests. Northd: Pause virtual port binding requests for crowded ports. controller: Drop binding requests for paused virtual port. controller/pinctrl.c | 39 - northd/northd.c | 186 +++ northd/northd.h | 2 + northd/ovn-northd.c | 3 + tests/ovn.at | 91 + 5 files changed, 319 insertions(+), 2 deletions(-) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn 2/3] Northd: Pause virtual port binding requests for crowded ports.
ovn-controller sends binding requests to update the virtual parent of a virtual port to northd, in some cases those requests are not handled immediately and ovn-controller keeps sending requests over and over which can lead to flooding northd with these requests. This patch add the ability to pause virtual ports that send so many binding requests to northd. Signed-off-by: Mohammad Heib --- northd/northd.c | 98 + 1 file changed, 98 insertions(+) diff --git a/northd/northd.c b/northd/northd.c index 7437b1dfe..49df463eb 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -3093,6 +3093,15 @@ ovn_port_update_sbrec(struct ovsdb_idl_txn *ovnsb_txn, "qdisc_queue_id", "%d", queue_id); } +if (smap_get_bool(&op->sb->options, +"binding_request_pause", false)) { +long long int p_time = smap_get_ullong(&op->sb->options, +"binding_request_pause_ts", 0); +smap_add_format(&options, "binding_request_pause_ts", +"%lld", p_time); +smap_add(&options, "binding_request_pause", "true"); +} + if (smap_get_bool(&op->od->nbs->other_config, "vlan-passthru", false)) { smap_add(&options, "vlan-passthru", "true"); } @@ -3830,6 +3839,90 @@ void destroy_tracked_virtual_ports(void) { hmap_destroy(&tracked_virtual_ports); } +/* + * For every virtual port that send request to update thier virtual_parent + * This function will update the following Port_binding options if needed: + * + * 1. tracked_virtual_port record belongs to this virtual port was created + *when this port created. This tracked struct have two main Fields: + * + * a. First_bind_in_tframe: this field will be set to the time that + * binding request were reicved for this vport for the first time + * within a timeframe. + * + * b. Bind_request_cnt: this filed will be incresses every time a binding + * request recived for that virtual port. + * + * + * 2. For each binding request received for a specific virtual port + * check if the time diff between now and the first time that a + * binding request were recived for this port within a pre-define + * timeframe is less than that timeframe. + * + * 3. If the previous condition true increase Bind_request_cnt and + * check if the total recived binding request recived for this port + * within a time fram exceeded the VPORT_MAX_BINDING_REQUEST_TRESHOLD + * set the Port_binding options: + * + * PB:OPTIONS:binding_request_pause=true + * PB:OPTIONS:binding_request_pause_ts=time_now + * + * + * 4. When ovn-controller recived a new GARP for this virtual port + * before sending a binding request update to northd it will check + * if the port have binding_request_pause=true, ovn-controller will do + * the following: + * + * If the PB:OPTIONS:binding_request_pause_ts + 10 seconds greater + * than the time now (GARP processing time), drop the GARP packet. + * + * Otherwise, set the PB:OPTIONS:binding_request_pause=false and resume + * binding request handling on this virtual port. + * + * + */ +static void +vport_binding_request_exceed_threshold(struct ovn_port *op) +{ +struct tracked_virtual_port * vport = + find_tracked_virtual_port(op->key); +if (op->sb != NULL) { +/* This port already paused or not found ignore it */ +if ((smap_get_bool(&op->sb->options, "binding_request_pause", + false) == true) || !vport) { +return; +} +} + +long long int cur_time = time_msec(); + +/* Still in the range of the time frame. */ +if ((vport->First_bind_in_tframe + VPORT_BINDING_TIMEFRAME) > cur_time) { +if (++vport->Bind_request_cnt > VPORT_MAX_BINDING_REQUEST_TRESHOLD) { +if (op->sb != NULL) { +static struct vlog_rate_limit rl = +VLOG_RATE_LIMIT_INIT(1, 1); +VLOG_WARN_RL(&rl, "Pausing virtual port %s from sending" +" binding requests for few seconds. " +" This port was paused in order to reduce the load on the" +" network.\n" , vport->name); +struct smap options; +smap_clone(&options, &op->sb->options); +smap_add(&options, "binding_request_pause", "true"); +smap_add_format(&options, "binding_request_pause_ts", "%lld", +
Re: [ovs-dev] [PATCH ovn] northd: Update virtual port when updating parent ports.
Hi Ilya, Thank you for your quick review On Thu, Jul 25, 2024 at 12:00 AM Ilya Maximets wrote: > On 7/24/24 11:56, Mohammad Heib wrote: > > Northd will not update/add flows for a virtual port if their > > parent ports were created/recreated after creating this virtual port. > > > > This change will fix the above issue by triggering an update for a > > virtual port if their parent port has been created. > > > > Rreported-at: https://issues.redhat.com/browse/FDP-710 > > Signed-off-by: Mohammad Heib > > --- > > northd/northd.c | 19 ++- > > tests/ovn.at| 84 + > > 2 files changed, 102 insertions(+), 1 deletion(-) > > > > Hi, Mohammad. Thanks for the patch! > See some comments inline. > > > diff --git a/northd/northd.c b/northd/northd.c > > index 5b50ea191..39c19b07f 100644 > > --- a/northd/northd.c > > +++ b/northd/northd.c > > @@ -4524,7 +4524,7 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn > *ovnsb_idl_txn, > > bool ls_had_only_router_ports = (od->n_router_ports > > && (od->n_router_ports == hmap_count(&od->ports))); > > > > -struct ovn_port *op; > > +struct ovn_port *op, *op_v; > > HMAP_FOR_EACH (op, dp_node, &od->ports) { > > op->visited = false; > > } > > @@ -4547,6 +4547,23 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn > *ovnsb_idl_txn, > > goto fail; > > } > > add_op_to_northd_tracked_ports(&trk_lsps->created, op); > > + > > +/* > > + * Update old virtual ports that had this VIF as parent port > > + * this code handles cases where the virtual port was > created > > + * before the parent port or when the parent port was > recreated. > > + */ > > +if (!strcmp(new_nbsp->type, "")) { > > +for (size_t i = 0; i < changed_ls->n_ports; i++) { > > This seems inefficient and may potentially tank performance at scale. > There should be a way to find all these ports without introducing > quadratic complexity. > yes, I agree that code is inefficient. > > On option might be to iterate once, if trk_lsps->created is not empty > after the loop, find all the parent ports and check if they are in > trk_lsps->created. > if you please can take a look at v2 <https://patchwork.ozlabs.org/project/ovn/patch/20240725072049.3884358-1-mh...@redhat.com/>, i adopted your idea with some changes. First, i will save all existing virtual ports during the first loop, these ports are already exist so no need to check if they are in both updated and created lists. afterward, at the end of the function, i will go through all the found virtual ports and for each vport i will check if one of the newly created port is a parent, and if so i will add it to the update list. worst case scenario complexity will be: Number of existing virtual ports * the number of newly created ports. which i think is the best i can do :(. > > Not sure if that's the most efficient way, but seems better than > quadratic. What do you think? > > > +op_v = ovn_port_find_in_datapath(od, > changed_ls->ports[i]); > > +if (op_v && !strcmp(op_v->nbsp->type, "virtual") && > > +strstr(smap_get_def(&op_v->nbsp->options, > > + "virtual-parents", ""), new_nbsp->name)) > { > > + > add_op_to_northd_tracked_ports(&trk_lsps->updated, > > + op_v); > > Is there a chance that these ports end up in both updated and created? > Can this cause issues later? > > Best regards, Ilya Maximets. > > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v2] northd: Update virtual port when updating parent ports.
Northd will not update/add flows for a virtual port if their parent ports were created/recreated after creating this virtual port. This change will fix the above issue by triggering an update for a virtual port if their parent port has been created. Rreported-at: https://issues.redhat.com/browse/FDP-710 Signed-off-by: Mohammad Heib --- northd/northd.c | 28 + tests/ovn.at| 84 + 2 files changed, 112 insertions(+) diff --git a/northd/northd.c b/northd/northd.c index 5b50ea191..0db0ba006 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -4525,6 +4525,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, && (od->n_router_ports == hmap_count(&od->ports))); struct ovn_port *op; +struct ovs_list exist_virtual_ports; +ovs_list_init(&exist_virtual_ports); HMAP_FOR_EACH (op, dp_node, &od->ports) { op->visited = false; } @@ -4588,6 +4590,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, delete_fdb_entry(ni->sbrec_fdb_by_dp_and_port, od->tunnel_key, old_tunnel_key); } +} else if (!strcmp(op->nbsp->type, "virtual")) { +ovs_list_push_back(&exist_virtual_ports, &op->list); } op->visited = true; } @@ -4628,6 +4632,30 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, } } +/* + * Update old virtual ports that have new created VIF as parent port + * this code handles cases where the virtual port was created + * before the parent port or when the parent port was recreated. + */ + if (!ovs_list_is_empty(&exist_virtual_ports)) { + struct hmapx_node *hmapx_node; + struct ovn_port *new_op; + LIST_FOR_EACH (op, list, &exist_virtual_ports) { + ovs_list_remove(&op->list); + HMAPX_FOR_EACH (hmapx_node, &trk_lsps->created) { + new_op = hmapx_node->data; + if (strstr(smap_get_def(&op->nbsp->options, + "virtual-parents", ""), new_op->nbsp->name)) { + add_op_to_northd_tracked_ports(&trk_lsps->updated, op); + /* Can stop the loop cause we have at lest one new parent + * created, no need to check the rest. + */ + break; + } + } + } + } + return true; fail: diff --git a/tests/ovn.at b/tests/ovn.at index 2ced7c0b2..83fba4f11 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -22439,6 +22439,90 @@ OVN_CLEANUP([hv1], [hv2]) AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD([ +AT_SETUP([virtual port - parents port re-create]) +AT_KEYWORDS([virtual ports]) +ovn_start +send_garp() { +local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6 +local request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa} +as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request +} + +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovn-appctl vlog/set dbg +ovs-vsctl -- add-port br-int hv1-vif1 -- \ +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ +options:tx_pcap=hv1/vif1-tx.pcap \ +options:rxq_pcap=hv1/vif1-rx.pcap \ +ofport-request=1 + +ovs-appctl -t ovn-controller vlog/set dbg + +ovn-nbctl ls-add sw0 +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3 1000::3" +check ovn-nbctl lsp-set-port-security sw0-p1 "50:54:00:00:00:03 10.0.0.3 10.0.0.10 1000::3" + +check ovn-nbctl lsp-add sw0 sw0-vir +check ovn-nbctl lsp-set-addresses sw0-vir "50:54:00:00:00:10 10.0.0.10" +check ovn-nbctl lsp-set-port-security sw0-vir "50:54:00:00:00:10 10.0.0.10" +check ovn-nbctl lsp-set-type sw0-vir virtual +check ovn-nbctl set logical_switch_port sw0-vir options:virtual-ip=10.0.0.10 +check ovn-nbctl set logical_switch_port sw0-vir options:virtual-parents=sw0-p1 + +wait_for_ports_up +ovn-nbctl --wait=hv sync +hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"` + +# From sw0-p1 send GARP for 10.0.0.10. hv1 should claim sw0-vir +# and sw0-p1 should be its virtual_parent. +eth_src=50540003 +eth_dst= +spa=$(ip_to_hex 10 0 0 10) +tpa=$(ip_to_hex 10 0 0 10) +send_garp 1 1 $eth_src $eth_dst $spa $tpa + +OVS_WAIT_UNTIL([test 1 = `cat hv1/ovn-controller.log | grep "pinctrl received packet-in" | \ +grep opcode=BIND_VPORT | grep OF_Table_ID=$(ovn-debug lflow-stage-to-oftable ls_in_arp_rsp) | wc -l`]) +wait_row_count Port_Binding 1 logical_port=sw0-vir chassis=$hv1_ch_uuid +check_row_count Port_Binding 1 logical_port=sw0-vir virtual_parent=sw0-p1 +wait_for_port
[ovs-dev] [PATCH ovn] northd: Update virtual port when updating parent ports.
Northd will not update/add flows for a virtual port if their parent ports were created/recreated after creating this virtual port. This change will fix the above issue by triggering an update for a virtual port if their parent port has been created. Rreported-at: https://issues.redhat.com/browse/FDP-710 Signed-off-by: Mohammad Heib --- northd/northd.c | 19 ++- tests/ovn.at| 84 + 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/northd/northd.c b/northd/northd.c index 5b50ea191..39c19b07f 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -4524,7 +4524,7 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, bool ls_had_only_router_ports = (od->n_router_ports && (od->n_router_ports == hmap_count(&od->ports))); -struct ovn_port *op; +struct ovn_port *op, *op_v; HMAP_FOR_EACH (op, dp_node, &od->ports) { op->visited = false; } @@ -4547,6 +4547,23 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, goto fail; } add_op_to_northd_tracked_ports(&trk_lsps->created, op); + +/* + * Update old virtual ports that had this VIF as parent port + * this code handles cases where the virtual port was created + * before the parent port or when the parent port was recreated. + */ +if (!strcmp(new_nbsp->type, "")) { +for (size_t i = 0; i < changed_ls->n_ports; i++) { +op_v = ovn_port_find_in_datapath(od, changed_ls->ports[i]); +if (op_v && !strcmp(op_v->nbsp->type, "virtual") && +strstr(smap_get_def(&op_v->nbsp->options, + "virtual-parents", ""), new_nbsp->name)) { +add_op_to_northd_tracked_ports(&trk_lsps->updated, + op_v); +} +} +} } else if (ls_port_has_changed(new_nbsp)) { /* Existing port updated */ bool temp = false; diff --git a/tests/ovn.at b/tests/ovn.at index 13b393932..93774b717 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -22439,6 +22439,90 @@ OVN_CLEANUP([hv1], [hv2]) AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD([ +AT_SETUP([virtual port - parents port re-create]) +AT_KEYWORDS([virtual ports]) +ovn_start +send_garp() { +local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6 +local request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa} +as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request +} + +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovn-appctl vlog/set dbg +ovs-vsctl -- add-port br-int hv1-vif1 -- \ +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ +options:tx_pcap=hv1/vif1-tx.pcap \ +options:rxq_pcap=hv1/vif1-rx.pcap \ +ofport-request=1 + +ovs-appctl -t ovn-controller vlog/set dbg + +ovn-nbctl ls-add sw0 +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3 1000::3" +check ovn-nbctl lsp-set-port-security sw0-p1 "50:54:00:00:00:03 10.0.0.3 10.0.0.10 1000::3" + +check ovn-nbctl lsp-add sw0 sw0-vir +check ovn-nbctl lsp-set-addresses sw0-vir "50:54:00:00:00:10 10.0.0.10" +check ovn-nbctl lsp-set-port-security sw0-vir "50:54:00:00:00:10 10.0.0.10" +check ovn-nbctl lsp-set-type sw0-vir virtual +check ovn-nbctl set logical_switch_port sw0-vir options:virtual-ip=10.0.0.10 +check ovn-nbctl set logical_switch_port sw0-vir options:virtual-parents=sw0-p1 + +wait_for_ports_up +ovn-nbctl --wait=hv sync +hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"` + +# From sw0-p1 send GARP for 10.0.0.10. hv1 should claim sw0-vir +# and sw0-p1 should be its virtual_parent. +eth_src=50540003 +eth_dst= +spa=$(ip_to_hex 10 0 0 10) +tpa=$(ip_to_hex 10 0 0 10) +send_garp 1 1 $eth_src $eth_dst $spa $tpa + +OVS_WAIT_UNTIL([test 1 = `cat hv1/ovn-controller.log | grep "pinctrl received packet-in" | \ +grep opcode=BIND_VPORT | grep OF_Table_ID=$(ovn-debug lflow-stage-to-oftable ls_in_arp_rsp) | wc -l`]) +wait_row_count Port_Binding 1 logical_port=sw0-vir chassis=$hv1_ch_uuid +check_row_count Port_Binding 1 logical_port=sw0-vir virtual_parent=sw0-p1 +wait_for_ports_up sw0-vir + +# Delete parent port +check ovn-nbctl lsp-del sw0-p1 +ovn-nbctl --wait=hv sync + +# Re-add parent port +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3 1000::3" +check ovn-nbctl lsp-set-port-security sw0-p1 "50:54:00:00:00:03 10.0.0.3 10.0.0.10 1000::3" + +wait_for
Re: [ovs-dev] [PATCH ovn 3/4] Revert "northd: Don't skip transit switch LSP when creating mcast groups."
On Tue, Jun 18, 2024 at 4:32 PM Dumitru Ceara wrote: > This reverts commit 85ca2b75369c9a73f4750d5914666a54ebb3f2e0. > > The commit above breaks inter-AZ IP multicast for the case when one of > the multicast receivers is co-located in the same zone as the sender. > In those cases traffic is not correctly forwarded to other receivers > that joined the group in other AZs. > > This is often the case in ovn-kubernetes deployments (with IC enabled). > The current "interconnection - IGMP/MLD multicast" unit test failed to > cover such topologies. > > CC: Mohammad Heib > Fixes: 85ca2b75369c ("northd: Don't skip transit switch LSP when creating > mcast groups.") > Reported-at: https://issues.redhat.com/browse/FDP-656 > Signed-off-by: Dumitru Ceara > --- > northd/northd.c | 8 +++- > northd/northd.h | 6 -- > tests/ovn-ic.at | 10 -- > 3 files changed, 3 insertions(+), 21 deletions(-) > > diff --git a/northd/northd.c b/northd/northd.c > index 3c1affb02f..7e474a7b89 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -5434,13 +5434,11 @@ ovn_igmp_group_get_ports(const struct > sbrec_igmp_group *sb_igmp_group, > continue; > } > > -/* If this is already a port of a router on which relay is enabled > - * and it's not a transit switch to router port, skip it for the > - * group. Traffic is flooded there anyway. > +/* If this is already a port of a router on which relay is > enabled, > + * skip it for the group. Traffic is flooded there anyway. > */ > if (port->peer && port->peer->od && > -port->peer->od->mcast_info.rtr.relay && > -!ovn_datapath_is_transit_switch(port->od)) { > +port->peer->od->mcast_info.rtr.relay) { > continue; > } > > diff --git a/northd/northd.h b/northd/northd.h > index 146139bebc..fd884c851e 100644 > --- a/northd/northd.h > +++ b/northd/northd.h > @@ -362,12 +362,6 @@ ovn_datapath_is_stale(const struct ovn_datapath *od) > return !od->nbr && !od->nbs; > }; > > -static inline bool > -ovn_datapath_is_transit_switch(const struct ovn_datapath *od) > -{ > -return od->tunnel_key >= OVN_MIN_DP_KEY_GLOBAL; > -} > - > /* Pipeline stages. */ > > /* The two purposes for which ovn-northd uses OVN logical datapaths. */ > diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at > index 1666e77295..20409f70ac 100644 > --- a/tests/ovn-ic.at > +++ b/tests/ovn-ic.at > @@ -2042,20 +2042,10 @@ wait_row_count IGMP_Group 2 address=239.0.1.68 > wait_row_count IGMP_Group 2 address='"ff0a:dead:beef::1"' > check ovn-nbctl --wait=hv sync > > -#Validate that Multicast Group contains all registered ports for > -# specific igmp group. > -ts_dp=$(fetch_column datapath_binding _uuid external_ids:name=ts) > -ports=$(fetch_column multicast_group ports name="239.0.1.68" > datapath=$ts_dp) > -check test X2 = X$(echo $ports | wc -w) > - > - > ovn_as az2 > wait_row_count IGMP_Group 2 address=239.0.1.68 > wait_row_count IGMP_Group 2 address='"ff0a:dead:beef::1"' > check ovn-nbctl --wait=hv sync > -ts_dp=$(fetch_column datapath_binding _uuid external_ids:name=ts) > -ports=$(fetch_column multicast_group ports name="239.0.1.68" > datapath=$ts_dp) > -check test X2 = X$(echo $ports | wc -w) > > # Send an IP multicast packet from LSP2, it should be forwarded > # to lsp1 and lsp3. > -- > 2.44.0 > > looks good to me, thanks Dumitru. Acked-by: Mohammad Heib ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn 1/4] Revert "IC: Tansit switch don't flood mcast traffic to router ports if matches igmp group."
Acked-by: Mohammad Heib Thanks On Tue, Jun 18, 2024 at 4:42 PM 0-day Robot wrote: > Bleep bloop. Greetings Dumitru Ceara, I am a robot and I have tried out > your patch. > Thanks for your contribution. > > I encountered some error that I wasn't expecting. See the details below. > > > checkpatch: > WARNING: The subject, ': ', is over 70 characters, i.e., 91. > WARNING: The subject summary should end with a dot. > Subject: Revert "IC: Tansit switch don't flood mcast traffic to router > ports if matches igmp group." > Lines checked: 90, Warnings: 2, Errors: 0 > > > Please check this out. If you feel there has been an error, please email > acon...@redhat.com > > Thanks, > 0-day Robot > ___ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn 2/2] IC: Tansit switch don't flood mcast traffic to router ports if matches igmp group.
Crrently ovn transit switch forward mcast traffic that match an igmp group to all ports participating in this group and to all router ports that are connected to this TS switch and have mcast_flood enabled. The above behavior can lead to packet duplicate if we have a VM in a specific AZ that participates in igmp group because the gateway router in this AZ will forward igmp membership report from the VM to the TS which will be learned as an IGMP_group on the Tansit switch in different AZs and every mcast traffic to that igmp group address from the different AZs will be handled by the Tansit switch twice: - First time TS will send the traffic according to the igmp group which will reach the VM. - Second time TS will send the traffic to all router ports including the router that exists on the VM AZ which will forward the traffic to the VM again. To avoid this issue this patch adds flows that forward mcast traffic that match igmp group to the igmp group ports only, this flows only apply to Transit switches. Rreported-at: https://issues.redhat.com/browse/FDP-101 Signed-off-by: Mohammad Heib --- northd/northd.c | 18 ++ northd/ovn-northd.8.xml | 7 +++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/northd/northd.c b/northd/northd.c index 98c837a20..0c5122d27 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -9362,8 +9362,14 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, } -/* Ingress table 25: Add IP multicast flows learnt from IGMP/MLD - * (priority 90). */ +/* Ingress table 27: Add IP multicast flows learnt from IGMP/MLD + * (priority 90). + * + * Ingress table 27: Transit switch add IP multicast flows learnt + * from IGMP/MLD to forward traffic explicitly to the ports that are + * part of the IGMP/MLD group, and ignore MROUTERAS Ports. + * (priority 95). + */ static void build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, struct lflow_table *lflows, @@ -9377,6 +9383,9 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, ds_clear(match); ds_clear(actions); +bool transit_switch = +ovn_datapath_is_transit_switch(igmp_group->datapath); + struct mcast_switch_info *mcast_sw_info = &igmp_group->datapath->mcast_info.sw; uint64_t table_size = mcast_sw_info->table_size; @@ -9422,7 +9431,7 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, } /* Also flood traffic to all multicast routers with relay enabled. */ -if (mcast_sw_info->flood_relay) { +if (mcast_sw_info->flood_relay && !transit_switch) { ds_put_cstr(actions, "clone { " "outport = \""MC_MROUTER_FLOOD "\"; " @@ -9440,7 +9449,8 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, igmp_group->mcgroup.name); ovn_lflow_add(lflows, igmp_group->datapath, S_SWITCH_IN_L2_LKUP, - 90, ds_cstr(match), ds_cstr(actions), NULL); + transit_switch? 95 : 90, ds_cstr(match), + ds_cstr(actions), NULL); } } diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 17b414144..e25285d67 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -1933,6 +1933,13 @@ output; logical switch. + +Priority-95 flows for transit switches only that forward registered +IP multicast traffic to their corresponding multicast group , which +ovn-northd creates based on learnt + entries. + + Priority-90 flows that forward registered IP multicast traffic to their corresponding multicast group, which ovn-northd -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn 1/2] northd: Don't skip transit switch LSP when creating mcast groups.
Currently when we enable IGMP on OVN-IC cluster with two or more AZs and one vm from AZ1 send IGMP report, northd will create the following multicast_group on each AZ: AZ1: 1. multicast_group that forward the mcast traffic from LS1 to the VM. 2. multicast_group that forward the mcast traffic from LR1 to the LS1. AZ2: 1. multicast_group that forward the mcast traffic from TS to LR1 in AZ1. This design works fine if we have one logical network only on each AZ, but if we have two or more logical network on the same AZ that separated from each other and only connected via transit switch and both join the same mcast network, the traffic will be delivered between those two networks because ovn floods it to all routers that connected to the transit switch (see logical flow table 27). The above design is not the right way to handle such mcast traffic because future changes for ovn that make it match explicitly on the igmp group address and not forward traffic to routers can break the mcast traffic in ovn-ic. This patch updates the above design by adding the router port that connects to the transit switch to the multicast_group even if the peer port have mcast_flood enabled. Signed-off-by: Mohammad Heib --- northd/northd.c | 8 +--- northd/northd.h | 6 ++ tests/ovn.at| 10 ++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/northd/northd.c b/northd/northd.c index 1839b7d8b..98c837a20 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -5377,11 +5377,13 @@ ovn_igmp_group_get_ports(const struct sbrec_igmp_group *sb_igmp_group, continue; } -/* If this is already a port of a router on which relay is enabled, - * skip it for the group. Traffic is flooded there anyway. +/* If this is already a port of a router on which relay is enabled + * and it's not a transit switch to router port,skip it for the group. + * Traffic is flooded there anyway. */ if (port->peer && port->peer->od && -port->peer->od->mcast_info.rtr.relay) { +port->peer->od->mcast_info.rtr.relay && +!ovn_datapath_is_transit_switch(port->od)) { continue; } diff --git a/northd/northd.h b/northd/northd.h index 3f1cd8341..5e9fa4745 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -362,6 +362,12 @@ ovn_datapath_is_stale(const struct ovn_datapath *od) return !od->nbr && !od->nbs; }; +static inline bool +ovn_datapath_is_transit_switch(const struct ovn_datapath *od) +{ +return od->tunnel_key >= OVN_MIN_DP_KEY_GLOBAL; +} + /* Pipeline stages. */ /* The two purposes for which ovn-northd uses OVN logical datapaths. */ diff --git a/tests/ovn.at b/tests/ovn.at index 438c7690a..4a9e433b2 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -26903,10 +26903,20 @@ wait_row_count IGMP_Group 2 address=239.0.1.68 wait_row_count IGMP_Group 2 address='"ff0a:dead:beef::1"' check ovn-nbctl --wait=hv sync +#Validate that Multicast Group contains all registered ports for +# specific igmp group. +ts_dp=$(fetch_column datapath_binding _uuid external_ids:name=ts) +ports=$(fetch_column multicast_group ports name="239.0.1.68" datapath=$ts_dp) +check test X2 = X$(echo $ports | wc -w) + + ovn_as az2 wait_row_count IGMP_Group 2 address=239.0.1.68 wait_row_count IGMP_Group 2 address='"ff0a:dead:beef::1"' check ovn-nbctl --wait=hv sync +ts_dp=$(fetch_column datapath_binding _uuid external_ids:name=ts) +ports=$(fetch_column multicast_group ports name="239.0.1.68" datapath=$ts_dp) +check test X2 = X$(echo $ports | wc -w) # Send an IP multicast packet from LSP2, it should be forwarded # to lsp1 and lsp3. -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [RFC ovn] ovn-ic: avoid igmp/mld traffic flooding
Hi Lorenzo, i have applied and tested this change and i can confirm that it fixes the issue. if you please can rebase on top of the main. Acked-by: Mohammad Heib On Thu, Oct 19, 2023 at 7:47 PM Lorenzo Bianconi < lorenzo.bianc...@redhat.com> wrote: > Avoid recirculating IGMP/MLD packets more than one time from stage > ls_out_pre_lb in the egress pipeline to ovn table 37 in order to avoid > packet looping for ovn-ic deployment. > > Signed-off-by: Lorenzo Bianconi > --- > controller/pinctrl.c | 2 ++ > include/ovn/logical-fields.h | 3 +++ > lib/logical-fields.c | 4 > northd/northd.c | 11 +++ > 4 files changed, 16 insertions(+), 4 deletions(-) > > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > index 3c1cecfde..d4ae7de46 100644 > --- a/controller/pinctrl.c > +++ b/controller/pinctrl.c > @@ -650,6 +650,8 @@ pinctrl_forward_pkt(struct rconn *swconn, int64_t > dp_key, > put_load(dp_key, MFF_LOG_DATAPATH, 0, 64, &ofpacts); > put_load(in_port_key, MFF_LOG_INPORT, 0, 32, &ofpacts); > put_load(out_port_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts); > +/* Avoid re-injecting packet already consumed. */ > +put_load(1, MFF_LOG_FLAGS, MLF_IGMP_IGMP_SPOOF_INJECT_BIT, 1, > &ofpacts); > > struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); > resubmit->in_port = OFPP_CONTROLLER; > diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h > index a7b64ef67..0652af380 100644 > --- a/include/ovn/logical-fields.h > +++ b/include/ovn/logical-fields.h > @@ -77,6 +77,7 @@ enum mff_log_flags_bits { > MLF_CHECK_PORT_SEC_BIT = 12, > MLF_LOOKUP_COMMIT_ECMP_NH_BIT = 13, > MLF_USE_LB_AFF_SESSION_BIT = 14, > +MLF_IGMP_IGMP_SPOOF_INJECT_BIT = 15, > }; > > /* MFF_LOG_FLAGS_REG flag assignments */ > @@ -124,6 +125,8 @@ enum mff_log_flags { > MLF_LOOKUP_COMMIT_ECMP_NH = (1 << MLF_LOOKUP_COMMIT_ECMP_NH_BIT), > > MLF_USE_LB_AFF_SESSION = (1 << MLF_USE_LB_AFF_SESSION_BIT), > + > +MLF_IGMP_IGMP_SPOOF = (1 << MLF_IGMP_IGMP_SPOOF_INJECT_BIT), > }; > > /* OVN logical fields > diff --git a/lib/logical-fields.c b/lib/logical-fields.c > index fd509d9ee..3d8d5f950 100644 > --- a/lib/logical-fields.c > +++ b/lib/logical-fields.c > @@ -129,6 +129,10 @@ ovn_init_symtab(struct shash *symtab) > MLF_USE_SNAT_ZONE); > expr_symtab_add_subfield(symtab, "flags.use_snat_zone", NULL, > flags_str); > +snprintf(flags_str, sizeof flags_str, "flags[%d]", > + MLF_IGMP_IGMP_SPOOF_INJECT_BIT); > +expr_symtab_add_subfield(symtab, "flags.igmp_loopback", NULL, > + flags_str); > > /* Connection tracking state. */ > expr_symtab_add_field_scoped(symtab, "ct_mark", MFF_CT_MARK, NULL, > false, > diff --git a/northd/northd.c b/northd/northd.c > index 916068d44..557fcca72 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -7323,7 +7323,8 @@ build_interconn_mcast_snoop_flows(struct > ovn_datapath *od, > continue; > } > /* Punt IGMP traffic to controller. */ > -char *match = xasprintf("inport == %s && igmp", op->json_key); > +char *match = xasprintf("inport == %s && igmp && " > +"flags.igmp_loopback == 0", op->json_key); > ovn_lflow_metered(lflows, od, S_SWITCH_OUT_PRE_LB, 120, match, >"clone { igmp; }; next;", >copp_meter_get(COPP_IGMP, od->nbs->copp, > @@ -7331,7 +7332,8 @@ build_interconn_mcast_snoop_flows(struct > ovn_datapath *od, > free(match); > > /* Punt MLD traffic to controller. */ > -match = xasprintf("inport == %s && (mldv1 || mldv2)", > op->json_key); > +match = xasprintf("inport == %s && (mldv1 || mldv2) && " > + "flags.igmp_loopback == 0", op->json_key); > ovn_lflow_metered(lflows, od, S_SWITCH_OUT_PRE_LB, 120, match, >"clone { igmp; }; next;", >copp_meter_get(COPP_IGMP, od->nbs->copp, > @@ -10317,13 +10319,14 @@ build_lswitch_destination_lookup_bmcast(struct > ovn_datapath *od, > ds_put_cstr(actions, "igmp;"); > /* Punt IGMP traffic to controller. */ > ovn_lflow_metered(lflows, od, S_SWITCH_IN_L2_LKUP, 100, > - "
[ovs-dev] [PATCH ovn v2 1/2] tests: Move ovn interconnection tests to ovn-ic.at.
Move ovn-ic tests that exist in ovn.at to ovn-ic.at. Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 687 tests/ovn.at| 686 --- 2 files changed, 687 insertions(+), 686 deletions(-) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index 44dbf8ab1..12267e960 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -1442,3 +1442,690 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([interconnection]) +AT_KEYWORDS([slowtest]) + +ovn_init_ic_db +# The number needs to stay relatively low due to high memory consumption +# with address sanitizers enabled. +n_az=3 +n_ts=3 +for i in `seq 1 $n_az`; do +ovn_start az$i +done + +net_add n1 + +# 1 HV and 1 GW per AZ +for az in `seq 1 $n_az`; do +sim_add hv$az +as hv$az +check ovs-vsctl add-br br-phys +ovn_az_attach az$az n1 br-phys 192.168.$az.1 16 +for p in `seq 1 $n_ts`; do +check ovs-vsctl -- add-port br-int vif$p -- \ +set interface vif$p external-ids:iface-id=lsp$az-$p \ +options:tx_pcap=hv$az/vif$p-tx.pcap \ +options:rxq_pcap=hv$az/vif$p-rx.pcap \ +ofport-request=$p +done + +sim_add gw$az +as gw$az +check ovs-vsctl add-br br-phys +ovn_az_attach az$az n1 br-phys 192.168.$az.2 16 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true +done + +for ts in `seq 1 $n_ts`; do +AT_CHECK([ovn-ic-nbctl create Transit_Switch name=ts$ts], [0], [ignore]) +for az in `seq 1 $n_az`; do +echo "az$az: wait for ts$ts..." +check ovn_as az$az ovn-nbctl wait-until logical_switch ts$ts +done +done + +for az in `seq 1 $n_az`; do +ovn_as az$az +check ovn-nbctl set nb_global . options:ic-route-learn=true +check ovn-nbctl set nb_global . options:ic-route-adv=true + +# Each AZ has n_ts LSPi->LSi->LRi connecting to each TSi +echo +echo "az$az" +for i in `seq 1 $n_ts`; do +lsp_mac=00:00:00:0$az:0$i:00 +lrp_ls_mac=00:00:00:0$az:0$i:01 +lrp_ts_mac=00:00:00:0$az:0$i:02 +lsp_ip=10.$az.$i.123 +lrp_ls_ip=10.$az.$i.1 +lrp_ts_ip=169.254.$i.$az + +check ovn-nbctl ls-add ls$az-$i +check ovn-nbctl lsp-add ls$az-$i lsp$az-$i +check ovn-nbctl lsp-set-addresses lsp$az-$i "$lsp_mac $lsp_ip" + +check ovn-nbctl lr-add lr$az-$i + +check ovn-nbctl lrp-add lr$az-$i lrp-lr$az-$i-ls$az-$i $lrp_ls_mac $lrp_ls_ip/24 +check ovn-nbctl lsp-add ls$az-$i lsp-ls$az-$i-lr$az-$i +check ovn-nbctl lsp-set-addresses lsp-ls$az-$i-lr$az-$i router +check ovn-nbctl lsp-set-type lsp-ls$az-$i-lr$az-$i router +check ovn-nbctl lsp-set-options lsp-ls$az-$i-lr$az-$i router-port=lrp-lr$az-$i-ls$az-$i + +check ovn-nbctl lrp-add lr$az-$i lrp-lr$az-$i-ts$i $lrp_ts_mac $lrp_ts_ip/24 +check ovn-nbctl lsp-add ts$i lsp-ts$i-lr$az-$i +check ovn-nbctl lsp-set-addresses lsp-ts$i-lr$az-$i router +check ovn-nbctl lsp-set-type lsp-ts$i-lr$az-$i router +check ovn-nbctl lsp-set-options lsp-ts$i-lr$az-$i router-port=lrp-lr$az-$i-ts$i +check ovn-nbctl lrp-set-gateway-chassis lrp-lr$az-$i-ts$i gw$az +done +check ovn-nbctl --wait=hv sync +ovn-sbctl list Port_Binding > az$az.ports +wait_for_ports_up +done + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +for i in `seq 1 $n_az`; do +check ovn_as az$i ovn-nbctl --wait=hv sync +ovn_as az$i ovn-sbctl dump-flows > az$i/sbflows +done + +# Allow some time for ovn-northd and ovn-controller to catch up. +# XXX This should be more systematic. +sleep 2 + +# Populate requested-chassis options for remote lsps +for az in $(seq 1 $n_az); do +ovn_as az${az} +for ts in $(seq 1 $n_ts); do +for i in $(seq 1 $n_ts); do +if [[ $i -eq ${az} ]]; then +continue +fi +check ovn-nbctl lsp-set-options lsp-ts${ts}-lr${i}-${ts} requested-chassis=gw$i +done +done +done + +ovn-ic-nbctl show > ic-nbctl.dump +AT_CAPTURE_FILE([ic-nbctl.dump]) + +(echo "-ISB dump-" + ovn-ic-sbctl show + echo "-" + ovn-ic-sbctl list gateway + echo "-" + ovn-ic-sbctl list datapath_binding + echo "-" + ovn-ic-sbctl list port_binding + echo "-" + ovn-ic-sbctl list route + echo "-") > ic-sbctl.dump +AT_CAPTURE_FILE([ic-sbctl.dump]) + +AT_CAPTURE_FILE([expected]) +AT_CAPTURE_FILE([received]) +check_packets() { +> expected +> received +for az in `seq 1 $n_az`; do +for i in `seq 1 $n_ts`; do +p
[ovs-dev] [PATCH ovn v2 2/2] tests: Use sync command in ovn-ic tests.
Use the sync commands in the ovn-ic unit tests and remove lines that wait for IC-SB to sync with IC-NB. Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 178 1 file changed, 72 insertions(+), 106 deletions(-) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index 12267e960..4a24e171b 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -6,7 +6,7 @@ ovn_init_ic_db ovn_start az1 ovn_start az2 -wait_row_count ic-sb:Availability_Zone 2 +check ovn-ic-nbctl --wait=sb sync AT_CHECK([ovn-ic-sbctl show], [0], [dnl availability-zone az1 availability-zone az2 @@ -31,7 +31,6 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) - OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-ic -- AZ update in GW]) ovn_init_ic_db @@ -47,10 +46,12 @@ check ovs-vsctl set open . external-ids:ovn-is-interconn=true az_uuid=$(fetch_column ic-sb:availability-zone _uuid name="az1") ovn_as az1 ovn-nbctl set NB_Global . name="az2" -wait_column "$az_uuid" ic-sb:availability-zone _uuid name="az2" + +check ovn-ic-nbctl --wait=sb sync +check_column "$az_uuid" ic-sb:availability-zone _uuid name="az2" # make sure that gateway still point to the same AZ with new name -wait_column "$az_uuid" ic-sb:gateway availability_zone name="gw-az1" +check_column "$az_uuid" ic-sb:gateway availability_zone name="gw-az1" OVN_CLEANUP_IC([az1]) AT_CLEANUP @@ -66,11 +67,11 @@ ovn_start az1 ovn-sbctl chassis-add fakechassis vxlan 192.168.0.2 AT_CHECK([ovn-ic-nbctl ts-add ts1]) -AT_CHECK([ovn-ic-nbctl ts-add ts2]) +AT_CHECK([ovn-ic-nbctl --wait=sb ts-add ts2]) # Check ISB -wait_row_count ic-sb:Datapath_Binding 1 transit_switch=ts1 -wait_row_count ic-sb:Datapath_Binding 1 transit_switch=ts2 +check_row_count ic-sb:Datapath_Binding 1 transit_switch=ts1 +check_row_count ic-sb:Datapath_Binding 1 transit_switch=ts2 check_column "ts1 ts2" ic-sb:Datapath_Binding transit_switch check_column "ts1 ts2" nb:Logical_Switch name @@ -81,8 +82,8 @@ ts1_key=$(fetch_column ic-sb:Datapath_Binding tunnel_key transit_switch=ts1) check_column "$ts1_key" Datapath_Binding tunnel_key external_ids:interconn-ts=ts1 # Test delete -AT_CHECK([ovn-ic-nbctl ts-del ts1]) -wait_row_count ic-sb:Datapath_Binding 0 transit_switch=ts1 +AT_CHECK([ovn-ic-nbctl --wait=sb ts-del ts1]) +check_row_count ic-sb:Datapath_Binding 0 transit_switch=ts1 check_column ts2 ic-sb:Datapath_Binding transit_switch check_column ts2 nb:Logical_Switch name @@ -111,12 +112,11 @@ done ovn_as az1 # create transit switch and connect to LR -check ovn-ic-nbctl ts-add ts1 +check ovn-ic-nbctl --wait=sb ts-add ts1 check ovn-nbctl lr-add lr1 check ovn-nbctl lrp-add lr1 lrp1 00:00:00:00:00:01 10.0.0.1/24 check ovn-nbctl lrp-set-gateway-chassis lrp1 gw-az1 -OVS_WAIT_UNTIL([ovn-nbctl show | grep switch | grep ts1]) check ovn-nbctl lsp-add ts1 lsp1 -- \ lsp-set-addresses lsp1 router -- \ lsp-set-type lsp1 router -- \ @@ -124,8 +124,8 @@ check ovn-nbctl lsp-add ts1 lsp1 -- \ wait_row_count Datapath_Binding 1 external_ids:interconn-ts=ts1 -# check port binding appeared -OVS_WAIT_UNTIL([ovn-ic-sbctl show | grep lsp1]) +# Sync ic-sb DB to see the TS changes. +check ovn-ic-nbctl --wait=sb sync AT_CHECK([ovn-ic-sbctl show | grep -A2 lsp1], [0], [dnl port lsp1 @@ -134,8 +134,8 @@ AT_CHECK([ovn-ic-sbctl show | grep -A2 lsp1], [0], [dnl ]) # remove transit switch and check if port_binding is deleted -check ovn-ic-nbctl ts-del ts1 -wait_row_count ic-sb:Port_Binding 0 logical_port=lsp1 +check ovn-ic-nbctl --wait=sb ts-del ts1 +check_row_count ic-sb:Port_Binding 0 logical_port=lsp1 for i in 1 2; do az=az$i ovn_as $az @@ -180,8 +180,7 @@ create_ic_infra() { ovn_as $az -check ovn-ic-nbctl ts-add $ts -OVS_WAIT_UNTIL([ovn-nbctl show | grep switch | grep $ts]) +check ovn-ic-nbctl --wait=sb ts-add $ts check ovn-nbctl lr-add $lr check ovn-nbctl lrp-add $lr $lrp 00:00:00:00:00:0$az_id 10.0.$az_id.1/24 check ovn-nbctl lrp-set-gateway-chassis $lrp gw-$az @@ -197,18 +196,18 @@ create_ic_infra() { create_ic_infra 1 1 create_ic_infra 1 2 create_ic_infra 2 1 +check ovn-ic-nbctl --wait=sb sync ovn_as az1 -wait_row_count ic-sb:Route 3 ip_prefix=192.168.0.0/16 +check_row_count ic-sb:Route 3 ip_prefix=192.168.0.0/16 # remove transit switch 1 (from az1) and check if its route is deleted # same route from another AZ and ts should remain, as -check ovn-ic-nbctl ts-del ts1-1 -sleep 2 +check ovn-ic-nbctl --wait=sb ts-del ts1-1 ovn-ic-sbctl list route ovn-ic-nbctl list transit_switch -wait_row_count ic-sb:route 2 ip_prefix=192.168.0.0/16 +checl_row_count ic-sb:route 2 ip_prefix=192.168.0.0/16 ovn-ic-sbctl list route for i in 1 2; do @@ -246,7 +245,7 @@ done ovn_as az1 # create transit switch and connect to LR -check ovn-ic-nbctl ts-add ts1 +check ovn-ic-nbctl --w
[ovs-dev] [PATCH ovn v3] controller: Release container lport when releasing parent port.
Currently if the user sets the container parent_port:requested-chassis option after the VIF/CIF is bonded to the chassis, this will migrate the VIF/CIF flows to the new chassis but will still have the container flows installed in the old chassis which can allow unwanted tagged traffic to reach VMS/containers on the old chassis. This patch will resolve the above issue by remove the CIF flows from the old chassis and prevent the CIF from being bonded to a chassis different from the parent port VIF binding chassis. Rreported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2220938 Signed-off-by: Mohammad Heib --- controller/binding.c | 3 +++ controller/physical.c | 9 tests/ovn.at | 53 +++ 3 files changed, 65 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 2afc5d48a..c2d15a6c4 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -1710,6 +1710,9 @@ consider_container_lport(const struct sbrec_port_binding *pb, ovs_assert(parent_b_lport && parent_b_lport->pb); bool can_bind = lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, pb); +/* cannot bind to this chassis if the parent_port cannot be bounded. */ +can_bind &= lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, + parent_b_lport->pb); return consider_vif_lport_(pb, can_bind, b_ctx_in, b_ctx_out, container_b_lport); diff --git a/controller/physical.c b/controller/physical.c index 7ef259da4..86d4b4578 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -1631,6 +1631,15 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, nested_container = true; parent_port = lport_lookup_by_name( sbrec_port_binding_by_name, binding->parent_port); + +if (parent_port +&& !lport_can_bind_on_this_chassis(chassis, parent_port)) { +/* Even though there is an ofport for this container + * parent port, it is requested on different chassis ignore + * this container port. + */ +return; +} } } else if (!strcmp(binding->type, "localnet") || !strcmp(binding->type, "l2gateway")) { diff --git a/tests/ovn.at b/tests/ovn.at index d26c95054..6f0fc1043 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -38351,3 +38351,56 @@ OVS_WAIT_UNTIL([test 1 = $(as hv ovs-ofctl dump-flows br-int | grep -E "pkt_mark OVN_CLEANUP([hv]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller - cleanup VIF/CIF related flows/fields when updating requested-chassis]) +ovn_start + +net_add n1 +sim_add hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int vif1 -- \ +set Interface vif1 external-ids:iface-id=lsp1 \ +ofport-request=8 + +check ovn-nbctl ls-add lsw0 + +check ovn-nbctl lsp-add lsw0 lsp1 +check ovn-nbctl lsp-add lsw0 sw0-port1.1 lsp1 7 + +# wait for the VIF to be claimed to this chassis +wait_row_count Chassis 1 name=hv1 +hv1_uuid=$(fetch_column Chassis _uuid name=hv1) +wait_for_ports_up lsp1 +wait_for_ports_up sw0-port1.1 +wait_column "$hv1_uuid" Port_Binding chassis logical_port=lsp1 +wait_column "$hv1_uuid" Port_Binding chassis logical_port=sw0-port1.1 + +# check that flows is installed +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=100 | grep -c in_port=8], [0],[dnl +1 +]) +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [0],[dnl +1 +]) + +# set lport requested-chassis to differant chassis +check ovn-nbctl set Logical_Switch_Port lsp1 \ +options:requested-chassis=foo + +OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding lsp1 up` = 'false']) +OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding sw0-port1.1 up` = 'false']) +wait_column "" Port_Binding chassis logical_port=lsp1 +wait_column "" Port_Binding chassis logical_port=sw0-port1.1 + +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=100 |grep -c in_port=8], [1],[dnl +0 +]) +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=150|grep dl_vlan=7| grep -c in_port=8], [1],[dnl +0 +]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn v2] ci: Update crun in GitHub actions runner.
Hi Dumitru, Thank you for your review :) i was confused because the fix <https://noobient.com/2023/11/15/fixing-ubuntu-containers-failing-to-start-with-systemd/> mentioned Docker as well, but you are right the default is runc so we don't have to update the ovn-k workflow. addressed in v3 thanks On Wed, Feb 28, 2024 at 12:00 AM Dumitru Ceara wrote: > On 2/27/24 17:28, Mohammad Heib wrote: > > There are some issues with older crun and newer kernel > > combination [0]. Unfortunately Ubuntu 22.04 falls into this > > category and the jobs will often time fail. Temoprarily use > > newer crun from git that has the fix [1]. > > > > [0] https://github.com/containers/crun/pull/1309 > > [1] > https://noobient.com/2023/11/15/fixing-ubuntu-containers-failing-to-start-with-systemd/ > > > > Signed-off-by: Mohammad Heib > > --- > > Hi Mohammad, > > Thanks for working on fixing the CI! > > > .github/workflows/ovn-fake-multinode-tests.yml | 8 > > .github/workflows/ovn-kubernetes.yml | 8 > > .github/workflows/test.yml | 8 > > 3 files changed, 24 insertions(+) > > > > diff --git a/.github/workflows/ovn-fake-multinode-tests.yml > b/.github/workflows/ovn-fake-multinode-tests.yml > > index 179c1d662..79b6c4253 100644 > > --- a/.github/workflows/ovn-fake-multinode-tests.yml > > +++ b/.github/workflows/ovn-fake-multinode-tests.yml > > @@ -137,6 +137,14 @@ jobs: > > sudo systemctl start openvswitch-switch > > sudo ovs-vsctl show > > > > +# XXX This should be removed when native crun >=1.9.1 > > +- name: update crun script > > + run: | > > +crun --version > > +sudo curl -L " > https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; > -o /usr/bin/crun > > +sudo chmod +x /usr/bin/crun > > +echo "New crun version: "$(crun --version) > > + > > - name: Start basic cluster > >run: | > > sudo -E ./ovn_cluster.sh start > > diff --git a/.github/workflows/ovn-kubernetes.yml > b/.github/workflows/ovn-kubernetes.yml > > index 0f2b30497..09a838cfe 100644 > > --- a/.github/workflows/ovn-kubernetes.yml > > +++ b/.github/workflows/ovn-kubernetes.yml > > @@ -140,6 +140,14 @@ jobs: > >run: | > > docker load --input image.tar && rm -rf image.tar > > > > +# XXX This should be removed when native crun >=1.9.1 > > +- name: update crun script > > + run: | > > +crun --version > > +sudo curl -L " > https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; > -o /usr/bin/crun > > +sudo chmod +x /usr/bin/crun > > +echo "New crun version: "$(crun --version) > > + > > We don't install podman anywhere for ovn-kubernetes jobs (maybe we > should but that's a different story) so kind will use docker. I don't > think we need to update (install?) crun. AFAICT docker/containerd uses > runc as runtime so we shouldn't be having any issues for ovn-k jobs. > > What do you think? > > > - name: kind setup > >run: | > > export OVN_IMAGE="ovn-daemonset-f:dev" > > diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml > > index 2def39531..0cb981775 100644 > > --- a/.github/workflows/test.yml > > +++ b/.github/workflows/test.yml > > @@ -217,6 +217,14 @@ jobs: > > path: /tmp/image.tar > > key: ${{ github.sha }} > > > > +# XXX This should be removed when native crun >=1.9.1 > > +- name: update crun script > > + run: | > > +crun --version > > +sudo curl -L " > https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; > -o /usr/bin/crun > > +sudo chmod +x /usr/bin/crun > > +echo "New crun version: "$(crun --version) > > + > > - name: load image > >run: | > > sudo podman load -i /tmp/image.tar > > The rest looks good to me, thanks! > > Regards, > Dumitru > > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v3] ci: Update crun in GitHub actions runner.
There are some issues with older crun and newer kernel combination [0]. Unfortunately Ubuntu 22.04 falls into this category and the jobs will often time fail. Temoprarily use newer crun from git that has the fix [1]. [0] https://github.com/containers/crun/pull/1309 [1] https://noobient.com/2023/11/15/fixing-ubuntu-containers-failing-to-start-with-systemd/ Signed-off-by: Mohammad Heib --- .github/workflows/ovn-fake-multinode-tests.yml | 8 .github/workflows/test.yml | 8 2 files changed, 16 insertions(+) diff --git a/.github/workflows/ovn-fake-multinode-tests.yml b/.github/workflows/ovn-fake-multinode-tests.yml index 179c1d662..79b6c4253 100644 --- a/.github/workflows/ovn-fake-multinode-tests.yml +++ b/.github/workflows/ovn-fake-multinode-tests.yml @@ -137,6 +137,14 @@ jobs: sudo systemctl start openvswitch-switch sudo ovs-vsctl show +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: Start basic cluster run: | sudo -E ./ovn_cluster.sh start diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2def39531..0cb981775 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -217,6 +217,14 @@ jobs: path: /tmp/image.tar key: ${{ github.sha }} +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: load image run: | sudo podman load -i /tmp/image.tar -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn] ci: Update crun in GitHub actions runer.
There are some issues with older crun and newer kernel combination [0]. Unfortunately Ubuntu 22.04 falls into this category and the jobs will often time fail. Temoprarily use newer crun from git that has the fix [1]. [0] https://github.com/containers/crun/pull/1309 [1] https://noobient.com/2023/11/15/fixing-ubuntu-containers-failing-to-start-with-systemd/ Signed-off-by: Mohammad Heib --- .github/workflows/ovn-fake-multinode-tests.yml | 8 .github/workflows/ovn-kubernetes.yml | 8 .github/workflows/test.yml | 8 3 files changed, 24 insertions(+) diff --git a/.github/workflows/ovn-fake-multinode-tests.yml b/.github/workflows/ovn-fake-multinode-tests.yml index 179c1d662..79b6c4253 100644 --- a/.github/workflows/ovn-fake-multinode-tests.yml +++ b/.github/workflows/ovn-fake-multinode-tests.yml @@ -137,6 +137,14 @@ jobs: sudo systemctl start openvswitch-switch sudo ovs-vsctl show +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: Start basic cluster run: | sudo -E ./ovn_cluster.sh start diff --git a/.github/workflows/ovn-kubernetes.yml b/.github/workflows/ovn-kubernetes.yml index 0f2b30497..09a838cfe 100644 --- a/.github/workflows/ovn-kubernetes.yml +++ b/.github/workflows/ovn-kubernetes.yml @@ -140,6 +140,14 @@ jobs: run: | docker load --input image.tar && rm -rf image.tar +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: kind setup run: | export OVN_IMAGE="ovn-daemonset-f:dev" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2def39531..0cb981775 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -217,6 +217,14 @@ jobs: path: /tmp/image.tar key: ${{ github.sha }} +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: load image run: | sudo podman load -i /tmp/image.tar -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v2] ci: Update crun in GitHub actions runner.
There are some issues with older crun and newer kernel combination [0]. Unfortunately Ubuntu 22.04 falls into this category and the jobs will often time fail. Temoprarily use newer crun from git that has the fix [1]. [0] https://github.com/containers/crun/pull/1309 [1] https://noobient.com/2023/11/15/fixing-ubuntu-containers-failing-to-start-with-systemd/ Signed-off-by: Mohammad Heib --- .github/workflows/ovn-fake-multinode-tests.yml | 8 .github/workflows/ovn-kubernetes.yml | 8 .github/workflows/test.yml | 8 3 files changed, 24 insertions(+) diff --git a/.github/workflows/ovn-fake-multinode-tests.yml b/.github/workflows/ovn-fake-multinode-tests.yml index 179c1d662..79b6c4253 100644 --- a/.github/workflows/ovn-fake-multinode-tests.yml +++ b/.github/workflows/ovn-fake-multinode-tests.yml @@ -137,6 +137,14 @@ jobs: sudo systemctl start openvswitch-switch sudo ovs-vsctl show +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: Start basic cluster run: | sudo -E ./ovn_cluster.sh start diff --git a/.github/workflows/ovn-kubernetes.yml b/.github/workflows/ovn-kubernetes.yml index 0f2b30497..09a838cfe 100644 --- a/.github/workflows/ovn-kubernetes.yml +++ b/.github/workflows/ovn-kubernetes.yml @@ -140,6 +140,14 @@ jobs: run: | docker load --input image.tar && rm -rf image.tar +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: kind setup run: | export OVN_IMAGE="ovn-daemonset-f:dev" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2def39531..0cb981775 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -217,6 +217,14 @@ jobs: path: /tmp/image.tar key: ${{ github.sha }} +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: load image run: | sudo podman load -i /tmp/image.tar -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn] ci: Update crun in GitHub actions runer.
There are some issues with older crun and newer kernel combination [0]. Unfortunately Ubuntu 22.04 falls into this category and the jobs will often time fail. Temoprarily use newer crun from git that has the fix [1]. [0] https://github.com/containers/crun/pull/1309 [1] https://noobient.com/2023/11/15/fixing-ubuntu-containers-failing-to-start-with-systemd/ Signed-off-by: Mohammad Heib --- .github/workflows/ovn-fake-multinode-tests.yml | 8 .github/workflows/ovn-kubernetes.yml | 8 .github/workflows/test.yml | 8 3 files changed, 24 insertions(+) diff --git a/.github/workflows/ovn-fake-multinode-tests.yml b/.github/workflows/ovn-fake-multinode-tests.yml index 179c1d662..79b6c4253 100644 --- a/.github/workflows/ovn-fake-multinode-tests.yml +++ b/.github/workflows/ovn-fake-multinode-tests.yml @@ -137,6 +137,14 @@ jobs: sudo systemctl start openvswitch-switch sudo ovs-vsctl show +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: Start basic cluster run: | sudo -E ./ovn_cluster.sh start diff --git a/.github/workflows/ovn-kubernetes.yml b/.github/workflows/ovn-kubernetes.yml index 0f2b30497..09a838cfe 100644 --- a/.github/workflows/ovn-kubernetes.yml +++ b/.github/workflows/ovn-kubernetes.yml @@ -140,6 +140,14 @@ jobs: run: | docker load --input image.tar && rm -rf image.tar +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: kind setup run: | export OVN_IMAGE="ovn-daemonset-f:dev" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2def39531..0cb981775 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -217,6 +217,14 @@ jobs: path: /tmp/image.tar key: ${{ github.sha }} +# XXX This should be removed when native crun >=1.9.1 +- name: update crun script + run: | +crun --version +sudo curl -L "https://github.com/containers/crun/releases/download/1.14.1/crun-1.14.1-linux-amd64"; -o /usr/bin/crun +sudo chmod +x /usr/bin/crun +echo "New crun version: "$(crun --version) + - name: load image run: | sudo podman load -i /tmp/image.tar -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn 1/2] tests: Move ovn interconnection tests to ovn-ic.at.
Move ovn-ic tests that exist in ovn.at to ovn-ic.at. Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 687 tests/ovn.at| 686 --- 2 files changed, 687 insertions(+), 686 deletions(-) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index 44dbf8ab1..12267e960 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -1442,3 +1442,690 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([interconnection]) +AT_KEYWORDS([slowtest]) + +ovn_init_ic_db +# The number needs to stay relatively low due to high memory consumption +# with address sanitizers enabled. +n_az=3 +n_ts=3 +for i in `seq 1 $n_az`; do +ovn_start az$i +done + +net_add n1 + +# 1 HV and 1 GW per AZ +for az in `seq 1 $n_az`; do +sim_add hv$az +as hv$az +check ovs-vsctl add-br br-phys +ovn_az_attach az$az n1 br-phys 192.168.$az.1 16 +for p in `seq 1 $n_ts`; do +check ovs-vsctl -- add-port br-int vif$p -- \ +set interface vif$p external-ids:iface-id=lsp$az-$p \ +options:tx_pcap=hv$az/vif$p-tx.pcap \ +options:rxq_pcap=hv$az/vif$p-rx.pcap \ +ofport-request=$p +done + +sim_add gw$az +as gw$az +check ovs-vsctl add-br br-phys +ovn_az_attach az$az n1 br-phys 192.168.$az.2 16 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true +done + +for ts in `seq 1 $n_ts`; do +AT_CHECK([ovn-ic-nbctl create Transit_Switch name=ts$ts], [0], [ignore]) +for az in `seq 1 $n_az`; do +echo "az$az: wait for ts$ts..." +check ovn_as az$az ovn-nbctl wait-until logical_switch ts$ts +done +done + +for az in `seq 1 $n_az`; do +ovn_as az$az +check ovn-nbctl set nb_global . options:ic-route-learn=true +check ovn-nbctl set nb_global . options:ic-route-adv=true + +# Each AZ has n_ts LSPi->LSi->LRi connecting to each TSi +echo +echo "az$az" +for i in `seq 1 $n_ts`; do +lsp_mac=00:00:00:0$az:0$i:00 +lrp_ls_mac=00:00:00:0$az:0$i:01 +lrp_ts_mac=00:00:00:0$az:0$i:02 +lsp_ip=10.$az.$i.123 +lrp_ls_ip=10.$az.$i.1 +lrp_ts_ip=169.254.$i.$az + +check ovn-nbctl ls-add ls$az-$i +check ovn-nbctl lsp-add ls$az-$i lsp$az-$i +check ovn-nbctl lsp-set-addresses lsp$az-$i "$lsp_mac $lsp_ip" + +check ovn-nbctl lr-add lr$az-$i + +check ovn-nbctl lrp-add lr$az-$i lrp-lr$az-$i-ls$az-$i $lrp_ls_mac $lrp_ls_ip/24 +check ovn-nbctl lsp-add ls$az-$i lsp-ls$az-$i-lr$az-$i +check ovn-nbctl lsp-set-addresses lsp-ls$az-$i-lr$az-$i router +check ovn-nbctl lsp-set-type lsp-ls$az-$i-lr$az-$i router +check ovn-nbctl lsp-set-options lsp-ls$az-$i-lr$az-$i router-port=lrp-lr$az-$i-ls$az-$i + +check ovn-nbctl lrp-add lr$az-$i lrp-lr$az-$i-ts$i $lrp_ts_mac $lrp_ts_ip/24 +check ovn-nbctl lsp-add ts$i lsp-ts$i-lr$az-$i +check ovn-nbctl lsp-set-addresses lsp-ts$i-lr$az-$i router +check ovn-nbctl lsp-set-type lsp-ts$i-lr$az-$i router +check ovn-nbctl lsp-set-options lsp-ts$i-lr$az-$i router-port=lrp-lr$az-$i-ts$i +check ovn-nbctl lrp-set-gateway-chassis lrp-lr$az-$i-ts$i gw$az +done +check ovn-nbctl --wait=hv sync +ovn-sbctl list Port_Binding > az$az.ports +wait_for_ports_up +done + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +for i in `seq 1 $n_az`; do +check ovn_as az$i ovn-nbctl --wait=hv sync +ovn_as az$i ovn-sbctl dump-flows > az$i/sbflows +done + +# Allow some time for ovn-northd and ovn-controller to catch up. +# XXX This should be more systematic. +sleep 2 + +# Populate requested-chassis options for remote lsps +for az in $(seq 1 $n_az); do +ovn_as az${az} +for ts in $(seq 1 $n_ts); do +for i in $(seq 1 $n_ts); do +if [[ $i -eq ${az} ]]; then +continue +fi +check ovn-nbctl lsp-set-options lsp-ts${ts}-lr${i}-${ts} requested-chassis=gw$i +done +done +done + +ovn-ic-nbctl show > ic-nbctl.dump +AT_CAPTURE_FILE([ic-nbctl.dump]) + +(echo "-ISB dump-" + ovn-ic-sbctl show + echo "-" + ovn-ic-sbctl list gateway + echo "-" + ovn-ic-sbctl list datapath_binding + echo "-" + ovn-ic-sbctl list port_binding + echo "-" + ovn-ic-sbctl list route + echo "-") > ic-sbctl.dump +AT_CAPTURE_FILE([ic-sbctl.dump]) + +AT_CAPTURE_FILE([expected]) +AT_CAPTURE_FILE([received]) +check_packets() { +> expected +> received +for az in `seq 1 $n_az`; do +for i in `seq 1 $n_ts`; do +p
[ovs-dev] [PATCH ovn 2/2] tests: Use sync command in ovn-ic tests.
Use the sync commands in the ovn-ic unit tests and remove lines that wait for IC-SB to sync with IC-NB. Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 178 1 file changed, 72 insertions(+), 106 deletions(-) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index 12267e960..4a24e171b 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -6,7 +6,7 @@ ovn_init_ic_db ovn_start az1 ovn_start az2 -wait_row_count ic-sb:Availability_Zone 2 +check ovn-ic-nbctl --wait=sb sync AT_CHECK([ovn-ic-sbctl show], [0], [dnl availability-zone az1 availability-zone az2 @@ -31,7 +31,6 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) - OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-ic -- AZ update in GW]) ovn_init_ic_db @@ -47,10 +46,12 @@ check ovs-vsctl set open . external-ids:ovn-is-interconn=true az_uuid=$(fetch_column ic-sb:availability-zone _uuid name="az1") ovn_as az1 ovn-nbctl set NB_Global . name="az2" -wait_column "$az_uuid" ic-sb:availability-zone _uuid name="az2" + +check ovn-ic-nbctl --wait=sb sync +check_column "$az_uuid" ic-sb:availability-zone _uuid name="az2" # make sure that gateway still point to the same AZ with new name -wait_column "$az_uuid" ic-sb:gateway availability_zone name="gw-az1" +check_column "$az_uuid" ic-sb:gateway availability_zone name="gw-az1" OVN_CLEANUP_IC([az1]) AT_CLEANUP @@ -66,11 +67,11 @@ ovn_start az1 ovn-sbctl chassis-add fakechassis vxlan 192.168.0.2 AT_CHECK([ovn-ic-nbctl ts-add ts1]) -AT_CHECK([ovn-ic-nbctl ts-add ts2]) +AT_CHECK([ovn-ic-nbctl --wait=sb ts-add ts2]) # Check ISB -wait_row_count ic-sb:Datapath_Binding 1 transit_switch=ts1 -wait_row_count ic-sb:Datapath_Binding 1 transit_switch=ts2 +check_row_count ic-sb:Datapath_Binding 1 transit_switch=ts1 +check_row_count ic-sb:Datapath_Binding 1 transit_switch=ts2 check_column "ts1 ts2" ic-sb:Datapath_Binding transit_switch check_column "ts1 ts2" nb:Logical_Switch name @@ -81,8 +82,8 @@ ts1_key=$(fetch_column ic-sb:Datapath_Binding tunnel_key transit_switch=ts1) check_column "$ts1_key" Datapath_Binding tunnel_key external_ids:interconn-ts=ts1 # Test delete -AT_CHECK([ovn-ic-nbctl ts-del ts1]) -wait_row_count ic-sb:Datapath_Binding 0 transit_switch=ts1 +AT_CHECK([ovn-ic-nbctl --wait=sb ts-del ts1]) +check_row_count ic-sb:Datapath_Binding 0 transit_switch=ts1 check_column ts2 ic-sb:Datapath_Binding transit_switch check_column ts2 nb:Logical_Switch name @@ -111,12 +112,11 @@ done ovn_as az1 # create transit switch and connect to LR -check ovn-ic-nbctl ts-add ts1 +check ovn-ic-nbctl --wait=sb ts-add ts1 check ovn-nbctl lr-add lr1 check ovn-nbctl lrp-add lr1 lrp1 00:00:00:00:00:01 10.0.0.1/24 check ovn-nbctl lrp-set-gateway-chassis lrp1 gw-az1 -OVS_WAIT_UNTIL([ovn-nbctl show | grep switch | grep ts1]) check ovn-nbctl lsp-add ts1 lsp1 -- \ lsp-set-addresses lsp1 router -- \ lsp-set-type lsp1 router -- \ @@ -124,8 +124,8 @@ check ovn-nbctl lsp-add ts1 lsp1 -- \ wait_row_count Datapath_Binding 1 external_ids:interconn-ts=ts1 -# check port binding appeared -OVS_WAIT_UNTIL([ovn-ic-sbctl show | grep lsp1]) +# Sync ic-sb DB to see the TS changes. +check ovn-ic-nbctl --wait=sb sync AT_CHECK([ovn-ic-sbctl show | grep -A2 lsp1], [0], [dnl port lsp1 @@ -134,8 +134,8 @@ AT_CHECK([ovn-ic-sbctl show | grep -A2 lsp1], [0], [dnl ]) # remove transit switch and check if port_binding is deleted -check ovn-ic-nbctl ts-del ts1 -wait_row_count ic-sb:Port_Binding 0 logical_port=lsp1 +check ovn-ic-nbctl --wait=sb ts-del ts1 +check_row_count ic-sb:Port_Binding 0 logical_port=lsp1 for i in 1 2; do az=az$i ovn_as $az @@ -180,8 +180,7 @@ create_ic_infra() { ovn_as $az -check ovn-ic-nbctl ts-add $ts -OVS_WAIT_UNTIL([ovn-nbctl show | grep switch | grep $ts]) +check ovn-ic-nbctl --wait=sb ts-add $ts check ovn-nbctl lr-add $lr check ovn-nbctl lrp-add $lr $lrp 00:00:00:00:00:0$az_id 10.0.$az_id.1/24 check ovn-nbctl lrp-set-gateway-chassis $lrp gw-$az @@ -197,18 +196,18 @@ create_ic_infra() { create_ic_infra 1 1 create_ic_infra 1 2 create_ic_infra 2 1 +check ovn-ic-nbctl --wait=sb sync ovn_as az1 -wait_row_count ic-sb:Route 3 ip_prefix=192.168.0.0/16 +check_row_count ic-sb:Route 3 ip_prefix=192.168.0.0/16 # remove transit switch 1 (from az1) and check if its route is deleted # same route from another AZ and ts should remain, as -check ovn-ic-nbctl ts-del ts1-1 -sleep 2 +check ovn-ic-nbctl --wait=sb ts-del ts1-1 ovn-ic-sbctl list route ovn-ic-nbctl list transit_switch -wait_row_count ic-sb:route 2 ip_prefix=192.168.0.0/16 +checl_row_count ic-sb:route 2 ip_prefix=192.168.0.0/16 ovn-ic-sbctl list route for i in 1 2; do @@ -246,7 +245,7 @@ done ovn_as az1 # create transit switch and connect to LR -check ovn-ic-nbctl ts-add ts1 +check ovn-ic-nbctl --w
Re: [ovs-dev] [PATCH ovn] ovn-controller: Stop dropping bind_vport requests immediately after handling.
Hi Ales, Thank you for the review i addressed all your comments in v2. regarding the test actually, it's a bit hard to test that using a unit test because we need to let ovn-sb ignore the first binding request which is not applicable using a unit test, i was testing that manually by dropping the connection to the SB that will drop the first bind request but it a bit hard to do that i an unit test. On Fri, Feb 2, 2024 at 1:21 PM Ales Musil wrote: > > > On Fri, Feb 2, 2024 at 12:19 PM Ales Musil wrote: > >> >> >> On Tue, Jan 30, 2024 at 2:59 PM Mohammad Heib wrote: >> >>> ovn-controller immediately removes the vport_bindings requests that were >>> generated by VIFs after handling them locally, this approach is intended >>> to avoid binding the vport to one VIF only and allocate the vport >>> between the different VIFs that exist in the vport:virtual-parents. >>> >>> Although the behavior mentioned above is correct, in some cases when the >>> SB Database is busy the transaction that binds this vport to the desired >>> VIF/chassis can fail and the controller will not re-try to bind the >>> vport again because we deleted the bind_vport request in the previous >>> loop/TXN. >>> >>> This patch aims to change the above behavior by storing the bind_vport >>> requests for a bit longer time and this is done by the following: >>> 1. add relevancy_time for each new bind_vport request and >>>mark this request as new. >>> >>> 2. loop0: ovn-controller will try to handle this bind_vport request >>>for the first time as usual (no change). >>> >>>3. loop0: ovn-controller will try to delete the already handled >>> bind_vport >>> request as usual but first, it will check if this request is >>> marked as new and >>> if the relevancy_time is still valid if so the controller will >>> mark this >>> request as an old request and keep it, otherwise remove it. >>> >>>4.loop1: ovn-controller will try to commit the same change again for >>> the old request, if the previous commit in loop0 succeeded the >>> change will not have any effect on SB, otherwise we will try to >>> commit the same vport_bind request again. >>> >>> 5. loop1: delete the old bind_vport request. >>> >>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1954659 >>> Signed-off-by: Mohammad Heib >>> --- >>> >> >> Hi Mohammad, >> >> overall the change makes sense, I have a couple of comments see down >> below. >> >> controller/pinctrl.c | 58 +++- >>> 1 file changed, 52 insertions(+), 6 deletions(-) >>> >>> diff --git a/controller/pinctrl.c b/controller/pinctrl.c >>> index bd3bd3d81..152962448 100644 >>> --- a/controller/pinctrl.c >>> +++ b/controller/pinctrl.c >>> @@ -6519,10 +6519,52 @@ struct put_vport_binding { >>> uint32_t vport_key; >>> >>> uint32_t vport_parent_key; >>> + >>> +/* This vport record Only relevant if "relevancy_time" >>> + * is earlier than the current_time, "new_record" is true. >>> + */ >>> +long long int relevancy_time; >>> >> >> The intention of the variable should be probably clearer e.g. >> relevant_until_ms. >> >> Also reading through the rest of the code it doesn't seem possible that >> the binding wouldn't be deleted, hence I think there isn't any need for the >> relevancy time, it should be enough to have a flag that will be flipped. In >> any case we will try to commit twice. I would leave out the whole relevancy >> and keep the flag flipping it on first commit WDYT? >> >> >>> +bool new_record; >>> }; >>> >>> /* Contains "struct put_vport_binding"s. */ >>> static struct hmap put_vport_bindings; >>> +/* the relevance time in ms of vport record before deleteing. */ >>> +#define VPORT_RELEVANCE_TIME 1500 >>> + >>> +/* >>> + * Validate if the vport_binding record that was added >>> + * by the pinctrl thread is still relevant and needs >>> + * to be updated in the SBDB or not. >>> + * >>> + * vport_binding record is only relevant and needs to be updated in SB >>> if: >>> + * 1. The put_vport_binding:relevancy_time still valid. >>> + * 2. The put_vport_binding:new_reco
[ovs-dev] [PATCH ovn v2] ovn-controller: Stop dropping bind_vport requests immediately after handling.
ovn-controller immediately removes the vport_bindings requests that were generated by VIFs after handling them locally, this approach is intended to avoid binding the vport to one VIF only and allocate the vport between the different VIFs that exist in the vport:virtual-parents. Although the behavior mentioned above is correct, in some cases when the SB Database is busy the transaction that binds this vport to the desired VIF/chassis can fail and the controller will not re-try to bind the vport again because we deleted the bind_vport request in the previous loop/TXN. This patch aims to change the above behavior by storing the bind_vport requests for a bit longer time and this is done by the following: 1. mark each new bind_vport request as new. 2. loop0: ovn-controller will try to handle this bind_vport request for the first time as usual (no change). 3. loop0: ovn-controller will try to delete the already handled bind_vport request as usual but first, it will check if this request is marked as new and if so the controller will mark this request as an old request and keep it, otherwise remove it. 4. loop1: ovn-controller will try to commit the same change again for the old request, if the previous commit in loop0 succeeded the change will not have any effect on SB, otherwise we will try to commit the same vport_bind request again. 5. loop1: delete the old bind_vport request. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1954659 Signed-off-by: Mohammad Heib --- V2: Address comments from Ales in v1. --- controller/pinctrl.c | 50 ++-- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 98b29de9f..e2f86f299 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -6529,11 +6529,46 @@ struct put_vport_binding { uint32_t vport_key; uint32_t vport_parent_key; + +/* This vport record Only relevant if "new_record" is true. */ +bool new_record; }; /* Contains "struct put_vport_binding"s. */ static struct hmap put_vport_bindings; +/* + * Validate if the vport_binding record that was added + * by the pinctrl thread is still relevant and needs + * to be updated in the SBDB or not. + * + * vport_binding record is only relevant and needs to be updated in SB if: + * 2. The put_vport_binding:new_record is true: + * The new_record will be set to "true" when this vport record is created + * by function "pinctrl_handle_bind_vport". + * + * After the first attempt to bind this vport to the chassis and + * virtual_parent by function "run_put_vport_bindings" we will set the + * value of vpb:new_record to "false" and keep it in "put_vport_bindings" + * + * After the second attempt of binding the vpb it will be removed by + * this function. + * + * The above guarantees that we will try to bind the vport twice in + * a certain amount of time. + * +*/ +static bool +is_vport_binding_relevant(struct put_vport_binding *vpb) +{ + +if (vpb->new_record) { +vpb->new_record = false; +return true; +} +return false; +} + static void init_put_vport_bindings(void) { @@ -6541,18 +6576,21 @@ init_put_vport_bindings(void) } static void -flush_put_vport_bindings(void) +flush_put_vport_bindings(bool force_flush) { struct put_vport_binding *vport_b; -HMAP_FOR_EACH_POP (vport_b, hmap_node, &put_vport_bindings) { -free(vport_b); +HMAP_FOR_EACH_SAFE (vport_b, hmap_node, &put_vport_bindings) { +if (!is_vport_binding_relevant(vport_b) || force_flush) { +hmap_remove(&put_vport_bindings, &vport_b->hmap_node); +free(vport_b); +} } } static void destroy_put_vport_bindings(void) { -flush_put_vport_bindings(); +flush_put_vport_bindings(true); hmap_destroy(&put_vport_bindings); } @@ -6630,7 +6668,7 @@ run_put_vport_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, sbrec_port_binding_by_key, chassis, vpb); } -flush_put_vport_bindings(); +flush_put_vport_bindings(false); } /* Called with in the pinctrl_handler thread context. */ @@ -6668,7 +6706,7 @@ pinctrl_handle_bind_vport( vpb->dp_key = dp_key; vpb->vport_key = vport_key; vpb->vport_parent_key = vport_parent_key; - +vpb->new_record = true; notify_pinctrl_main(); } -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v3] OVN-SB: Exposes igmp group protocol version through IGMP table.
Expose the igmp/mld group protocol version through the IGMP_GROUP table in SBDB. This patch can be used by ovn consumer for debuggability purposes, user now can match between the protocol version used in the OVN logical switches and the uplink ports. Rreported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2160476 Signed-off-by: Mohammad Heib --- v3: Address Ales comments in v2 and rebase over main. --- NEWS | 2 ++ controller/ip-mcast.c | 11 +-- controller/ip-mcast.h | 11 ++- controller/pinctrl.c | 16 ++-- northd/ovn-northd.c | 2 +- ovn-sb.ovsschema | 5 +++-- ovn-sb.xml| 4 tests/ovn.at | 3 +++ 8 files changed, 42 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index c0131ceee..784fedfa0 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ Post v24.03.0 cloned to all unknown ports connected to the same Logical Switch. - Added a new logical switch port option "disable_arp_nd_rsp" to disable adding the ARP responder flows if set to true. + - IGMP_Group has new "protocol" column that displays the the group +protocol version. OVN v24.03.0 - xx xxx -- diff --git a/controller/ip-mcast.c b/controller/ip-mcast.c index b457c7e69..0969cc07f 100644 --- a/controller/ip-mcast.c +++ b/controller/ip-mcast.c @@ -111,11 +111,12 @@ igmp_mrouter_create(struct ovsdb_idl_txn *idl_txn, } void -igmp_group_update_ports(const struct sbrec_igmp_group *g, +igmp_group_update(const struct sbrec_igmp_group *g, struct ovsdb_idl_index *datapaths, struct ovsdb_idl_index *port_bindings, const struct mcast_snooping *ms OVS_UNUSED, -const struct mcast_group *mc_group) +const struct mcast_group *mc_group, +const bool igmp_support_protocol) OVS_REQ_RDLOCK(ms->rwlock) { struct igmp_group_port *old_ports_storage = @@ -155,6 +156,12 @@ igmp_group_update_ports(const struct sbrec_igmp_group *g, sbrec_igmp_group_update_ports_delvalue(g, igmp_port->port); } +/* set Group protocol */ +if (igmp_support_protocol) { + sbrec_igmp_group_set_protocol(g, mcast_snooping_group_protocol_str( + mc_group->protocol_version)); +} + free(old_ports_storage); hmap_destroy(&old_ports); } diff --git a/controller/ip-mcast.h b/controller/ip-mcast.h index eebada968..026503139 100644 --- a/controller/ip-mcast.h +++ b/controller/ip-mcast.h @@ -47,11 +47,12 @@ struct sbrec_igmp_group *igmp_mrouter_create( const struct sbrec_chassis *chassis, bool igmp_group_has_chassis_name); -void igmp_group_update_ports(const struct sbrec_igmp_group *g, - struct ovsdb_idl_index *datapaths, - struct ovsdb_idl_index *port_bindings, - const struct mcast_snooping *ms, - const struct mcast_group *mc_group) +void igmp_group_update(const struct sbrec_igmp_group *g, + struct ovsdb_idl_index *datapaths, + struct ovsdb_idl_index *port_bindings, + const struct mcast_snooping *ms, + const struct mcast_group *mc_group, + const bool igmp_support_protocol) OVS_REQ_RDLOCK(ms->rwlock); void igmp_mrouter_update_ports(const struct sbrec_igmp_group *g, diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 98b29de9f..66e390e80 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -181,6 +181,7 @@ struct pinctrl { bool fdb_can_timestamp; bool dns_supports_ovn_owned; bool igmp_group_has_chassis_name; +bool igmp_support_protocol; }; static struct pinctrl pinctrl; @@ -3599,6 +3600,17 @@ pinctrl_update(const struct ovsdb_idl *idl, const char *br_int_name) notify_pinctrl_handler(); } +bool igmp_support_proto = +sbrec_server_has_igmp_group_table_col_protocol(idl); +if (igmp_support_proto != pinctrl.igmp_support_protocol) { +pinctrl.igmp_support_protocol = igmp_support_proto; + +/* Notify pinctrl_handler that igmp protocol column + * availability has changed. */ +notify_pinctrl_handler(); +} + + ovs_mutex_unlock(&pinctrl_mutex); } @@ -5409,9 +5421,9 @@ ip_mcast_sync(struct ovsdb_idl_txn *ovnsb_idl_txn, chassis, pinctrl.igmp_group_has_chassis_name); } -igmp_group_update_ports(sbrec_igmp, sbrec_datapath_binding_by_key, +igmp_group_update(sbrec_igmp, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, ip_ms->ms, -mc_group); +mc_group, pinctrl.igmp_support_p
[ovs-dev] [PATCH ovn v2] OVN-SB: Exposes igmp group protocol version through IGMP table.
Expose the igmp/mld group protocol version through the IGMP_GROUP table in SBDB. This patch can be used by ovn consumer for debuggability purposes, user now can match between the protocol version used in the OVN logical switches and the uplink ports. Rreported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2160476 Signed-off-by: Mohammad Heib --- NEWS | 2 ++ controller/ip-mcast.c | 10 -- controller/ip-mcast.h | 5 +++-- controller/pinctrl.c | 28 northd/ovn-northd.c | 2 +- ovn-sb.ovsschema | 5 +++-- ovn-sb.xml| 4 tests/ovn.at | 3 +++ 8 files changed, 48 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index 6553bd078..6505ef22b 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,8 @@ Post v23.09.0 - Support selecting encapsulation IP based on the source/destination VIF's settting. See ovn-controller(8) 'external_ids:ovn-encap-ip' for more details. + - IGMP_Group has new "protocol" column that displays the the group +protocol version. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/controller/ip-mcast.c b/controller/ip-mcast.c index a870fb29e..18a3e1fc2 100644 --- a/controller/ip-mcast.c +++ b/controller/ip-mcast.c @@ -107,11 +107,12 @@ igmp_mrouter_create(struct ovsdb_idl_txn *idl_txn, } void -igmp_group_update_ports(const struct sbrec_igmp_group *g, +igmp_group_update(const struct sbrec_igmp_group *g, struct ovsdb_idl_index *datapaths, struct ovsdb_idl_index *port_bindings, const struct mcast_snooping *ms OVS_UNUSED, -const struct mcast_group *mc_group) +const struct mcast_group *mc_group, +const char *protocol) OVS_REQ_RDLOCK(ms->rwlock) { struct igmp_group_port *old_ports_storage = @@ -151,6 +152,11 @@ igmp_group_update_ports(const struct sbrec_igmp_group *g, sbrec_igmp_group_update_ports_delvalue(g, igmp_port->port); } +/* set Group protocol */ +if (protocol) { + sbrec_igmp_group_set_protocol(g, protocol); +} + free(old_ports_storage); hmap_destroy(&old_ports); } diff --git a/controller/ip-mcast.h b/controller/ip-mcast.h index 326f39db1..2a8921976 100644 --- a/controller/ip-mcast.h +++ b/controller/ip-mcast.h @@ -45,11 +45,12 @@ struct sbrec_igmp_group *igmp_mrouter_create( const struct sbrec_datapath_binding *datapath, const struct sbrec_chassis *chassis); -void igmp_group_update_ports(const struct sbrec_igmp_group *g, +void igmp_group_update(const struct sbrec_igmp_group *g, struct ovsdb_idl_index *datapaths, struct ovsdb_idl_index *port_bindings, const struct mcast_snooping *ms, - const struct mcast_group *mc_group) + const struct mcast_group *mc_group, + const char *protocol) OVS_REQ_RDLOCK(ms->rwlock); void igmp_mrouter_update_ports(const struct sbrec_igmp_group *g, diff --git a/controller/pinctrl.c b/controller/pinctrl.c index bd3bd3d81..f3597b489 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -180,6 +180,7 @@ struct pinctrl { bool mac_binding_can_timestamp; bool fdb_can_timestamp; bool dns_supports_ovn_owned; +bool igmp_support_protocol; }; static struct pinctrl pinctrl; @@ -3586,11 +3587,21 @@ pinctrl_update(const struct ovsdb_idl *idl, const char *br_int_name) if (dns_supports_ovn_owned != pinctrl.dns_supports_ovn_owned) { pinctrl.dns_supports_ovn_owned = dns_supports_ovn_owned; -/* Notify pinctrl_handler that fdb timestamp column +/* Notify pinctrl_handler that dns ovn_owned column * availability has changed. */ notify_pinctrl_handler(); } +bool igmp_support_proto = +sbrec_server_has_igmp_group_table_col_protocol(idl); +if (igmp_support_proto != pinctrl.igmp_support_protocol) { +pinctrl.igmp_support_protocol = igmp_support_proto; + +/* Notify pinctrl_handler that igmp protocol column + * availability has changed. */ +notify_pinctrl_handler(); +} + ovs_mutex_unlock(&pinctrl_mutex); } @@ -5400,9 +5411,18 @@ ip_mcast_sync(struct ovsdb_idl_txn *ovnsb_idl_txn, local_dp->datapath, chassis); } -igmp_group_update_ports(sbrec_igmp, sbrec_datapath_binding_by_key, -sbrec_port_binding_by_key, ip_ms->ms, -mc_group); +/* Set Group protocol if supported */ +if (pinctrl.igmp_support_protocol) { +igmp_group_update(sbrec_igmp, sbrec_datapath_binding_by_key, +
[ovs-dev] [PATCH ovn] ovn-controller: Stop dropping bind_vport requests immediately after handling.
ovn-controller immediately removes the vport_bindings requests that were generated by VIFs after handling them locally, this approach is intended to avoid binding the vport to one VIF only and allocate the vport between the different VIFs that exist in the vport:virtual-parents. Although the behavior mentioned above is correct, in some cases when the SB Database is busy the transaction that binds this vport to the desired VIF/chassis can fail and the controller will not re-try to bind the vport again because we deleted the bind_vport request in the previous loop/TXN. This patch aims to change the above behavior by storing the bind_vport requests for a bit longer time and this is done by the following: 1. add relevancy_time for each new bind_vport request and mark this request as new. 2. loop0: ovn-controller will try to handle this bind_vport request for the first time as usual (no change). 3. loop0: ovn-controller will try to delete the already handled bind_vport request as usual but first, it will check if this request is marked as new and if the relevancy_time is still valid if so the controller will mark this request as an old request and keep it, otherwise remove it. 4.loop1: ovn-controller will try to commit the same change again for the old request, if the previous commit in loop0 succeeded the change will not have any effect on SB, otherwise we will try to commit the same vport_bind request again. 5. loop1: delete the old bind_vport request. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1954659 Signed-off-by: Mohammad Heib --- controller/pinctrl.c | 58 +++- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index bd3bd3d81..152962448 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -6519,10 +6519,52 @@ struct put_vport_binding { uint32_t vport_key; uint32_t vport_parent_key; + +/* This vport record Only relevant if "relevancy_time" + * is earlier than the current_time, "new_record" is true. + */ +long long int relevancy_time; +bool new_record; }; /* Contains "struct put_vport_binding"s. */ static struct hmap put_vport_bindings; +/* the relevance time in ms of vport record before deleteing. */ +#define VPORT_RELEVANCE_TIME 1500 + +/* + * Validate if the vport_binding record that was added + * by the pinctrl thread is still relevant and needs + * to be updated in the SBDB or not. + * + * vport_binding record is only relevant and needs to be updated in SB if: + * 1. The put_vport_binding:relevancy_time still valid. + * 2. The put_vport_binding:new_record is true: + * The new_record will be set to "true" when this vport record is created + * by function "pinctrl_handle_bind_vport". + * + * After the first attempt to bind this vport to the chassis and + * virtual_parent by function "run_put_vport_bindings" we will set the + * value of vpb:new_record to "false" and keep it in "put_vport_bindings" + * + * After the second attempt of binding the vpb it will be removed by + * this function. + * + * The above guarantees that we will try to bind the vport twice in + * a certain amount of time. + * +*/ +static bool +is_vport_binding_relevant(struct put_vport_binding *vpb) +{ +long long int cur_time = time_msec(); + +if (vpb->new_record && vpb->relevancy_time > cur_time) { +vpb->new_record = false; +return true; +} +return false; +} static void init_put_vport_bindings(void) @@ -6531,18 +6573,21 @@ init_put_vport_bindings(void) } static void -flush_put_vport_bindings(void) +flush_put_vport_bindings(bool force_flush) { struct put_vport_binding *vport_b; -HMAP_FOR_EACH_POP (vport_b, hmap_node, &put_vport_bindings) { -free(vport_b); +HMAP_FOR_EACH_SAFE (vport_b, hmap_node, &put_vport_bindings) { +if (!is_vport_binding_relevant(vport_b) || force_flush) { +hmap_remove(&put_vport_bindings, &vport_b->hmap_node); +free(vport_b); +} } } static void destroy_put_vport_bindings(void) { -flush_put_vport_bindings(); +flush_put_vport_bindings(true); hmap_destroy(&put_vport_bindings); } @@ -6620,7 +6665,7 @@ run_put_vport_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, sbrec_port_binding_by_key, chassis, vpb); } -flush_put_vport_bindings(); +flush_put_vport_bindings(false); } /* Called with in the pinctrl_handler thread context. */ @@ -6658,7 +6703,8 @@ pinctrl_handle_bind_vport( vpb->dp_key = dp_key; vpb->vport_key = vport_key; vpb->vport_parent_key = vport_parent_key; - +
Re: [ovs-dev] [PATCH ovn] ovs: Bump submodule to latest OVS branch-3.3.
Hi, Thank you Dumitru. Acked-by: Mohammad Heib On Tue, Jan 30, 2024 at 11:16 AM Eelco Chaudron wrote: > > > On 30 Jan 2024, at 9:57, Dumitru Ceara wrote: > > > On 1/30/24 09:04, Eelco Chaudron wrote: > >> > >> > >> On 30 Jan 2024, at 0:36, Dumitru Ceara wrote: > >> > >>> This picks up the following relevant OVS commits: > >>> 8893e24d9d dpdk: Update to use v23.11. > >>> ed738eca39 util: Annotate function that will never return NULL. > >>> 77d0bad04 mcast-snooping: Store IGMP/MLD protocol version. > >>> b222593bc6 mcast-snooping: Add group protocol to mdb/show output. > >>> a940a691e7 ovs-atomic: Fix inclusion of Clang header by GCC 14. > >>> b0cf73112d dp-packet: Reset offload/offsets when clearing a packet. > >>> > >>> This commit also ports the CI DPDK related changes from OVS commit > >>> 8893e24d9d09 ("dpdk: Update to use v23.11.") which are required as > 23.11 > >>> is the supported DPDK branch on OVS 3.3. There's also a small change > >>> that had to be made when mangling the prefix path of the installed > >>> DPDK version in the container. > >>> > >>> As a side effect this will also address OVN Fedora 40 (rawhide) build > >>> failures on aarch64 and s390x. They are fixed by a940a691e7d9 > >>> ("ovs-atomic: Fix inclusion of Clang header by GCC 14."). > >>> > >>> Suggested-by: Ilya Maximets > >>> Signed-off-by: Dumitru Ceara > >> > >> There is also a change in controller/pinctrl.c, any reason why this is > part of this patch? > >> > > > > Yes, b222593bc6 ("mcast-snooping: Add group protocol to mdb/show > > output") changed the OVS mcast library API. That's used by OVN. We > > need that pinctrl.c change otherwise compilation fails. > > Thanks Dumitru for the clarification, maybe you can add this to the commit > message when you apply? The rest looks good, and as the tests passed; > > Acked-by: Eelco Chaudron > > > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH] mcast-snooping: Remove typedef from mcast_group_proto.
Thanks, Ilya, Looks good to me. Acked-by: Mohammad Heib Thanks, On Fri, Jan 26, 2024 at 7:11 PM Ilya Maximets wrote: > Typedefs are confusing and the coding style generally advises to not > use them. Removing typedef until others start using it. > > This typedef already got me while testing an OVN update to use OVS 3.3 > as a submodule, since the variable was declared in a switch statement > and it wasn't clearly visible that there is a variable definition in > one of the cases and braces should be used. Strangely some versions > of compilers do not require braces in this case, so OVN change works > locally, but not in CI. > > Fixes: 077d0bad0436 ("mcast-snooping: Store IGMP/MLD protocol version.") > Signed-off-by: Ilya Maximets > --- > lib/mcast-snooping.c | 6 +++--- > lib/mcast-snooping.h | 12 ++-- > ofproto/ofproto-dpif-xlate.c | 2 +- > 3 files changed, 10 insertions(+), 10 deletions(-) > > diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c > index 60ef8381e..dc5164b41 100644 > --- a/lib/mcast-snooping.c > +++ b/lib/mcast-snooping.c > @@ -58,7 +58,7 @@ mcast_snooping_flood_unreg(const struct mcast_snooping > *ms) > } > > char * > -mcast_snooping_group_protocol_str(mcast_group_proto grp_proto) > +mcast_snooping_group_protocol_str(enum mcast_group_proto grp_proto) > { > switch (grp_proto) { > case MCAST_GROUP_IGMPV1: > @@ -414,7 +414,7 @@ bool > mcast_snooping_add_group(struct mcast_snooping *ms, > const struct in6_addr *addr, > uint16_t vlan, void *port, > - mcast_group_proto grp_proto) > + enum mcast_group_proto grp_proto) > OVS_REQ_WRLOCK(ms->rwlock) > { > bool learned; > @@ -460,7 +460,7 @@ mcast_snooping_add_group(struct mcast_snooping *ms, > bool > mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, > uint16_t vlan, void *port, > - mcast_group_proto grp_proto) > + enum mcast_group_proto grp_proto) > OVS_REQ_WRLOCK(ms->rwlock) > { > struct in6_addr addr = in6_addr_mapped_ipv4(ip4); > diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h > index 76ab4e4f7..de42cf826 100644 > --- a/lib/mcast-snooping.h > +++ b/lib/mcast-snooping.h > @@ -40,13 +40,13 @@ struct mcast_snooping; > #define MCAST_MROUTER_PORT_IDLE_TIME 180 > > /* Multicast group protocol. */ > -typedef enum { > +enum mcast_group_proto { > MCAST_GROUP_IGMPV1 = 0, > MCAST_GROUP_IGMPV2, > MCAST_GROUP_IGMPV3, > MCAST_GROUP_MLDV1, > MCAST_GROUP_MLDV2, > -} mcast_group_proto; > +}; > > /* Multicast group entry. > * Guarded by owning 'mcast_snooping''s rwlock. */ > @@ -61,7 +61,7 @@ struct mcast_group { > uint16_t vlan; > > /* Multicast group IPv6/IPv4 Protocol version IGMPv1,2,3 or MLDv1,2 */ > -mcast_group_proto protocol_version; > +enum mcast_group_proto protocol_version; > > /* Node in parent struct mcast_snooping group_lru. */ > struct ovs_list group_node OVS_GUARDED; > @@ -198,11 +198,11 @@ mcast_snooping_lookup4(const struct mcast_snooping > *ms, ovs_be32 ip4, > bool mcast_snooping_add_group(struct mcast_snooping *ms, >const struct in6_addr *addr, >uint16_t vlan, void *port, > - mcast_group_proto grp_proto) > + enum mcast_group_proto grp_proto) > OVS_REQ_WRLOCK(ms->rwlock); > bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, > uint16_t vlan, void *port, > - mcast_group_proto grp_proto) > + enum mcast_group_proto grp_proto) > OVS_REQ_WRLOCK(ms->rwlock); > int mcast_snooping_add_report(struct mcast_snooping *ms, >const struct dp_packet *p, > @@ -224,7 +224,7 @@ bool mcast_snooping_add_mrouter(struct mcast_snooping > *ms, uint16_t vlan, > OVS_REQ_WRLOCK(ms->rwlock); > bool mcast_snooping_is_query(ovs_be16 igmp_type); > bool mcast_snooping_is_membership(ovs_be16 igmp_type); > -char *mcast_snooping_group_protocol_str(mcast_group_proto grp_proto); > +char *mcast_snooping_group_protocol_str(enum mcast_group_proto grp_proto); > > /* Flush. */ > void mcast_snooping_mdb_flush(struct mcast_snooping *ms); > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index f4d1d7194..1cf4d5f7c 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++
Re: [ovs-dev] [PATCH ovn] Controller: Handle unconditional IDL messages while paused.
Hi Mark, Thank you for your quick review, On Thu, Jan 25, 2024 at 12:40 AM Mark Michelson wrote: > Hi Mohammad, > > I'm having a hard time with this one, and mainly it's because of what > the intended semantics of being "paused" are. I could see it argued that > pausing ovn-controller should have the existing behavior. I could see > someone writing a test where they pause ovn-controller specifically to > trigger disconnection SB DB. > > > My comments below have the mindset that this change is the correct > behavior. But in addition to my comments, I think we need to verify if > this proposed change is what we actually want ovn-controller to do. > > i agree with you indeed this patch changed the controller behavior a little bit, but we need it to handle cases such as BZ [1]. This BZ is affected by similar scenarios that this patch is fixing: when we have the ovn-controller in a pause state some pinctrl pkt-in can be received on the ovn-controller and pinctrl thread will handle them and save the needed data for SBDB to temporary storage that will be removed each controller loop iteration (see run_put_vport_bindings in the pinctrl for example). so once the user triggers a resume to the ovn-controller the controller will try to commit this temporary data and the TXN will fail and we lose the needed data. The issue is present even if the controller wasn't on pause but the ovsdb server is a bit busy and TXN has failed. i will submit a separate patch to handle vport specific issue when TXN fails maybe keep the temporary data for a bit longer using timestamp but i think we must also keep answering the ovsdb server prob messages to avoid mult-reconnecting from the ovsdb server. What do you think? [1] https://bugzilla.redhat.com/show_bug.cgi?id=1954659 On 1/23/24 08:03, Mohammad Heib wrote: > > If the user triggers a pause command to the ovn-controller the current > > implementation will wait for commands from unixctl server only and > > ignore the other component. > > > > This implementation works fine if we don't have inactivity_probe set in > > the SB DataBase, but once the user sets the inactivity_probe in SB > > DataBase the connection will be dropped by the SBDB. Once the controller > > resumes the execution it will try to commit some changes to the SBDB but > > the transaction will fail since we lost the connection to the SBDB and > > the controller must reconnect before committing the transaction again. > > > > To avoid the above scenario the controller can keep handling > > unconditional IDL messages to avoid reconnecting to SB. > > > > Signed-off-by: Mohammad Heib > > --- > > controller/ovn-controller.c | 16 +--- > > ovn-sb.xml | 2 +- > > tests/ovn-controller.at | 51 + > > 3 files changed, 65 insertions(+), 4 deletions(-) > > > > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > > index 856e5e270..d2c8f66d9 100644 > > --- a/controller/ovn-controller.c > > +++ b/controller/ovn-controller.c > > @@ -5534,12 +5534,22 @@ main(int argc, char *argv[]) > > simap_destroy(&usage); > > } > > > > -/* If we're paused just run the unixctl server and skip most of > the > > - * processing loop. > > +/* If we're paused just run the unixctl-server/unconditional > IDL and > > + * skip most of the processing loop. > >*/ > > if (paused) { > > unixctl_server_run(unixctl); > > +int ovnsb_seq = ovsdb_idl_get_seqno(ovnsb_idl_loop.idl); > > +ovsdb_idl_run(ovnsb_idl_loop.idl); > > +int new_ovnsb_seq = ovsdb_idl_get_seqno(ovnsb_idl_loop.idl); > > +/* If the IDL content has changed while the controller is > > + * in pause state, trigger a recompute. > > + */ > > +if (new_ovnsb_seq != ovnsb_seq) { > > +engine_set_force_recompute(true); > > +} > > If we're going to safeguard ourselves from being disconnected from the > SB DB, then we should do the same for the OVS DB. > > > unixctl_server_wait(unixctl); > > +ovsdb_idl_wait(ovnsb_idl_loop.idl); > > goto loop_done; > > } > > > > @@ -6009,7 +6019,6 @@ main(int argc, char *argv[]) > > OVS_NOT_REACHED(); > > } > > > > -ovsdb_idl_track_clear(ovnsb_idl_loop.idl); > > ovsdb_idl_track_clear(ovs_idl_loop.idl); > > > > lflow_ca
Re: [ovs-dev] [PATCH ovn v4 4/4] ic/tests: add unit test for ic sync command
Hi Ales, On Fri, Jan 12, 2024 at 11:12 AM Ales Musil wrote: > > > On Tue, Jan 9, 2024 at 2:29 PM Mohammad Heib wrote: > >> add unit test that check validate that sync command >> sync ISB properly >> >> Signed-off-by: Mohammad Heib >> --- >> > > Hi Mohammad, > > I have a few comments down below. > > >> tests/ovn-ic.at | 47 +++ >> 1 file changed, 47 insertions(+) >> >> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at >> index d4c436f84..f55ffa6cd 100644 >> --- a/tests/ovn-ic.at >> +++ b/tests/ovn-ic.at >> @@ -1274,3 +1274,50 @@ OVN_CLEANUP_IC([az1], [az2]) >> >> AT_CLEANUP >> ]) >> + >> +AT_SETUP([ovn-ic -- sync ISB status to INB]) >> +ovn_init_ic_db >> +net_add n1 >> + >> +ovn_start az1 >> +sim_add gw-az1 >> +as gw-az1 >> + >> +check ovs-vsctl add-br br-phys >> +ovn_az_attach az1 n1 br-phys 192.168.1.1 >> +check ovs-vsctl set open . external-ids:ovn-is-interconn=true >> +as az1 >> + >> +# pause ovn-ic instance >> +check ovn-appctl -t ic/ovn-ic pause >> + >> +# run sync command in the background this commands >> +# supposed to stuck since ovn-ic is paused. >> +$(ovn-ic-nbctl --wait=sb sync &) >> > > The extra $() around shouldn't be needed. > > >> + >> +for i in {1..5}; do >> +set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) >> +AS_VAR_SET([ic_nb_cfg], [$1]) >> +AS_VAR_SET([ic_sb_cfg], [$2]) >> +if test $ic_nb_cfg -gt $ic_sb_cfg; then >> +sleep 1 >> +else >> +break >> +fi >> +done >> > > Why not to use OVS_WAIT_UNTIL? > > >> + >> +# if ic_nb_cfg equal to ic_sb_cfg that mean both zero >> +# or both 1 which is a not correct and the test must fail. >> +AT_FAIL_IF([test $ic_nb_cfg == $ic_sb_cfg]) >> > > AT_CHECK would be better suited for this. > > >> + >> +# resume ovn-ic instance >> +check ovn-appctl -t ic/ovn-ic resume >> +set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) >> > > We should wait after "resume" for the values to settle down. > > >> +AS_VAR_SET([ic_nb_cfg], [$1]) >> +AS_VAR_SET([ic_sb_cfg], [$2]) >> +AT_FAIL_IF([test $ic_nb_cfg != 1]) >> +AT_FAIL_IF([test $ic_nb_cfg != 1]) >> > > Same as above, AT_CHECK would be better. > > >> + >> +OVN_CLEANUP_IC([az1]) >> +AT_CLEANUP >> +]) >> -- >> 2.34.3 >> >> ___ >> dev mailing list >> d...@openvswitch.org >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> >> > The test seems to be overly complicated for what it tries to achieve. I > would suggest the following diff: > Thank you so much for reviewing the patch, I agree with you the test is complicated, I will go with your suggestions in v5, Thanks :) > > diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at > index f55ffa6cd..32df3be2c 100644 > --- a/tests/ovn-ic.at > +++ b/tests/ovn-ic.at > @@ -1293,30 +1293,25 @@ check ovn-appctl -t ic/ovn-ic pause > > # run sync command in the background this commands > # supposed to stuck since ovn-ic is paused. > -$(ovn-ic-nbctl --wait=sb sync &) > - > -for i in {1..5}; do > -set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) > -AS_VAR_SET([ic_nb_cfg], [$1]) > -AS_VAR_SET([ic_sb_cfg], [$2]) > -if test $ic_nb_cfg -gt $ic_sb_cfg; then > -sleep 1 > -else > -break > -fi > -done > +ovn-ic-nbctl --wait=sb sync & > > -# if ic_nb_cfg equal to ic_sb_cfg that mean both zero > -# or both 1 which is a not correct and the test must fail. > -AT_FAIL_IF([test $ic_nb_cfg == $ic_sb_cfg]) > +OVS_WAIT_UNTIL([test $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg) -gt > $(ovn-ic-nbctl get ic_nb_global . sb_ic_cfg)]) > +AT_CHECK([ovn-ic-nbctl get ic_nb_global . nb_ic_cfg], [0], [dnl > +1 > +]) > +AT_CHECK([ovn-ic-nbctl get ic_nb_global . sb_ic_cfg], [0], [dnl > +0 > +]) > > # resume ovn-ic instance > check ovn-appctl -t ic/ovn-ic resume > -set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) > -AS_VAR_SET([ic_nb_cfg], [$1]) > -AS_VAR_SET([ic_sb_cfg], [$2]) > -AT_FAIL_IF([test $ic_nb_cfg != 1]) > -AT_FAIL_IF([test $ic_nb_cfg != 1]) > +OVS_WAIT_UNTIL([test $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg) -eq > $(ovn-ic-nbctl get ic_nb_global . sb_ic_cfg)]) > +AT_CHECK([ovn-ic-nbctl get ic_nb_global . nb_ic_cfg], [0], [dnl > +1 > +]) > +AT_CHECK([ovn-ic-nbctl get ic_nb_global . sb_ic_cfg], [0], [dnl > +1 > +]) > > OVN_CLEANUP_IC([az1]) > AT_CLEANUP > > > 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
[ovs-dev] [PATCH ovn v5 3/4] OVN-IC: Make it possible for CMS to detect when the ISB is up-to-date.
Until now, there has been no reliable for the CMS to detect when changes made to the INB configuration have been passed through to the ISB, This commit adds this feature to the system, by adding sequence numbers to the INB and ISB and adding code in ovn-ic-nbctl, ovn-ic to keep those sequence numbers up-to-date. The biggest user-visible change from this commit is a new option '--wait' and new command 'sync' to ovn-ic-nbctl. With --wait=sb, ovn-ic-nbctl now waits for ovn-ics to update the ISB database. Signed-off-by: Mohammad Heib Acked-by: Mark Michelson Acked-by: Ales Musil --- utilities/ovn-ic-nbctl.8.xml | 49 utilities/ovn-ic-nbctl.c | 86 +++- 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/utilities/ovn-ic-nbctl.8.xml b/utilities/ovn-ic-nbctl.8.xml index 4a70994b8..5a1324d2d 100644 --- a/utilities/ovn-ic-nbctl.8.xml +++ b/utilities/ovn-ic-nbctl.8.xml @@ -123,9 +123,58 @@ +Synchronization Commands + + + sync + +Ordinarily, --wait=sb only waits for changes by the +current ovn-ic-nbctl invocation to take effect. +This means that, if none of the commands supplied to +ovn-ic-nbctl change the database, then the command does +not wait at all. With the sync command, however, +ovn-ic-nbctl waits even for earlier changes to the +database to propagate down to the southbound database, according to the +argument of --wait. + + + Options + --no-wait | --wait=none + --wait=sb + + + + These options control whether and how ovn-ic-nbctl waits + for the OVN system to become up-to-date with changes made in an + ovn-ic-nbctl invocation. + + + + By default, or if --no-wait or --wait=none, + ovn-ic-nbctl exits immediately after confirming that + changes have been committed to the Interconnect northbound database, + without waiting. + + + + With --wait=sb, before ovn-ic-nbctl exits, + it waits for ovn-ics to bring the Interconnect + southbound database up-to-date with the Interconnect northbound + database updates. + + + + Ordinarily, --wait=sb only waits for changes by the + current ovn-ic-nbctl invocation to take effect. + This means that, if none of the commands supplied to + ovn-ic-nbctl change the database, then the command + does not wait at all. + Use the sync command to override this behavior. + + --db database The OVSDB database remote to contact. If the OVN_IC_NB_DB diff --git a/utilities/ovn-ic-nbctl.c b/utilities/ovn-ic-nbctl.c index 721dc4586..4317c385a 100644 --- a/utilities/ovn-ic-nbctl.c +++ b/utilities/ovn-ic-nbctl.c @@ -58,6 +58,13 @@ static bool oneline; /* --dry-run: Do not commit any changes. */ static bool dry_run; +/* --wait=TYPE: Wait for configuration change to take effect? */ +static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE; + +/* Should we wait (if specified by 'wait_type') even if the commands don't + * change the database at all */ +static bool force_wait = false; + /* --timeout: Time to wait for a connection to 'db'. */ static unsigned int timeout; @@ -161,6 +168,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) OPT_DB = UCHAR_MAX + 1, OPT_ONELINE, OPT_NO_SYSLOG, +OPT_NO_WAIT, +OPT_WAIT, OPT_DRY_RUN, OPT_LOCAL, OPT_COMMANDS, @@ -173,6 +182,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) static const struct option global_long_options[] = { {"db", required_argument, NULL, OPT_DB}, {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, +{"no-wait", no_argument, NULL, OPT_NO_WAIT}, +{"wait", required_argument, NULL, OPT_WAIT}, {"dry-run", no_argument, NULL, OPT_DRY_RUN}, {"oneline", no_argument, NULL, OPT_ONELINE}, {"timeout", required_argument, NULL, 't'}, @@ -234,7 +245,19 @@ parse_options(int argc, char *argv[], struct shash *local_options) case OPT_DRY_RUN: dry_run = true; break; - +case OPT_NO_WAIT: +wait_type = NBCTL_WAIT_NONE; +break; +case OPT_WAIT: +if (!strcmp(optarg, "none")) { +wait_type = NBCTL_WAIT_NONE; +} else if (!strcmp(optarg, "sb")) { +wait_type = NBCTL_WAIT_SB; +} else { +ctl_fatal("argument to --wait must be " + "\"none\", \"sb\" "); +} +break;
[ovs-dev] [PATCH ovn v5 4/4] ic/tests: Add unit test for ic sync command.
add unit test that check validate that sync command sync ISB properly Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 43 +++ 1 file changed, 43 insertions(+) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index d4c436f84..535aba7da 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -1274,3 +1274,46 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-ic -- sync ISB status to INB]) +ovn_init_ic_db +net_add n1 + +ovn_start az1 +sim_add gw-az1 +as gw-az1 + +check ovs-vsctl add-br br-phys +ovn_az_attach az1 n1 br-phys 192.168.1.1 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true +as az1 + +# pause ovn-ic instance +check ovn-appctl -t ic/ovn-ic pause + +# run sync command in the background this commands +# supposed to stuck since ovn-ic is paused. +ovn-ic-nbctl --wait=sb sync & + +OVS_WAIT_UNTIL([test $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg) -gt $(ovn-ic-nbctl get ic_nb_global . sb_ic_cfg)]) +AT_CHECK([ovn-ic-nbctl get ic_nb_global . nb_ic_cfg], [0], [dnl +1 +]) +AT_CHECK([ovn-ic-nbctl get ic_nb_global . sb_ic_cfg], [0], [dnl +0 +]) + +# resume ovn-ic instance +check ovn-appctl -t ic/ovn-ic resume +OVS_WAIT_UNTIL([test $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg) -eq $(ovn-ic-nbctl get ic_nb_global . sb_ic_cfg)]) +AT_CHECK([ovn-ic-nbctl get ic_nb_global . nb_ic_cfg], [0], [dnl +1 +]) +AT_CHECK([ovn-ic-nbctl get ic_nb_global . sb_ic_cfg], [0], [dnl +1 +]) + +OVN_CLEANUP_IC([az1]) +AT_CLEANUP +]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v5 2/4] ovn-ic: Implement basic INB change handling status.
This patch implements a basic sequence number protocol that can be used by CMS to determine if the changes applied to INB are successfully propagated to ISB. The implementation of this patch relies on OVN-ICs instances to update the ISB by adding a per AZ a nb_ic_cfg counter that will be updated by the OVN-IC once it is done and commit all needed changes to the ISB, and according to this AZ:nb_ic_cfg the ISB and INB will be updating about the status of the changes. Signed-off-by: Mohammad Heib --- ic/ovn-ic.c | 95 ++--- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 8ceb34d7c..d0b58d4d1 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -1782,16 +1782,95 @@ route_run(struct ic_context *ctx, hmap_destroy(&ic_lrs); } +/* + * This function implements a sequence number protocol that can be used by + * the INB end user to verify that ISB is synced with all the changes that + * are done be the user/AZs-controllers: + * + * Since we have multiple IC instances running in different regions + * we can't rely on one of them to update the ISB and sync that update + * to INB since other ICs can make changes in parallel. + * So to have a sequence number protocol working properly we must + * make sure that all the IC instances are synced with the ISB first + * and then update the INB. + * + * To guarantee that all instances are synced with ISB first, each IC + * will do the following steps: + * + * 1. when local ovn-ic sees that INB:nb_ic_cfg has updated we will set + *the ic_sb_loop->next_cfg to match the INB:nb_ic_cfg and increment + *the value of AZ:nb_ic_cfg and wait until we get confirmation from + *the server. + * + * 2. once this IC instance changes for ISB are committed successfully + *(next loop), the value of cur_cfg will be updated to match + *the INB:nb_ic_cfg that indicate that our local instance is up to date + *and no more changes need to be done for ISB. + * + * 3. validate that the AZ:nb_ic_cfg to match the INB:nb_ic_cfg. + * + * 4. Go through all the AZs and check if all have the same value of + *AZ:nb_ic_cfg that means all the AZs are done with ISB changes and ISB are + *up to date with INB, so we can set the values of ISB:nb_ic_cfg to + *INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg. + */ static void -ovn_db_run(struct ic_context *ctx) +update_sequence_numbers(const struct icsbrec_availability_zone *az, +struct ic_context *ctx, +struct ovsdb_idl_loop *ic_sb_loop) { -const struct icsbrec_availability_zone *az = az_run(ctx); -VLOG_DBG("Availability zone: %s", az ? az->name : "not created yet."); +if (!ctx->ovnisb_txn || !ctx->ovninb_txn) { +return; +} + +const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first( + ctx->ovninb_idl); +if (!ic_nb) { +ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn); +} +const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first( + ctx->ovnisb_idl); +if (!ic_sb) { +ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn); +} -if (!az) { +if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) && + (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) { +/* Deal with potential overflows. */ +if (az->nb_ic_cfg == LLONG_MAX) { +icsbrec_availability_zone_set_nb_ic_cfg(az, 0); +} +ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg; +ovsdb_idl_txn_increment(ctx->ovnisb_txn, &az->header_, + &icsbrec_availability_zone_col_nb_ic_cfg, true); return; } +/* handle cases where accidentally AZ:ic_nb_cfg exceeds + * the INB:ic_nb_cfg. + */ +if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) { +icsbrec_availability_zone_set_nb_ic_cfg(az, ic_sb_loop->cur_cfg); +return; +} + +const struct icsbrec_availability_zone *other_az; +ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) { +if (other_az->nb_ic_cfg != az->nb_ic_cfg) { +return; +} +} +/* All the AZs are updated successfully, update SB/NB counter. */ +if (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) { +icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg); +icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg); +} +} + +static void +ovn_db_run(struct ic_context *ctx, + const struct icsbrec_availability_zone *az) +{ ts_run(ctx); gateway_run(ctx, az); port_binding_run(ctx, az); @@ -2218,7 +2297,13 @@ main(int argc, char *argv[]) ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) && ovsdb_idl_h
[ovs-dev] [PATCH ovn v5 1/4] OVN-IC: Interconnect DBs add basic Information Flow columns.
Add basic flow columns to interconnect northbound DB and interconnect Southbound DB. Those columns will be used by future patches to add basic support for Information Flow in OVN interconnect. Signed-off-by: Mohammad Heib Acked-by: Mark Michelson Acked-by: Ales Musil --- NEWS| 8 ovn-ic-nb.ovsschema | 6 -- ovn-ic-nb.xml | 17 + ovn-ic-sb.ovsschema | 8 +--- ovn-ic-sb.xml | 21 + 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 5f267b4c6..9762af0e6 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,14 @@ Post v23.09.0 - ovn-northd-ddlog has been removed. - A new LSP option "enable_router_port_acl" has been added to enable conntrack for the router port whose peer is l3dgw_port if set it true. + - OVN Interconnection: +* INB provides basic feedback to the CMS about the ISB changes + handling status. +* IC_NB_Global now have "nb_ic_cfg" and "sb_ic_cfg" columns for + for ISB informational status. +* IC_SB_Global now have "nb_ic_cfg" column for ISB informational status. +* Availability_Zone now have "nb_ic_cfg" column for local AZ + informational status. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/ovn-ic-nb.ovsschema b/ovn-ic-nb.ovsschema index 894db8344..bee174357 100644 --- a/ovn-ic-nb.ovsschema +++ b/ovn-ic-nb.ovsschema @@ -1,10 +1,12 @@ { "name": "OVN_IC_Northbound", -"version": "1.0.0", -"cksum": "45589876 3383", +"version": "1.1.0", +"cksum": "3964083684 3501", "tables": { "IC_NB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, +"sb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, diff --git a/ovn-ic-nb.xml b/ovn-ic-nb.xml index 8c53bec3b..2ae9bf6d5 100644 --- a/ovn-ic-nb.xml +++ b/ovn-ic-nb.xml @@ -36,6 +36,23 @@ one row. + + These columns allow a client to track the overall configuration state of + the system. + + +Sequence number for client to increment. When a client modifies the +interconnect northbound database configuration and wishes to wait for +OVN-ICs to handle this change and update the Interconnect +southbound database, it may increment this sequence number. + + +Sequence number that one OVN-IC sets to the value of + after waiting to all the OVN-ICs +finish applying their changes to interconnect southbound database. + + + See External IDs at the beginning of this document. diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema index 1d60b36d1..5baf141cf 100644 --- a/ovn-ic-sb.ovsschema +++ b/ovn-ic-sb.ovsschema @@ -1,10 +1,11 @@ { "name": "OVN_IC_Southbound", -"version": "1.1.1", -"cksum": "3684563024 6914", +"version": "1.2.0", +"cksum": "1381014956 7032", "tables": { "IC_SB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, @@ -24,7 +25,8 @@ "isRoot": true}, "Availability_Zone": { "columns": { -"name": {"type": "string"}}, +"name": {"type": "string"}, +"nb_ic_cfg": {"type": {"key": "integer"}}}, "isRoot": true, "indexes": [["name"]]}, "Gateway": { diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml index f7e17e113..c3e7d2173 100644 --- a/ovn-ic-sb.xml +++ b/ovn-ic-sb.xml @@ -69,6 +69,21 @@ one row. + + This column allow a client to track the overall configuration state of + the system. + + +Sequence number for the configuration. When a CMS or +ovn-ic-nbctl updates the Interconnect northbound database, +it increments the nb_ic_cfg column in the +NB_IC_Global table in the Interconnect northbound +database. when OVN-ICs updates the southbound database to +bring it up to date with these changes, one OVN-IC updates +this column to the same value. + + + See External IDs at the beginning of this document. @@ -102,6 +117,12 @@ A name that uniquely identifies the availability zone. + + + This column is used by the OVN-IC to inform + that this IC instance is aligned with the changes in INB + + -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v5 0/4] OVN-IC: Add basic sequence number status support.
Currently, OVN-IC doesn't support a way to tell the end-user when their changes to the IC-NB database have propagated successfully to the IC-SB Database. This patch series adds basic support for the sequence number status protocol that is implemented on the native OVN, with this patch series the end user now can wait for their changes in the IC-NB DB to take effect by executing the 'sync' command after applying any changes to the IC-NB DB, for example, if the end-user has created a transit switch in the IC-NB global DB and want to make sure that the IC-SB create a DP binding for this ts-switch the user now can use the 'sync' command as following: $ ovn-ic-nbctl ts-add ts1 $ ovn-ic-nbctl --wait=sb sync The second command will wait until all the ovn-ic instances see the new changes and update their own local dbs and the global IC-SB db. v4 -> v5 * Addressed review comments from Ales to simplify the unit test and * a small comment on the ovn-ic. v3 -> v4 * Addressed review comments from Ales to add check for the overflow cases. v2 -> v3 * Rebase over main. * Addressed review comments from Mark and Ales. Mohammad Heib (4): OVN-IC: Interconnect DBs add basic Information Flow columns. ovn-ic: Implement basic INB change handling status. OVN-IC: Make it possible for CMS to detect when the ISB is up-to-date. ic/tests: Add unit test for ic sync command. NEWS | 8 +++ ic/ovn-ic.c | 95 ++-- ovn-ic-nb.ovsschema | 6 ++- ovn-ic-nb.xml| 17 +++ ovn-ic-sb.ovsschema | 8 +-- ovn-ic-sb.xml| 21 tests/ovn-ic.at | 43 utilities/ovn-ic-nbctl.8.xml | 49 +++ utilities/ovn-ic-nbctl.c | 86 +++- 9 files changed, 321 insertions(+), 12 deletions(-) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn v4 0/4] OVN-IC: add basic sequence number status support
Hi Ales, Yes sure that's what I'm planning to do next, i first wanted to make those patches accepted upstream and then update the test case to use the sync command, i guess it will be easier to review if send the test cases change as a separate patch, what do you think? On Fri, Jan 12, 2024 at 11:14 AM Ales Musil wrote: > > > On Tue, Jan 9, 2024 at 2:29 PM Mohammad Heib wrote: > >> Currently, OVN-IC doesn't support a way to tell the end-user when their >> changes >> to the IC-NB database have propagated successfully to the IC-SB Database. >> >> This patch series adds basic support for the sequence number status >> protocol >> that is implemented on the native OVN, with this patch series the end user >> now can wait for their changes in the IC-NB DB to take effect by >> executing the >> 'sync' command after applying any changes to the IC-NB DB, for example, >> if the >> end-user has created a transit switch in the IC-NB global DB and want to >> make >> sure that the IC-SB create a DP binding for this ts-switch the user now >> can use >> the 'sync' command as following: >> $ ovn-ic-nbctl ts-add ts1 >> $ ovn-ic-nbctl --wait=sb sync >> >> The second command will wait until all the ovn-ic instances see the new >> changes >> and update their own local dbs and the global IC-SB db. >> >> v3 -> v4 >> >> * Addressed review comments from Ales to add check for the >> overflow cases. >> >> v2 -> v3 >> >> * Rebase over main. >> * Addressed review comments from Mark and Ales. >> >> >> Mohammad Heib (4): >> OVN-IC: interconnect DBs add basic Information Flow columns >> ovn-ic: implement basic INB change handling status >> OVN-IC: Make it possible for CMS to detect when the ISB is up-to-date. >> ic/tests: add unit test for ic sync command >> >> NEWS | 8 +++ >> ic/ovn-ic.c | 96 ++-- >> ovn-ic-nb.ovsschema | 6 ++- >> ovn-ic-nb.xml| 17 +++ >> ovn-ic-sb.ovsschema | 8 +-- >> ovn-ic-sb.xml| 21 >> tests/ovn-ic.at | 47 ++ >> utilities/ovn-ic-nbctl.8.xml | 49 ++ >> utilities/ovn-ic-nbctl.c | 89 - >> 9 files changed, 329 insertions(+), 12 deletions(-) >> >> -- >> 2.34.3 >> >> ___ >> dev mailing list >> d...@openvswitch.org >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> >> > Hi Mohammad, > > thank you for the series. This suggestion is out of scope of this series, > but it would be great to use the new sync across all ic tests that we > currently have to further stabilize them. WDYT? > > 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
Re: [ovs-dev] [PATCH ovn 2/2] OVN-SB: Exposes igmp group protocol version through IGMP table.
On Tue, Jan 23, 2024 at 4:10 PM Dumitru Ceara wrote: > On 1/23/24 14:58, Mohammad Heib wrote: > >>> static struct pinctrl pinctrl; > >>> @@ -3586,11 +3587,21 @@ pinctrl_update(const struct ovsdb_idl *idl, > >> const char *br_int_name) > >>> if (dns_supports_ovn_owned != pinctrl.dns_supports_ovn_owned) { > >>> pinctrl.dns_supports_ovn_owned = dns_supports_ovn_owned; > >>> > >>> -/* Notify pinctrl_handler that fdb timestamp column > >>> +/* Notify pinctrl_handler that dns ovn_owned column > >>> * availability has changed. */ > >>> notify_pinctrl_handler(); > >>> } > >>> > >>> +bool igmp_support_proto = > >>> +sbrec_server_has_igmp_group_table_col_protocol(idl); > >>> +if (igmp_support_proto != pinctrl.igmp_support_protocol) { > >>> +pinctrl.igmp_support_protocol = igmp_support_proto; > >> We only use this in the main thread, when updating the SB, why can't we > >> just directly check the column support there instead? > >> > > *like you mean to call > > sbrec_server_has_igmp_group_table_col_protocol(idl); inside the > **ip_mcast_sync > > function?* > > *something like this:* > > > > > > > > > > */* Set Group protocol*/if > > (sbrec_server_has_igmp_group_table_col_protocol(idl)) { > > igmp_group_set_protocol(sbrec_igmp, > > mc_group->protocol_version);}* > > Yes, I think that would be better. Or even inside > igmp_group_update_ports() but then we should also pass the IDL pointer; > the latter seems like a better option to me. > > Please let me know what you think. > Sound good to me :), i will send v2 addressing your comments when I can bump the ovs to the last stable. Thank you so much :) > > Regards, > Dumitru > > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn 2/2] OVN-SB: Exposes igmp group protocol version through IGMP table.
On Mon, Jan 22, 2024 at 5:26 PM Dumitru Ceara wrote: > On 1/22/24 15:14, Mohammad Heib wrote: > > Expose the igmp/mld group protocol version through the > > IGMP_GROUP table in SBDB. > > > > This patch can be used by ovn consumer for debuggability purposes, user > > now can match between the protocol version used in the OVN logical > > switches and the uplink ports. > > > > Rreported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2160476 > > Signed-off-by: Mohammad Heib > > --- > Hi Dumitru, Thank you for your review :), i have small question please see below. > Hi Mohammad, > > I have a few (minor) comments, please see below. > > > NEWS | 2 ++ > > controller/ip-mcast.c | 8 > > controller/ip-mcast.h | 3 +++ > > controller/pinctrl.c | 19 ++- > > northd/ovn-northd.c | 2 +- > > ovn-sb.ovsschema | 5 +++-- > > ovn-sb.xml| 4 > > tests/ovn.at | 3 +++ > > 8 files changed, 42 insertions(+), 4 deletions(-) > > > > diff --git a/NEWS b/NEWS > > index 5f267b4c6..9075e7d80 100644 > > --- a/NEWS > > +++ b/NEWS > > @@ -14,6 +14,8 @@ Post v23.09.0 > >- ovn-northd-ddlog has been removed. > >- A new LSP option "enable_router_port_acl" has been added to enable > > conntrack for the router port whose peer is l3dgw_port if set it > true. > > + - IGMP_Group have a new "protocol" column that displays the the group > > Nit: s/have/has > > > +protocol version. > > > > OVN v23.09.0 - 15 Sep 2023 > > -- > > diff --git a/controller/ip-mcast.c b/controller/ip-mcast.c > > index a870fb29e..83e41c81f 100644 > > --- a/controller/ip-mcast.c > > +++ b/controller/ip-mcast.c > > @@ -226,6 +226,14 @@ igmp_group_cleanup(struct ovsdb_idl_txn > *ovnsb_idl_txn, > > return true; > > } > > > > + > > +void igmp_group_set_protocol(const struct sbrec_igmp_group *group, > > + mcast_group_proto protocol) > > +{ > > +sbrec_igmp_group_set_protocol(group, > > + > mcast_snooping_group_protocol_str(protocol)); > > +} > > + > > Does it make more sense to add the protocol as argument to > igmp_group_update_ports() and rename that function to igmp_group_update()? > yes that make sense and will make the code more cleaner. > > > static const struct sbrec_igmp_group * > > igmp_group_lookup_(struct ovsdb_idl_index *igmp_groups, > > const char *addr_str, > > diff --git a/controller/ip-mcast.h b/controller/ip-mcast.h > > index 326f39db1..f0c34343f 100644 > > --- a/controller/ip-mcast.h > > +++ b/controller/ip-mcast.h > > @@ -63,4 +63,7 @@ void igmp_group_delete(const struct sbrec_igmp_group > *g); > > bool igmp_group_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, > > struct ovsdb_idl_index *igmp_groups); > > > > +void igmp_group_set_protocol(const struct sbrec_igmp_group *group, > > + mcast_group_proto protocol); > > + > > #endif /* controller/ip-mcast.h */ > > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > > index 77bf67e58..6379b7afb 100644 > > --- a/controller/pinctrl.c > > +++ b/controller/pinctrl.c > > @@ -180,6 +180,7 @@ struct pinctrl { > > bool mac_binding_can_timestamp; > > bool fdb_can_timestamp; > > bool dns_supports_ovn_owned; > > +bool igmp_support_protocol; > > }; > > > > static struct pinctrl pinctrl; > > @@ -3586,11 +3587,21 @@ pinctrl_update(const struct ovsdb_idl *idl, > const char *br_int_name) > > if (dns_supports_ovn_owned != pinctrl.dns_supports_ovn_owned) { > > pinctrl.dns_supports_ovn_owned = dns_supports_ovn_owned; > > > > -/* Notify pinctrl_handler that fdb timestamp column > > +/* Notify pinctrl_handler that dns ovn_owned column > > * availability has changed. */ > > notify_pinctrl_handler(); > > } > > > > +bool igmp_support_proto = > > +sbrec_server_has_igmp_group_table_col_protocol(idl); > > +if (igmp_support_proto != pinctrl.igmp_support_protocol) { > > +pinctrl.igmp_support_protocol = igmp_support_proto; > > We only use this in the main thread, when updating the SB, why can't we > just directly check the column support there instead? > *like you mean to call sbrec_server_has_igmp_group_table_col_protocol(idl); insid
Re: [ovs-dev] [PATCH ovn 1/2] ovs: Bump submodule to include igmp protocol version.
Hi Dumitru, Thank you for the review, yes sure will bump the submodule to the last stable once they fix the issue. Thanks On Mon, Jan 22, 2024 at 5:01 PM Dumitru Ceara wrote: > On 1/22/24 15:14, Mohammad Heib wrote: > > Specifically the following commit: > > 077d0bad0436 ("mcast-snooping: Store IGMP/MLD protocol version.") > > > > Also fix a small compilation error due to prototype change. > > > > Signed-off-by: Mohammad Heib > > --- > > Hi Mohammad, > > Thanks for the patch! > > > controller/pinctrl.c | 6 +- > > ovs | 2 +- > > 2 files changed, 6 insertions(+), 2 deletions(-) > > > > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > > index 4992eab08..77bf67e58 100644 > > --- a/controller/pinctrl.c > > +++ b/controller/pinctrl.c > > @@ -5474,9 +5474,13 @@ pinctrl_ip_mcast_handle_igmp(struct rconn *swconn, > > switch (ntohs(ip_flow->tp_src)) { > > case IGMP_HOST_MEMBERSHIP_REPORT: > > case IGMPV2_HOST_MEMBERSHIP_REPORT: > > +mcast_group_proto grp_proto = > > +(ntohs(ip_flow->tp_src) == IGMP_HOST_MEMBERSHIP_REPORT) > > +? MCAST_GROUP_IGMPV1 > > +: MCAST_GROUP_IGMPV2; > > group_change = > > mcast_snooping_add_group4(ip_ms->ms, ip4, IP_MCAST_VLAN, > > - port_key_data); > > + port_key_data, grp_proto); > > break; > > case IGMP_HOST_LEAVE_MESSAGE: > > group_change = > > diff --git a/ovs b/ovs > > index 4102674b3..b222593bc 16 > > --- a/ovs > > +++ b/ovs > > @@ -1 +1 @@ > > -Subproject commit 4102674b3ecadb0e20e512cc661cddbbc4b3d1f6 > > +Subproject commit b222593bc69b5d82849d18eb435564f5f93449d3 > > However, it's probably desirable to bump the submodule to the tip of the > latest stable branch, i.e. branch-3.3: > > > https://github.com/ovn-org/ovn/blob/main/Documentation/internals/ovs_submodule.rst#submodules-for-releases > > That would also fix our scheduled CI runs: > > https://github.com/ovn-org/ovn/actions/runs/7597582431/job/20692570222#step:10:3531 > > However, there's a crash in OVS on branch-3.3 that needs to be fixed first: > https://issues.redhat.com/browse/FDP-300 > > I'd wait with bumping the submodule until then. > > Regards, > Dumitru > > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v2] ovn-ic: Handle NB:name updates properly.
When the user updates the NB_GLOBAL.name after registering to IC Databases if the user already has defined chassis as a gateway that will cause ovn-ic instance to run in an infinity loop trying to update the gateways and insert the current gateway to the SB.chassis tables as a remote chassis (we match on the new AZ ) which will fail since we already have this chassis with is-interconn in local SB. This patch aims to fix the above issues by updating the AZ.name only when the user updates the NB.name locally. Signed-off-by: Mohammad Heib Acked-by: Dumitru Ceara --- ic/ovn-ic.c | 10 +++--- tests/ovn-ic.at | 24 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 8ceb34d7c..12e2729ce 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -132,14 +132,18 @@ az_run(struct ic_context *ctx) return NULL; } -/* Delete old AZ if name changes. Note: if name changed when ovn-ic - * is not running, one has to manually delete the old AZ with: +/* Update old AZ if name changes. Note: if name changed when ovn-ic + * is not running, one has to manually delete/update the old AZ with: * "ovn-ic-sbctl destroy avail ". */ static char *az_name; const struct icsbrec_availability_zone *az; if (az_name && strcmp(az_name, nb_global->name)) { ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) { -if (!strcmp(az->name, az_name)) { +/* AZ name update locally need to update az in ISB. */ +if (nb_global->name[0] && !strcmp(az->name, az_name)) { +icsbrec_availability_zone_set_name(az, nb_global->name); +break; +} else if (!nb_global->name[0] && !strcmp(az->name, az_name)) { icsbrec_availability_zone_delete(az); break; } diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index d4c436f84..6061d054c 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -28,7 +28,31 @@ availability-zone az3 ]) OVN_CLEANUP_IC([az1], [az2]) +AT_CLEANUP +]) + + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-ic -- AZ update in GW]) +ovn_init_ic_db +net_add n1 +ovn_start az1 +sim_add gw-az1 +as gw-az1 + +check ovs-vsctl add-br br-phys +ovn_az_attach az1 n1 br-phys 192.168.1.1 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true + +az_uuid=$(fetch_column ic-sb:availability-zone _uuid name="az1") +ovn_as az1 ovn-nbctl set NB_Global . name="az2" +wait_column "$az_uuid" ic-sb:availability-zone _uuid name="az2" + +# make sure that gateway still point to the same AZ with new name +wait_column "$az_uuid" ic-sb:gateway availability_zone name="gw-az1" + +OVN_CLEANUP_IC([az1]) AT_CLEANUP ]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn] Controller: Handle unconditional IDL messages while paused.
If the user triggers a pause command to the ovn-controller the current implementation will wait for commands from unixctl server only and ignore the other component. This implementation works fine if we don't have inactivity_probe set in the SB DataBase, but once the user sets the inactivity_probe in SB DataBase the connection will be dropped by the SBDB. Once the controller resumes the execution it will try to commit some changes to the SBDB but the transaction will fail since we lost the connection to the SBDB and the controller must reconnect before committing the transaction again. To avoid the above scenario the controller can keep handling unconditional IDL messages to avoid reconnecting to SB. Signed-off-by: Mohammad Heib --- controller/ovn-controller.c | 16 +--- ovn-sb.xml | 2 +- tests/ovn-controller.at | 51 + 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 856e5e270..d2c8f66d9 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -5534,12 +5534,22 @@ main(int argc, char *argv[]) simap_destroy(&usage); } -/* If we're paused just run the unixctl server and skip most of the - * processing loop. +/* If we're paused just run the unixctl-server/unconditional IDL and + * skip most of the processing loop. */ if (paused) { unixctl_server_run(unixctl); +int ovnsb_seq = ovsdb_idl_get_seqno(ovnsb_idl_loop.idl); +ovsdb_idl_run(ovnsb_idl_loop.idl); +int new_ovnsb_seq = ovsdb_idl_get_seqno(ovnsb_idl_loop.idl); +/* If the IDL content has changed while the controller is + * in pause state, trigger a recompute. + */ +if (new_ovnsb_seq != ovnsb_seq) { +engine_set_force_recompute(true); +} unixctl_server_wait(unixctl); +ovsdb_idl_wait(ovnsb_idl_loop.idl); goto loop_done; } @@ -6009,7 +6019,6 @@ main(int argc, char *argv[]) OVS_NOT_REACHED(); } -ovsdb_idl_track_clear(ovnsb_idl_loop.idl); ovsdb_idl_track_clear(ovs_idl_loop.idl); lflow_cache_run(ctrl_engine_ctx.lflow_cache); @@ -6017,6 +6026,7 @@ main(int argc, char *argv[]) loop_done: memory_wait(); +ovsdb_idl_track_clear(ovnsb_idl_loop.idl); poll_block(); if (should_service_stop()) { exit_args.exiting = true; diff --git a/ovn-sb.xml b/ovn-sb.xml index e393f92b3..43c13f23c 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -4308,7 +4308,7 @@ tcp.flags = RST; Maximum number of milliseconds of idle time on connection to the client before sending an inactivity probe message. If Open vSwitch does not -communicate with the client for the specified number of seconds, it +communicate with the client for the specified number of milliseconds,it will send a probe. If a response is not received for the same additional amount of time, Open vSwitch assumes the connection has been broken and attempts to reconnect. Default is implementation-specific. diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index 9d2a37c72..04e4c52e7 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -352,6 +352,57 @@ OVS_APP_EXIT_AND_WAIT([ovsdb-server]) AT_CLEANUP ]) +# Check that the connection to the Southbound database +# is not dropped when probe-interval is set and the controller +# is in pause state. +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller - check sbdb connection while pause]) +AT_KEYWORDS([ovn]) +ovn_start + +net_add n1 +sim_add hv +as hv +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 + +ovs-vsctl -- add-port br-int hv1-vif1 -- \ +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ +options:tx_pcap=hv1/vif1-tx.pcap \ +options:rxq_pcap=hv1/vif1-rx.pcap \ +ofport-request=1 + +ovs-vsctl set open . external_ids:ovn-remote-probe-interval=10 +ovn-sbctl set connection . inactivity_probe=1 + +ovn-nbctl ls-add sw0 +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3" +check ovn-nbctl lsp-set-port-security sw0-p1 "50:54:00:00:00:03 10.0.0.3" +ovn-nbctl --wait=hv sync + +sleep_controller hv +# Trigger DB change to make SBDB connect to controller. +check ovn-nbctl lsp-del sw0-p1 + +# wait for 2 sec to give enough time to the SBDB to drop the connection +# if there is no answer from the controller. The connection should not +# be dropped since we keep handle the idl messages from SBDB even if we +# in pause state. +sleep 2 +wake_up_controller hv + +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3
[ovs-dev] [PATCH ovn 2/2] OVN-SB: Exposes igmp group protocol version through IGMP table.
Expose the igmp/mld group protocol version through the IGMP_GROUP table in SBDB. This patch can be used by ovn consumer for debuggability purposes, user now can match between the protocol version used in the OVN logical switches and the uplink ports. Rreported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2160476 Signed-off-by: Mohammad Heib --- NEWS | 2 ++ controller/ip-mcast.c | 8 controller/ip-mcast.h | 3 +++ controller/pinctrl.c | 19 ++- northd/ovn-northd.c | 2 +- ovn-sb.ovsschema | 5 +++-- ovn-sb.xml| 4 tests/ovn.at | 3 +++ 8 files changed, 42 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 5f267b4c6..9075e7d80 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,8 @@ Post v23.09.0 - ovn-northd-ddlog has been removed. - A new LSP option "enable_router_port_acl" has been added to enable conntrack for the router port whose peer is l3dgw_port if set it true. + - IGMP_Group have a new "protocol" column that displays the the group +protocol version. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/controller/ip-mcast.c b/controller/ip-mcast.c index a870fb29e..83e41c81f 100644 --- a/controller/ip-mcast.c +++ b/controller/ip-mcast.c @@ -226,6 +226,14 @@ igmp_group_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, return true; } + +void igmp_group_set_protocol(const struct sbrec_igmp_group *group, + mcast_group_proto protocol) +{ +sbrec_igmp_group_set_protocol(group, + mcast_snooping_group_protocol_str(protocol)); +} + static const struct sbrec_igmp_group * igmp_group_lookup_(struct ovsdb_idl_index *igmp_groups, const char *addr_str, diff --git a/controller/ip-mcast.h b/controller/ip-mcast.h index 326f39db1..f0c34343f 100644 --- a/controller/ip-mcast.h +++ b/controller/ip-mcast.h @@ -63,4 +63,7 @@ void igmp_group_delete(const struct sbrec_igmp_group *g); bool igmp_group_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *igmp_groups); +void igmp_group_set_protocol(const struct sbrec_igmp_group *group, + mcast_group_proto protocol); + #endif /* controller/ip-mcast.h */ diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 77bf67e58..6379b7afb 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -180,6 +180,7 @@ struct pinctrl { bool mac_binding_can_timestamp; bool fdb_can_timestamp; bool dns_supports_ovn_owned; +bool igmp_support_protocol; }; static struct pinctrl pinctrl; @@ -3586,11 +3587,21 @@ pinctrl_update(const struct ovsdb_idl *idl, const char *br_int_name) if (dns_supports_ovn_owned != pinctrl.dns_supports_ovn_owned) { pinctrl.dns_supports_ovn_owned = dns_supports_ovn_owned; -/* Notify pinctrl_handler that fdb timestamp column +/* Notify pinctrl_handler that dns ovn_owned column * availability has changed. */ notify_pinctrl_handler(); } +bool igmp_support_proto = +sbrec_server_has_igmp_group_table_col_protocol(idl); +if (igmp_support_proto != pinctrl.igmp_support_protocol) { +pinctrl.igmp_support_protocol = igmp_support_proto; + +/* Notify pinctrl_handler that igmp protocol column + * availability has changed. */ +notify_pinctrl_handler(); +} + ovs_mutex_unlock(&pinctrl_mutex); } @@ -5400,6 +5411,12 @@ ip_mcast_sync(struct ovsdb_idl_txn *ovnsb_idl_txn, local_dp->datapath, chassis); } +/* Set Group protocol*/ +if (pinctrl.igmp_support_protocol) { +igmp_group_set_protocol(sbrec_igmp, +mc_group->protocol_version); +} + igmp_group_update_ports(sbrec_igmp, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, ip_ms->ms, mc_group); diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index f3868068d..700c9cf6e 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -120,7 +120,7 @@ static const char *rbac_svc_monitor_auth_update[] = static const char *rbac_igmp_group_auth[] = {""}; static const char *rbac_igmp_group_update[] = -{"address", "chassis", "datapath", "ports"}; +{"address", "protocol", "chassis", "datapath", "ports"}; static const char *rbac_bfd_auth[] = {""}; static const char *rbac_bfd_update[] = diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index 72e230b75..240d65f69 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", -"version&qu
[ovs-dev] [PATCH ovn 1/2] ovs: Bump submodule to include igmp protocol version.
Specifically the following commit: 077d0bad0436 ("mcast-snooping: Store IGMP/MLD protocol version.") Also fix a small compilation error due to prototype change. Signed-off-by: Mohammad Heib --- controller/pinctrl.c | 6 +- ovs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 4992eab08..77bf67e58 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -5474,9 +5474,13 @@ pinctrl_ip_mcast_handle_igmp(struct rconn *swconn, switch (ntohs(ip_flow->tp_src)) { case IGMP_HOST_MEMBERSHIP_REPORT: case IGMPV2_HOST_MEMBERSHIP_REPORT: +mcast_group_proto grp_proto = +(ntohs(ip_flow->tp_src) == IGMP_HOST_MEMBERSHIP_REPORT) +? MCAST_GROUP_IGMPV1 +: MCAST_GROUP_IGMPV2; group_change = mcast_snooping_add_group4(ip_ms->ms, ip4, IP_MCAST_VLAN, - port_key_data); + port_key_data, grp_proto); break; case IGMP_HOST_LEAVE_MESSAGE: group_change = diff --git a/ovs b/ovs index 4102674b3..b222593bc 16 --- a/ovs +++ b/ovs @@ -1 +1 @@ -Subproject commit 4102674b3ecadb0e20e512cc661cddbbc4b3d1f6 +Subproject commit b222593bc69b5d82849d18eb435564f5f93449d3 -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v4 3/4] OVN-IC: Make it possible for CMS to detect when the ISB is up-to-date.
Until now, there has been no reliable for the CMS to detect when changes made to the INB configuration have been passed through to the ISB, This commit adds this feature to the system, by adding sequence numbers to the INB and ISB and adding code in ovn-ic-nbctl, ovn-ic to keep those sequence numbers up-to-date. The biggest user-visible change from this commit is a new option '--wait' and new command 'sync' to ovn-ic-nbctl. With --wait=sb, ovn-ic-nbctl now waits for ovn-ics to update the ISB database. Signed-off-by: Mohammad Heib Acked-by: Mark Michelson --- utilities/ovn-ic-nbctl.8.xml | 49 utilities/ovn-ic-nbctl.c | 86 +++- 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/utilities/ovn-ic-nbctl.8.xml b/utilities/ovn-ic-nbctl.8.xml index 4a70994b8..5a1324d2d 100644 --- a/utilities/ovn-ic-nbctl.8.xml +++ b/utilities/ovn-ic-nbctl.8.xml @@ -123,9 +123,58 @@ +Synchronization Commands + + + sync + +Ordinarily, --wait=sb only waits for changes by the +current ovn-ic-nbctl invocation to take effect. +This means that, if none of the commands supplied to +ovn-ic-nbctl change the database, then the command does +not wait at all. With the sync command, however, +ovn-ic-nbctl waits even for earlier changes to the +database to propagate down to the southbound database, according to the +argument of --wait. + + + Options + --no-wait | --wait=none + --wait=sb + + + + These options control whether and how ovn-ic-nbctl waits + for the OVN system to become up-to-date with changes made in an + ovn-ic-nbctl invocation. + + + + By default, or if --no-wait or --wait=none, + ovn-ic-nbctl exits immediately after confirming that + changes have been committed to the Interconnect northbound database, + without waiting. + + + + With --wait=sb, before ovn-ic-nbctl exits, + it waits for ovn-ics to bring the Interconnect + southbound database up-to-date with the Interconnect northbound + database updates. + + + + Ordinarily, --wait=sb only waits for changes by the + current ovn-ic-nbctl invocation to take effect. + This means that, if none of the commands supplied to + ovn-ic-nbctl change the database, then the command + does not wait at all. + Use the sync command to override this behavior. + + --db database The OVSDB database remote to contact. If the OVN_IC_NB_DB diff --git a/utilities/ovn-ic-nbctl.c b/utilities/ovn-ic-nbctl.c index 721dc4586..4317c385a 100644 --- a/utilities/ovn-ic-nbctl.c +++ b/utilities/ovn-ic-nbctl.c @@ -58,6 +58,13 @@ static bool oneline; /* --dry-run: Do not commit any changes. */ static bool dry_run; +/* --wait=TYPE: Wait for configuration change to take effect? */ +static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE; + +/* Should we wait (if specified by 'wait_type') even if the commands don't + * change the database at all */ +static bool force_wait = false; + /* --timeout: Time to wait for a connection to 'db'. */ static unsigned int timeout; @@ -161,6 +168,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) OPT_DB = UCHAR_MAX + 1, OPT_ONELINE, OPT_NO_SYSLOG, +OPT_NO_WAIT, +OPT_WAIT, OPT_DRY_RUN, OPT_LOCAL, OPT_COMMANDS, @@ -173,6 +182,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) static const struct option global_long_options[] = { {"db", required_argument, NULL, OPT_DB}, {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, +{"no-wait", no_argument, NULL, OPT_NO_WAIT}, +{"wait", required_argument, NULL, OPT_WAIT}, {"dry-run", no_argument, NULL, OPT_DRY_RUN}, {"oneline", no_argument, NULL, OPT_ONELINE}, {"timeout", required_argument, NULL, 't'}, @@ -234,7 +245,19 @@ parse_options(int argc, char *argv[], struct shash *local_options) case OPT_DRY_RUN: dry_run = true; break; - +case OPT_NO_WAIT: +wait_type = NBCTL_WAIT_NONE; +break; +case OPT_WAIT: +if (!strcmp(optarg, "none")) { +wait_type = NBCTL_WAIT_NONE; +} else if (!strcmp(optarg, "sb")) { +wait_type = NBCTL_WAIT_SB; +} else { +ctl_fatal("argument to --wait must be " + "\"none\", \"sb\" "); +} +break; case OPT_LO
[ovs-dev] [PATCH ovn v4 4/4] ic/tests: add unit test for ic sync command
add unit test that check validate that sync command sync ISB properly Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 47 +++ 1 file changed, 47 insertions(+) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index d4c436f84..f55ffa6cd 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -1274,3 +1274,50 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) + +AT_SETUP([ovn-ic -- sync ISB status to INB]) +ovn_init_ic_db +net_add n1 + +ovn_start az1 +sim_add gw-az1 +as gw-az1 + +check ovs-vsctl add-br br-phys +ovn_az_attach az1 n1 br-phys 192.168.1.1 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true +as az1 + +# pause ovn-ic instance +check ovn-appctl -t ic/ovn-ic pause + +# run sync command in the background this commands +# supposed to stuck since ovn-ic is paused. +$(ovn-ic-nbctl --wait=sb sync &) + +for i in {1..5}; do +set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) +AS_VAR_SET([ic_nb_cfg], [$1]) +AS_VAR_SET([ic_sb_cfg], [$2]) +if test $ic_nb_cfg -gt $ic_sb_cfg; then +sleep 1 +else +break +fi +done + +# if ic_nb_cfg equal to ic_sb_cfg that mean both zero +# or both 1 which is a not correct and the test must fail. +AT_FAIL_IF([test $ic_nb_cfg == $ic_sb_cfg]) + +# resume ovn-ic instance +check ovn-appctl -t ic/ovn-ic resume +set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) +AS_VAR_SET([ic_nb_cfg], [$1]) +AS_VAR_SET([ic_sb_cfg], [$2]) +AT_FAIL_IF([test $ic_nb_cfg != 1]) +AT_FAIL_IF([test $ic_nb_cfg != 1]) + +OVN_CLEANUP_IC([az1]) +AT_CLEANUP +]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v4 2/4] ovn-ic: implement basic INB change handling status
This patch implements a basic sequence number protocol that can be used by CMS to determine if the changes applied to INB are successfully propagated to ISB. The implementation of this patch relies on OVN-ICs instances to update the ISB by adding a per AZ a nb_ic_cfg counter that will be updated by the OVN-IC once it is done and commit all needed changes to the ISB, and according to this AZ:nb_ic_cfg the ISB and INB will be updating about the status of the changes. Signed-off-by: Mohammad Heib --- ic/ovn-ic.c | 96 ++--- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 8ceb34d7c..ba393e910 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -1782,16 +1782,96 @@ route_run(struct ic_context *ctx, hmap_destroy(&ic_lrs); } +/* + * This function implements a sequence number protocol that can be used by + * the INB end user to verify that ISB is synced with all the changes that + * are done be the user/AZs-controllers: + * + * Since we have multiple IC instances running in different regions + * we can't rely on one of them to update the ISB and sync that update + * to INB since other ICs can make changes in parallel. + * So to have a sequence number protocol working properly we must + * make sure that all the IC instances are synced with the ISB first + * and then update the INB. + * + * To guarantee that all instances are synced with ISB first, each IC + * will do the following steps: + * + * 1. when local ovn-ic sees that INB:nb_ic_cfg has updated we will set + *the ic_sb_loop->next_cfg to match the INB:nb_ic_cfg and increment + *the value of AZ:nb_ic_cfg and wait until we get confirmation from + *the server. + * + * 2. once this IC instance changes for ISB are committed successfully + *(next loop), the value of cur_cfg will be updated to match + *the INB:nb_ic_cfg that indicate that our local instance is up to date + *and no more changes need to be done for ISB. + * + * 3. validate that the AZ:nb_ic_cfg to match the INB:nb_ic_cfg. + * + * 4. Go through all the AZs and check if all have the same value of + *AZ:nb_ic_cfg that means all the AZs are done with ISB changes and ISB are + *up to date with INB, so we can set the values of ISB:nb_ic_cfg to + *INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg. + */ static void -ovn_db_run(struct ic_context *ctx) +update_sequence_numbers(const struct icsbrec_availability_zone *az, +struct ic_context *ctx, +struct ovsdb_idl_loop *ic_sb_loop) { -const struct icsbrec_availability_zone *az = az_run(ctx); -VLOG_DBG("Availability zone: %s", az ? az->name : "not created yet."); +bool azs_cfg_equals = true; +if (!ctx->ovnisb_txn || !ctx->ovninb_txn) { +return; +} -if (!az) { +const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first( + ctx->ovninb_idl); +if (!ic_nb) { +ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn); +} +const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first( + ctx->ovnisb_idl); +if (!ic_sb) { +ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn); +} + +if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) && + (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) { +/* Deal with potential overflows. */ +if (az->nb_ic_cfg == LLONG_MAX) { +icsbrec_availability_zone_set_nb_ic_cfg(az, 0); +} +ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg; +ovsdb_idl_txn_increment(ctx->ovnisb_txn, &az->header_, + &icsbrec_availability_zone_col_nb_ic_cfg, true); return; } +/* handle cases where accidentally AZ:ic_nb_cfg exceeds + * the INB:ic_nb_cfg. + */ +if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) { +icsbrec_availability_zone_set_nb_ic_cfg(az, ic_sb_loop->cur_cfg); +return; +} + +const struct icsbrec_availability_zone *other_az; +ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) { +if (other_az->nb_ic_cfg != az->nb_ic_cfg) { +azs_cfg_equals = false; +} +} + +if (azs_cfg_equals && (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg)) { +icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg); +icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg); +} +} + +static void +ovn_db_run(struct ic_context *ctx, + const struct icsbrec_availability_zone *az) +{ ts_run(ctx); gateway_run(ctx, az); port_binding_run(ctx, az); @@ -2218,7 +2298,13 @@ main(int argc, char *argv[]) ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) && ovs
[ovs-dev] [PATCH ovn v4 1/4] OVN-IC: interconnect DBs add basic Information Flow columns
Add basic flow columns to interconnect northbound DB and interconnect Southbound DB. Those columns will be used by future patches to add basic support for Information Flow in OVN interconnect. Signed-off-by: Mohammad Heib Acked-by: Mark Michelson Acked-by: Ales Musil --- NEWS| 8 ovn-ic-nb.ovsschema | 6 -- ovn-ic-nb.xml | 17 + ovn-ic-sb.ovsschema | 8 +--- ovn-ic-sb.xml | 21 + 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 20df92cb7..23609957c 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,14 @@ Post v23.09.0 - Support CIDR based MAC binding aging threshold. See ovn-nb(5) for 'mac_binding_age_threshold' for more details. - ovn-northd-ddlog has been removed. + - OVN Interconnection: +* INB provides basic feedback to the CMS about the ISB changes + handling status. +* IC_NB_Global now have "nb_ic_cfg" and "sb_ic_cfg" columns for + for ISB informational status. +* IC_SB_Global now have "nb_ic_cfg" column for ISB informational status. +* Availability_Zone now have "nb_ic_cfg" column for local AZ + informational status. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/ovn-ic-nb.ovsschema b/ovn-ic-nb.ovsschema index 894db8344..bee174357 100644 --- a/ovn-ic-nb.ovsschema +++ b/ovn-ic-nb.ovsschema @@ -1,10 +1,12 @@ { "name": "OVN_IC_Northbound", -"version": "1.0.0", -"cksum": "45589876 3383", +"version": "1.1.0", +"cksum": "3964083684 3501", "tables": { "IC_NB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, +"sb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, diff --git a/ovn-ic-nb.xml b/ovn-ic-nb.xml index 8c53bec3b..2ae9bf6d5 100644 --- a/ovn-ic-nb.xml +++ b/ovn-ic-nb.xml @@ -36,6 +36,23 @@ one row. + + These columns allow a client to track the overall configuration state of + the system. + + +Sequence number for client to increment. When a client modifies the +interconnect northbound database configuration and wishes to wait for +OVN-ICs to handle this change and update the Interconnect +southbound database, it may increment this sequence number. + + +Sequence number that one OVN-IC sets to the value of + after waiting to all the OVN-ICs +finish applying their changes to interconnect southbound database. + + + See External IDs at the beginning of this document. diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema index 1d60b36d1..5baf141cf 100644 --- a/ovn-ic-sb.ovsschema +++ b/ovn-ic-sb.ovsschema @@ -1,10 +1,11 @@ { "name": "OVN_IC_Southbound", -"version": "1.1.1", -"cksum": "3684563024 6914", +"version": "1.2.0", +"cksum": "1381014956 7032", "tables": { "IC_SB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, @@ -24,7 +25,8 @@ "isRoot": true}, "Availability_Zone": { "columns": { -"name": {"type": "string"}}, +"name": {"type": "string"}, +"nb_ic_cfg": {"type": {"key": "integer"}}}, "isRoot": true, "indexes": [["name"]]}, "Gateway": { diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml index f7e17e113..c3e7d2173 100644 --- a/ovn-ic-sb.xml +++ b/ovn-ic-sb.xml @@ -69,6 +69,21 @@ one row. + + This column allow a client to track the overall configuration state of + the system. + + +Sequence number for the configuration. When a CMS or +ovn-ic-nbctl updates the Interconnect northbound database, +it increments the nb_ic_cfg column in the +NB_IC_Global table in the Interconnect northbound +database. when OVN-ICs updates the southbound database to +bring it up to date with these changes, one OVN-IC updates +this column to the same value. + + + See External IDs at the beginning of this document. @@ -102,6 +117,12 @@ A name that uniquely identifies the availability zone. + + + This column is used by the OVN-IC to inform + that this IC instance is aligned with the changes in INB + + -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v4 0/4] OVN-IC: add basic sequence number status support
Currently, OVN-IC doesn't support a way to tell the end-user when their changes to the IC-NB database have propagated successfully to the IC-SB Database. This patch series adds basic support for the sequence number status protocol that is implemented on the native OVN, with this patch series the end user now can wait for their changes in the IC-NB DB to take effect by executing the 'sync' command after applying any changes to the IC-NB DB, for example, if the end-user has created a transit switch in the IC-NB global DB and want to make sure that the IC-SB create a DP binding for this ts-switch the user now can use the 'sync' command as following: $ ovn-ic-nbctl ts-add ts1 $ ovn-ic-nbctl --wait=sb sync The second command will wait until all the ovn-ic instances see the new changes and update their own local dbs and the global IC-SB db. v3 -> v4 * Addressed review comments from Ales to add check for the overflow cases. v2 -> v3 * Rebase over main. * Addressed review comments from Mark and Ales. Mohammad Heib (4): OVN-IC: interconnect DBs add basic Information Flow columns ovn-ic: implement basic INB change handling status OVN-IC: Make it possible for CMS to detect when the ISB is up-to-date. ic/tests: add unit test for ic sync command NEWS | 8 +++ ic/ovn-ic.c | 96 ++-- ovn-ic-nb.ovsschema | 6 ++- ovn-ic-nb.xml| 17 +++ ovn-ic-sb.ovsschema | 8 +-- ovn-ic-sb.xml| 21 tests/ovn-ic.at | 47 ++ utilities/ovn-ic-nbctl.8.xml | 49 ++ utilities/ovn-ic-nbctl.c | 89 - 9 files changed, 329 insertions(+), 12 deletions(-) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn v2 3/4] IC: Make it possible for CMS to detect when the ISB is up-to-date.
Hi Ales, Thank you for your review :) i addressed most of your comments in v3, i just have one small comment please see below: On Tue, Jan 2, 2024 at 10:13 AM Ales Musil wrote: > > > On Wed, Dec 20, 2023 at 4:28 PM Mohammad Heib wrote: > >> Until now, there has been no reliable for the CMS to detect when >> changes made to the INB configuration have been passed through >> to the ISB, This commit adds this feature to the system, >> by adding sequence numbers to the INB and ISB and adding code >> in ovn-ic-nbctl, ovn-ic to keep those sequence numbers up-to-date. >> >> The biggest user-visible change from this commit is a new option >> '--wait' and new command 'sync' to ovn-ic-nbctl. >> With --wait=sb, ovn-ic-nbctl now waits for ovn-ics to update the ISB >> database. >> >> Signed-off-by: Mohammad Heib >> > --- >> > > Hi Mohammad, > > thank you for the series, I have a few comments down below. One small nit, > the commit messages are a bit inconsistent, some patches have label IC, > some ovn-ci. I guess all of this would fall into category ovn-ic with > exception to the last patch. Also please include a cover letter for a > series that has some common theme. > > >> utilities/ovn-ic-nbctl.8.xml | 49 +++ >> utilities/ovn-ic-nbctl.c | 77 +++- >> 2 files changed, 124 insertions(+), 2 deletions(-) >> >> diff --git a/utilities/ovn-ic-nbctl.8.xml b/utilities/ovn-ic-nbctl.8.xml >> index 4a70994b8..5a1324d2d 100644 >> --- a/utilities/ovn-ic-nbctl.8.xml >> +++ b/utilities/ovn-ic-nbctl.8.xml >> @@ -123,9 +123,58 @@ >> >> >> >> +Synchronization Commands >> + >> + >> + sync >> + >> +Ordinarily, --wait=sb only waits for changes by the >> +current ovn-ic-nbctl invocation to take effect. >> +This means that, if none of the commands supplied to >> +ovn-ic-nbctl change the database, then the command >> does >> +not wait at all. With the sync command, however, >> +ovn-ic-nbctl waits even for earlier changes to the >> +database to propagate down to the southbound database, according >> to the >> +argument of --wait. >> + >> + >> + >> Options >> >> >> + --no-wait | --wait=none >> + --wait=sb >> + >> + >> + >> + These options control whether and how >> ovn-ic-nbctl waits >> + for the OVN system to become up-to-date with changes made in an >> + ovn-ic-nbctl invocation. >> + >> + >> + >> + By default, or if --no-wait or >> --wait=none, >> + ovn-ic-nbctl exits immediately after confirming >> that >> + changes have been committed to the Interconnect northbound >> database, >> + without waiting. >> + >> + >> + >> + With --wait=sb, before ovn-ic-nbctl >> exits, >> + it waits for ovn-ics to bring the Interconnect >> + southbound database up-to-date with the Interconnect northbound >> + database updates. >> + >> + >> + >> + Ordinarily, --wait=sb only waits for changes by >> the >> + current ovn-ic-nbctl invocation to take effect. >> + This means that, if none of the commands supplied to >> + ovn-ic-nbctl change the database, then the command >> + does not wait at all. >> + Use the sync command to override this behavior. >> + >> + >> --db database >> >>The OVSDB database remote to contact. If the >> OVN_IC_NB_DB >> diff --git a/utilities/ovn-ic-nbctl.c b/utilities/ovn-ic-nbctl.c >> index 721dc4586..7eca5bdc4 100644 >> --- a/utilities/ovn-ic-nbctl.c >> +++ b/utilities/ovn-ic-nbctl.c >> @@ -58,6 +58,13 @@ static bool oneline; >> /* --dry-run: Do not commit any changes. */ >> static bool dry_run; >> >> +/* --wait=TYPE: Wait for configuration change to take effect? */ >> +static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE; >> + >> +/* Should we wait (if specified by 'wait_type') even if the commands >> don't >> + * change the database at all */ >> +static bool force_wait = false; >> + >> /* --timeout: Time to wait for a connection to 'db'. */ >> static unsigned int
[ovs-dev] [PATCH ovn v3 3/4] OVN-IC: Make it possible for CMS to detect when the ISB is up-to-date.
Until now, there has been no reliable for the CMS to detect when changes made to the INB configuration have been passed through to the ISB, This commit adds this feature to the system, by adding sequence numbers to the INB and ISB and adding code in ovn-ic-nbctl, ovn-ic to keep those sequence numbers up-to-date. The biggest user-visible change from this commit is a new option '--wait' and new command 'sync' to ovn-ic-nbctl. With --wait=sb, ovn-ic-nbctl now waits for ovn-ics to update the ISB database. Signed-off-by: Mohammad Heib Acked-by: Mark Michelson Signed-off-by: Mohammad Heib --- utilities/ovn-ic-nbctl.8.xml | 49 + utilities/ovn-ic-nbctl.c | 85 +++- 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/utilities/ovn-ic-nbctl.8.xml b/utilities/ovn-ic-nbctl.8.xml index 4a70994b8..5a1324d2d 100644 --- a/utilities/ovn-ic-nbctl.8.xml +++ b/utilities/ovn-ic-nbctl.8.xml @@ -123,9 +123,58 @@ +Synchronization Commands + + + sync + +Ordinarily, --wait=sb only waits for changes by the +current ovn-ic-nbctl invocation to take effect. +This means that, if none of the commands supplied to +ovn-ic-nbctl change the database, then the command does +not wait at all. With the sync command, however, +ovn-ic-nbctl waits even for earlier changes to the +database to propagate down to the southbound database, according to the +argument of --wait. + + + Options + --no-wait | --wait=none + --wait=sb + + + + These options control whether and how ovn-ic-nbctl waits + for the OVN system to become up-to-date with changes made in an + ovn-ic-nbctl invocation. + + + + By default, or if --no-wait or --wait=none, + ovn-ic-nbctl exits immediately after confirming that + changes have been committed to the Interconnect northbound database, + without waiting. + + + + With --wait=sb, before ovn-ic-nbctl exits, + it waits for ovn-ics to bring the Interconnect + southbound database up-to-date with the Interconnect northbound + database updates. + + + + Ordinarily, --wait=sb only waits for changes by the + current ovn-ic-nbctl invocation to take effect. + This means that, if none of the commands supplied to + ovn-ic-nbctl change the database, then the command + does not wait at all. + Use the sync command to override this behavior. + + --db database The OVSDB database remote to contact. If the OVN_IC_NB_DB diff --git a/utilities/ovn-ic-nbctl.c b/utilities/ovn-ic-nbctl.c index 721dc4586..81c1ea00f 100644 --- a/utilities/ovn-ic-nbctl.c +++ b/utilities/ovn-ic-nbctl.c @@ -58,6 +58,13 @@ static bool oneline; /* --dry-run: Do not commit any changes. */ static bool dry_run; +/* --wait=TYPE: Wait for configuration change to take effect? */ +static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE; + +/* Should we wait (if specified by 'wait_type') even if the commands don't + * change the database at all */ +static bool force_wait = false; + /* --timeout: Time to wait for a connection to 'db'. */ static unsigned int timeout; @@ -161,6 +168,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) OPT_DB = UCHAR_MAX + 1, OPT_ONELINE, OPT_NO_SYSLOG, +OPT_NO_WAIT, +OPT_WAIT, OPT_DRY_RUN, OPT_LOCAL, OPT_COMMANDS, @@ -173,6 +182,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) static const struct option global_long_options[] = { {"db", required_argument, NULL, OPT_DB}, {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, +{"no-wait", no_argument, NULL, OPT_NO_WAIT}, +{"wait", required_argument, NULL, OPT_WAIT}, {"dry-run", no_argument, NULL, OPT_DRY_RUN}, {"oneline", no_argument, NULL, OPT_ONELINE}, {"timeout", required_argument, NULL, 't'}, @@ -234,7 +245,19 @@ parse_options(int argc, char *argv[], struct shash *local_options) case OPT_DRY_RUN: dry_run = true; break; - +case OPT_NO_WAIT: +wait_type = NBCTL_WAIT_NONE; +break; +case OPT_WAIT: +if (!strcmp(optarg, "none")) { +wait_type = NBCTL_WAIT_NONE; +} else if (!strcmp(optarg, "sb")) { +wait_type = NBCTL_WAIT_SB; +} else { +ctl_fatal("argument to --wait must be " + "\"none\", \"sb\" "); +} +
[ovs-dev] [PATCH ovn v3 1/4] OVN-IC: interconnect DBs add basic Information Flow columns
Add basic flow columns to interconnect northbound DB and interconnect Southbound DB. Those columns will be used by future patches to add basic support for Information Flow in OVN interconnect. Signed-off-by: Mohammad Heib Acked-by: Mark Michelson Acked-by: Ales Musil --- NEWS| 8 ovn-ic-nb.ovsschema | 6 -- ovn-ic-nb.xml | 17 + ovn-ic-sb.ovsschema | 8 +--- ovn-ic-sb.xml | 21 + 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 20df92cb7..23609957c 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,14 @@ Post v23.09.0 - Support CIDR based MAC binding aging threshold. See ovn-nb(5) for 'mac_binding_age_threshold' for more details. - ovn-northd-ddlog has been removed. + - OVN Interconnection: +* INB provides basic feedback to the CMS about the ISB changes + handling status. +* IC_NB_Global now have "nb_ic_cfg" and "sb_ic_cfg" columns for + for ISB informational status. +* IC_SB_Global now have "nb_ic_cfg" column for ISB informational status. +* Availability_Zone now have "nb_ic_cfg" column for local AZ + informational status. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/ovn-ic-nb.ovsschema b/ovn-ic-nb.ovsschema index 894db8344..bee174357 100644 --- a/ovn-ic-nb.ovsschema +++ b/ovn-ic-nb.ovsschema @@ -1,10 +1,12 @@ { "name": "OVN_IC_Northbound", -"version": "1.0.0", -"cksum": "45589876 3383", +"version": "1.1.0", +"cksum": "3964083684 3501", "tables": { "IC_NB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, +"sb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, diff --git a/ovn-ic-nb.xml b/ovn-ic-nb.xml index 8c53bec3b..2ae9bf6d5 100644 --- a/ovn-ic-nb.xml +++ b/ovn-ic-nb.xml @@ -36,6 +36,23 @@ one row. + + These columns allow a client to track the overall configuration state of + the system. + + +Sequence number for client to increment. When a client modifies the +interconnect northbound database configuration and wishes to wait for +OVN-ICs to handle this change and update the Interconnect +southbound database, it may increment this sequence number. + + +Sequence number that one OVN-IC sets to the value of + after waiting to all the OVN-ICs +finish applying their changes to interconnect southbound database. + + + See External IDs at the beginning of this document. diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema index 1d60b36d1..5baf141cf 100644 --- a/ovn-ic-sb.ovsschema +++ b/ovn-ic-sb.ovsschema @@ -1,10 +1,11 @@ { "name": "OVN_IC_Southbound", -"version": "1.1.1", -"cksum": "3684563024 6914", +"version": "1.2.0", +"cksum": "1381014956 7032", "tables": { "IC_SB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, @@ -24,7 +25,8 @@ "isRoot": true}, "Availability_Zone": { "columns": { -"name": {"type": "string"}}, +"name": {"type": "string"}, +"nb_ic_cfg": {"type": {"key": "integer"}}}, "isRoot": true, "indexes": [["name"]]}, "Gateway": { diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml index f7e17e113..c3e7d2173 100644 --- a/ovn-ic-sb.xml +++ b/ovn-ic-sb.xml @@ -69,6 +69,21 @@ one row. + + This column allow a client to track the overall configuration state of + the system. + + +Sequence number for the configuration. When a CMS or +ovn-ic-nbctl updates the Interconnect northbound database, +it increments the nb_ic_cfg column in the +NB_IC_Global table in the Interconnect northbound +database. when OVN-ICs updates the southbound database to +bring it up to date with these changes, one OVN-IC updates +this column to the same value. + + + See External IDs at the beginning of this document. @@ -102,6 +117,12 @@ A name that uniquely identifies the availability zone. + + + This column is used by the OVN-IC to inform + that this IC instance is aligned with the changes in INB + + -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v3 2/4] ovn-ic: implement basic INB change handling status
This patch implements a basic sequence number protocol that can be used by CMS to determine if the changes applied to INB are successfully propagated to ISB. The implementation of this patch relies on OVN-ICs instances to update the ISB by adding a per AZ a nb_ic_cfg counter that will be updated by the OVN-IC once it is done and commit all needed changes to the ISB, and according to this AZ:nb_ic_cfg the ISB and INB will be updating about the status of the changes. Signed-off-by: Mohammad Heib --- ic/ovn-ic.c | 96 ++--- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 8ceb34d7c..ba393e910 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -1782,16 +1782,96 @@ route_run(struct ic_context *ctx, hmap_destroy(&ic_lrs); } +/* + * This function implements a sequence number protocol that can be used by + * the INB end user to verify that ISB is synced with all the changes that + * are done be the user/AZs-controllers: + * + * Since we have multiple IC instances running in different regions + * we can't rely on one of them to update the ISB and sync that update + * to INB since other ICs can make changes in parallel. + * So to have a sequence number protocol working properly we must + * make sure that all the IC instances are synced with the ISB first + * and then update the INB. + * + * To guarantee that all instances are synced with ISB first, each IC + * will do the following steps: + * + * 1. when local ovn-ic sees that INB:nb_ic_cfg has updated we will set + *the ic_sb_loop->next_cfg to match the INB:nb_ic_cfg and increment + *the value of AZ:nb_ic_cfg and wait until we get confirmation from + *the server. + * + * 2. once this IC instance changes for ISB are committed successfully + *(next loop), the value of cur_cfg will be updated to match + *the INB:nb_ic_cfg that indicate that our local instance is up to date + *and no more changes need to be done for ISB. + * + * 3. validate that the AZ:nb_ic_cfg to match the INB:nb_ic_cfg. + * + * 4. Go through all the AZs and check if all have the same value of + *AZ:nb_ic_cfg that means all the AZs are done with ISB changes and ISB are + *up to date with INB, so we can set the values of ISB:nb_ic_cfg to + *INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg. + */ static void -ovn_db_run(struct ic_context *ctx) +update_sequence_numbers(const struct icsbrec_availability_zone *az, +struct ic_context *ctx, +struct ovsdb_idl_loop *ic_sb_loop) { -const struct icsbrec_availability_zone *az = az_run(ctx); -VLOG_DBG("Availability zone: %s", az ? az->name : "not created yet."); +bool azs_cfg_equals = true; +if (!ctx->ovnisb_txn || !ctx->ovninb_txn) { +return; +} -if (!az) { +const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first( + ctx->ovninb_idl); +if (!ic_nb) { +ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn); +} +const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first( + ctx->ovnisb_idl); +if (!ic_sb) { +ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn); +} + +if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) && + (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) { +/* Deal with potential overflows. */ +if (az->nb_ic_cfg == LLONG_MAX) { +icsbrec_availability_zone_set_nb_ic_cfg(az, 0); +} +ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg; +ovsdb_idl_txn_increment(ctx->ovnisb_txn, &az->header_, + &icsbrec_availability_zone_col_nb_ic_cfg, true); return; } +/* handle cases where accidentally AZ:ic_nb_cfg exceeds + * the INB:ic_nb_cfg. + */ +if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) { +icsbrec_availability_zone_set_nb_ic_cfg(az, ic_sb_loop->cur_cfg); +return; +} + +const struct icsbrec_availability_zone *other_az; +ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) { +if (other_az->nb_ic_cfg != az->nb_ic_cfg) { +azs_cfg_equals = false; +} +} + +if (azs_cfg_equals && (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg)) { +icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg); +icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg); +} +} + +static void +ovn_db_run(struct ic_context *ctx, + const struct icsbrec_availability_zone *az) +{ ts_run(ctx); gateway_run(ctx, az); port_binding_run(ctx, az); @@ -2218,7 +2298,13 @@ main(int argc, char *argv[]) ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) && ovs
[ovs-dev] [PATCH ovn v3 4/4] ic/tests: add unit test for ic sync command
add unit test that check validate that sync command sync ISB properly Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 47 +++ 1 file changed, 47 insertions(+) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index d4c436f84..f55ffa6cd 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -1274,3 +1274,50 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) + +AT_SETUP([ovn-ic -- sync ISB status to INB]) +ovn_init_ic_db +net_add n1 + +ovn_start az1 +sim_add gw-az1 +as gw-az1 + +check ovs-vsctl add-br br-phys +ovn_az_attach az1 n1 br-phys 192.168.1.1 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true +as az1 + +# pause ovn-ic instance +check ovn-appctl -t ic/ovn-ic pause + +# run sync command in the background this commands +# supposed to stuck since ovn-ic is paused. +$(ovn-ic-nbctl --wait=sb sync &) + +for i in {1..5}; do +set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) +AS_VAR_SET([ic_nb_cfg], [$1]) +AS_VAR_SET([ic_sb_cfg], [$2]) +if test $ic_nb_cfg -gt $ic_sb_cfg; then +sleep 1 +else +break +fi +done + +# if ic_nb_cfg equal to ic_sb_cfg that mean both zero +# or both 1 which is a not correct and the test must fail. +AT_FAIL_IF([test $ic_nb_cfg == $ic_sb_cfg]) + +# resume ovn-ic instance +check ovn-appctl -t ic/ovn-ic resume +set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) +AS_VAR_SET([ic_nb_cfg], [$1]) +AS_VAR_SET([ic_sb_cfg], [$2]) +AT_FAIL_IF([test $ic_nb_cfg != 1]) +AT_FAIL_IF([test $ic_nb_cfg != 1]) + +OVN_CLEANUP_IC([az1]) +AT_CLEANUP +]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v3 0/4] OVN-IC: add basic sequence number status support
Currently, OVN-IC doesn't support a way to tell the end-user when their changes to the IC-NB database have propagated successfully to the IC-SB Database. This patch series adds basic support for the sequence number status protocol that is implemented on the native OVN, with this patch series the end user now can wait for their changes in the IC-NB DB to take effect by executing the 'sync' command after applying any changes to the IC-NB DB, for example, if the end-user has created a transit switch in the IC-NB global DB and want to make sure that the IC-SB create a DP binding for this ts-switch the user now can use the 'sync' command as following: $ ovn-ic-nbctl ts-add ts1 $ ovn-ic-nbctl --wait=sb sync The second command will wait until all the ovn-ic instances see the new changes and update their own local dbs and the global IC-SB db. v2 -> v3 * Rebase over main. * Addressed review comments from Mark and Ales. Mohammad Heib (4): OVN-IC: interconnect DBs add basic Information Flow columns ovn-ic: implement basic INB change handling status OVN-IC: Make it possible for CMS to detect when the ISB is up-to-date. ic/tests: add unit test for ic sync command NEWS | 8 +++ ic/ovn-ic.c | 96 ++-- ovn-ic-nb.ovsschema | 6 ++- ovn-ic-nb.xml| 17 +++ ovn-ic-sb.ovsschema | 8 +-- ovn-ic-sb.xml| 21 tests/ovn-ic.at | 47 ++ utilities/ovn-ic-nbctl.8.xml | 49 ++ utilities/ovn-ic-nbctl.c | 85 ++- 9 files changed, 325 insertions(+), 12 deletions(-) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH v6 1/2] mcast-snooping: Store IGMP/MLD protocol version.
Hi Simon, Thank you for the review :) On Thu, Jan 4, 2024 at 1:27 PM Simon Horman wrote: > On Wed, Dec 27, 2023 at 01:15:22PM +0200, Mohammad Heib wrote: > > Store igmp/mld protocol version into the > > mcast_group internally, the multicast snooping feature > > is used by many OVS consumers and those consumers heavily rely > > on the OVS implementation to manage/deal with mcast groups, > > some of those consumers also need to deal/expose the mcast protocol > > to the end user for debuggability purposes. > > > > OVN for example needs to expose the protocol version to the end user > > to match between the protocol version used in the OVN logical switches > > and the uplink ports > > > > Therefore, instead of implementing this in each OVS consumer that needs > > to deal mcast group protocol version which will be very complicated > > implementation since it rely on the OVS code, saving the protocol to > > the mdb inside OVS will give that consumer access to the protocol version > > very easily. > > > > Signed-off-by: Mohammad Heib > > --- > > v6: Rebase on top of current master. > > Address comments from Eelco: > > - hardcode MCAST_GROUP_IGMPV3 inside mcast_snooping_add_report > > function. > > --- > > lib/mcast-snooping.c | 20 ++-- > > lib/mcast-snooping.h | 18 -- > > ofproto/ofproto-dpif-xlate.c | 7 ++- > > 3 files changed, 36 insertions(+), 9 deletions(-) > > > > diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c > > index 43805ae4d..995216a4b 100644 > > --- a/lib/mcast-snooping.c > > +++ b/lib/mcast-snooping.c > > @@ -389,7 +389,8 @@ mcast_snooping_prune_expired(struct mcast_snooping > *ms, > > bool > > mcast_snooping_add_group(struct mcast_snooping *ms, > > const struct in6_addr *addr, > > - uint16_t vlan, void *port) > > + uint16_t vlan, void *port, > > + mcast_group_proto grp_proto) > > OVS_REQ_WRLOCK(ms->rwlock) > > { > > bool learned; > > @@ -424,6 +425,9 @@ mcast_snooping_add_group(struct mcast_snooping *ms, > > } > > mcast_group_insert_bundle(ms, grp, port, ms->idle_time); > > Hi Mohammad, > > the code leading up to this hunk looks a bit like this: > > grp = mcast_snooping_lookup(ms, addr, vlan); > if (!grp) { > /* Create grp */ > } else { > ovs_list_remove(&grp->group_node); > } > mcast_group_insert_bundle(ms, grp, port, ms->idle_time); > > In v4 of the patchset grp->protocol_version was set inside the > (!grp) arm of the if condition. But now it is set below. > > Is this intentional? If so, I have a few questions: > yes, i updated the code to cover cases where a new port that uses a different igmp/mld version will be added to this group. > > 1. Is it ok to set grp->protocol_version after the >mcast_group_insert_bundle() call? > yes, That will update the group version to match the protocol version used by the latest added port, that will not have any effect because we only use the protocol version for debuggability/user-inform and not used in the code at all. 2. Is it ok to reset grp->protocol_version for an existing grp? > actually, in v5 I was setting the protocol version for newly created grps only, but based on feedback on v5 for Eelco Chaudron <https://patchwork.ozlabs.org/project/openvswitch/list/?submitter=70613> [v5] <https://patchwork.ozlabs.org/project/openvswitch/patch/20231130153821.855531-2-mh...@redhat.com/> i updated the code to store the latest protocol used to join this group which will be more accurate in the DB. 3. Are there situations where 2 will change the value of >grp->protocol_version? > only if the user uses two different ports each one using a different igmp/mld version to join the same mcast group, this is an infrequent scenario but it will be better to use the latest join port protocol version. > > > > > +/* update the protocol version. */ > > +grp->protocol_version = grp_proto; > > + > > /* Mark 'grp' as recently used. */ > > ovs_list_push_back(&ms->group_lru, &grp->group_node); > > return learned; > > ... > > Thanks, > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH v6 2/2] mcast-snooping: Add group protocol to mdb/show output.
Expose the mcast group protocol via the mdb/show command output. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c| 24 lib/mcast-snooping.h| 1 + ofproto/ofproto-dpif.c | 9 ++- tests/mcast-snooping.at | 130 tests/stp.at| 6 +- 5 files changed, 139 insertions(+), 31 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 995216a4b..60ef8381e 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -57,6 +57,30 @@ mcast_snooping_flood_unreg(const struct mcast_snooping *ms) return ms->flood_unreg; } +char * +mcast_snooping_group_protocol_str(mcast_group_proto grp_proto) +{ +switch (grp_proto) { +case MCAST_GROUP_IGMPV1: +return "IGMPv1"; +break; +case MCAST_GROUP_IGMPV2: +return "IGMPv2"; +break; +case MCAST_GROUP_IGMPV3: +return "IGMPv3"; +break; +case MCAST_GROUP_MLDV1: +return "MLDv1"; +break; +case MCAST_GROUP_MLDV2: +return "MLDv2"; +break; +default: +return "UNKNOWN"; +} +} + bool mcast_snooping_is_query(ovs_be16 igmp_type) { diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index 8cc8fb0fb..acd9fdb68 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -224,6 +224,7 @@ bool mcast_snooping_add_mrouter(struct mcast_snooping *ms, uint16_t vlan, OVS_REQ_WRLOCK(ms->rwlock); bool mcast_snooping_is_query(ovs_be16 igmp_type); bool mcast_snooping_is_membership(ovs_be16 igmp_type); +char * mcast_snooping_group_protocol_str(mcast_group_proto grp_proto); /* Flush. */ void mcast_snooping_mdb_flush(struct mcast_snooping *ms); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 6e62ed1f9..434ea1670 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -6172,7 +6172,7 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, return; } -ds_put_cstr(&ds, " port VLAN GROUPAge\n"); +ds_put_cstr(&ds, " port VLAN protocol GROUPAge\n"); ovs_rwlock_rdlock(&ofproto->ms->rwlock); LIST_FOR_EACH (grp, group_node, &ofproto->ms->group_lru) { LIST_FOR_EACH(b, bundle_node, &grp->bundle_lru) { @@ -6181,7 +6181,9 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, bundle = b->port; ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port, NULL, name, sizeof name); -ds_put_format(&ds, "%5s %4d ", name, grp->vlan); +ds_put_format(&ds, "%5s %4d %8s ", name, grp->vlan, + mcast_snooping_group_protocol_str( + grp->protocol_version)); ipv6_format_mapped(&grp->addr, &ds); ds_put_format(&ds, " %3d\n", mcast_bundle_age(ofproto->ms, b)); @@ -6195,8 +6197,9 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, bundle = mrouter->port; ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port, NULL, name, sizeof name); -ds_put_format(&ds, "%5s %4d querier %3d\n", +ds_put_format(&ds, "%5s %4d %8s querier %3d\n", name, mrouter->vlan, + mcast_snooping_group_protocol_str(-1), mcast_mrouter_age(ofproto->ms, mrouter)); } ovs_rwlock_unlock(&ofproto->ms->rwlock); diff --git a/tests/mcast-snooping.at b/tests/mcast-snooping.at index 890e6aca0..800a77504 100644 --- a/tests/mcast-snooping.at +++ b/tests/mcast-snooping.at @@ -44,9 +44,9 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ '01005e015c8a38552552810006c0080046c0002401027c00ac111c01e00194041164ec1e027d']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge -2 1725 querier 0 -2 1728 querier 0 + port VLAN protocol GROUPAge +2 1725 UNKNOWN querier 0 +2 1728 UNKNOWN querier 0 ]) AT_CHECK([ovs-vsctl set Interface p2 options:tx_pcap=p2.pcap]) @@ -75,7 +75,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ '01005e015c8a38552552810006bd080046c0002401027f00ac111901e00194041164ec10027d']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN protocol GROUPAge ]) @@ -87,8 +87,8 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ 'ff0e4
[ovs-dev] [PATCH v6 1/2] mcast-snooping: Store IGMP/MLD protocol version.
Store igmp/mld protocol version into the mcast_group internally, the multicast snooping feature is used by many OVS consumers and those consumers heavily rely on the OVS implementation to manage/deal with mcast groups, some of those consumers also need to deal/expose the mcast protocol to the end user for debuggability purposes. OVN for example needs to expose the protocol version to the end user to match between the protocol version used in the OVN logical switches and the uplink ports Therefore, instead of implementing this in each OVS consumer that needs to deal mcast group protocol version which will be very complicated implementation since it rely on the OVS code, saving the protocol to the mdb inside OVS will give that consumer access to the protocol version very easily. Signed-off-by: Mohammad Heib --- v6: Rebase on top of current master. Address comments from Eelco: - hardcode MCAST_GROUP_IGMPV3 inside mcast_snooping_add_report function. --- lib/mcast-snooping.c | 20 ++-- lib/mcast-snooping.h | 18 -- ofproto/ofproto-dpif-xlate.c | 7 ++- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 43805ae4d..995216a4b 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -389,7 +389,8 @@ mcast_snooping_prune_expired(struct mcast_snooping *ms, bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { bool learned; @@ -424,6 +425,9 @@ mcast_snooping_add_group(struct mcast_snooping *ms, } mcast_group_insert_bundle(ms, grp, port, ms->idle_time); +/* update the protocol version. */ +grp->protocol_version = grp_proto; + /* Mark 'grp' as recently used. */ ovs_list_push_back(&ms->group_lru, &grp->group_node); return learned; @@ -431,11 +435,12 @@ mcast_snooping_add_group(struct mcast_snooping *ms, bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { struct in6_addr addr = in6_addr_mapped_ipv4(ip4); -return mcast_snooping_add_group(ms, &addr, vlan, port); +return mcast_snooping_add_group(ms, &addr, vlan, port, grp_proto); } int @@ -478,7 +483,8 @@ mcast_snooping_add_report(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group4(ms, ip4, vlan, port); } else { -ret = mcast_snooping_add_group4(ms, ip4, vlan, port); +ret = mcast_snooping_add_group4(ms, ip4, vlan, port, +MCAST_GROUP_IGMPV3); } if (ret) { count++; @@ -513,7 +519,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, switch (mld->type) { case MLD_REPORT: -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MCAST_GROUP_MLDV1); if (ret) { count++; } @@ -545,7 +552,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group(ms, addr, vlan, port); } else { -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MCAST_GROUP_MLDV2); } if (ret) { count++; diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f120405da..8cc8fb0fb 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -39,6 +39,15 @@ struct mcast_snooping; /* Time, in seconds, before expiring a mrouter_port due to inactivity. */ #define MCAST_MROUTER_PORT_IDLE_TIME 180 +/* Multicast group protocol. */ +typedef enum { +MCAST_GROUP_IGMPV1 = 0, +MCAST_GROUP_IGMPV2, +MCAST_GROUP_IGMPV3, +MCAST_GROUP_MLDV1, +MCAST_GROUP_MLDV2, +} mcast_group_proto; + /* Multicast group entry. * Guarded by owning 'mcast_snooping''s rwlock. */ struct mcast_group { @@ -51,6 +60,9 @@ struct mcast_group { /* VLAN tag. */ uint16_t vlan; +/* Multicast group IPv6/IPv4 Protocol version IGMPv1,2,3 or MLDv1,2 */ +mcast_group_proto protocol_version; + /* Node in parent struct mcast_snooping group_lru. */ struct ovs_list group_node OVS_
[ovs-dev] [PATCH ovn v2 4/4] ic/tests: add unit test for ic sync command
add unit test that check validate that sync command sync ISB properly Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 22 ++ 1 file changed, 22 insertions(+) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index d4c436f84..da7c37817 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -1274,3 +1274,25 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) + +AT_SETUP([ovn-ic -- sync ISB status to INB]) +ovn_init_ic_db +net_add n1 + +ovn_start az1 +sim_add gw-az1 +as gw-az1 + +check ovs-vsctl add-br br-phys +ovn_az_attach az1 n1 br-phys 192.168.1.1 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true + +ovn-ic-nbctl --wait=sb sync +set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) +AS_VAR_SET([ic_nb_cfg], [$1]) +AS_VAR_SET([ic_sb_cfg], [$2]) +check test $ic_nb_cfg == $ic_sb_cfg + +OVN_CLEANUP_IC([az1]) +AT_CLEANUP +]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v2 3/4] IC: Make it possible for CMS to detect when the ISB is up-to-date.
Until now, there has been no reliable for the CMS to detect when changes made to the INB configuration have been passed through to the ISB, This commit adds this feature to the system, by adding sequence numbers to the INB and ISB and adding code in ovn-ic-nbctl, ovn-ic to keep those sequence numbers up-to-date. The biggest user-visible change from this commit is a new option '--wait' and new command 'sync' to ovn-ic-nbctl. With --wait=sb, ovn-ic-nbctl now waits for ovn-ics to update the ISB database. Signed-off-by: Mohammad Heib --- utilities/ovn-ic-nbctl.8.xml | 49 +++ utilities/ovn-ic-nbctl.c | 77 +++- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/utilities/ovn-ic-nbctl.8.xml b/utilities/ovn-ic-nbctl.8.xml index 4a70994b8..5a1324d2d 100644 --- a/utilities/ovn-ic-nbctl.8.xml +++ b/utilities/ovn-ic-nbctl.8.xml @@ -123,9 +123,58 @@ +Synchronization Commands + + + sync + +Ordinarily, --wait=sb only waits for changes by the +current ovn-ic-nbctl invocation to take effect. +This means that, if none of the commands supplied to +ovn-ic-nbctl change the database, then the command does +not wait at all. With the sync command, however, +ovn-ic-nbctl waits even for earlier changes to the +database to propagate down to the southbound database, according to the +argument of --wait. + + + Options + --no-wait | --wait=none + --wait=sb + + + + These options control whether and how ovn-ic-nbctl waits + for the OVN system to become up-to-date with changes made in an + ovn-ic-nbctl invocation. + + + + By default, or if --no-wait or --wait=none, + ovn-ic-nbctl exits immediately after confirming that + changes have been committed to the Interconnect northbound database, + without waiting. + + + + With --wait=sb, before ovn-ic-nbctl exits, + it waits for ovn-ics to bring the Interconnect + southbound database up-to-date with the Interconnect northbound + database updates. + + + + Ordinarily, --wait=sb only waits for changes by the + current ovn-ic-nbctl invocation to take effect. + This means that, if none of the commands supplied to + ovn-ic-nbctl change the database, then the command + does not wait at all. + Use the sync command to override this behavior. + + --db database The OVSDB database remote to contact. If the OVN_IC_NB_DB diff --git a/utilities/ovn-ic-nbctl.c b/utilities/ovn-ic-nbctl.c index 721dc4586..7eca5bdc4 100644 --- a/utilities/ovn-ic-nbctl.c +++ b/utilities/ovn-ic-nbctl.c @@ -58,6 +58,13 @@ static bool oneline; /* --dry-run: Do not commit any changes. */ static bool dry_run; +/* --wait=TYPE: Wait for configuration change to take effect? */ +static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE; + +/* Should we wait (if specified by 'wait_type') even if the commands don't + * change the database at all */ +static bool force_wait = false; + /* --timeout: Time to wait for a connection to 'db'. */ static unsigned int timeout; @@ -161,6 +168,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) OPT_DB = UCHAR_MAX + 1, OPT_ONELINE, OPT_NO_SYSLOG, +OPT_NO_WAIT, +OPT_WAIT, OPT_DRY_RUN, OPT_LOCAL, OPT_COMMANDS, @@ -173,6 +182,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) static const struct option global_long_options[] = { {"db", required_argument, NULL, OPT_DB}, {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, +{"no-wait", no_argument, NULL, OPT_NO_WAIT}, +{"wait", required_argument, NULL, OPT_WAIT}, {"dry-run", no_argument, NULL, OPT_DRY_RUN}, {"oneline", no_argument, NULL, OPT_ONELINE}, {"timeout", required_argument, NULL, 't'}, @@ -234,7 +245,19 @@ parse_options(int argc, char *argv[], struct shash *local_options) case OPT_DRY_RUN: dry_run = true; break; - +case OPT_NO_WAIT: +wait_type = NBCTL_WAIT_NONE; +break; +case OPT_WAIT: +if (!strcmp(optarg, "none")) { +wait_type = NBCTL_WAIT_NONE; +} else if (!strcmp(optarg, "sb")) { +wait_type = NBCTL_WAIT_SB; +} else { +ctl_fatal("argument to --wait must be " + "\"none\", \"sb\" "); +} +break; case OPT_LOCAL:
[ovs-dev] [PATCH ovn v2 2/4] ovn-ic: implement basic INB change handling status
This patch implements a basic sequence number protocol that can be used by CMS to determine if the changes applied to INB are successfully propagated to ISB. The implementation of this patch relies on OVN-ICs instances to update the ISB by adding a per AZ a nb_ic_cfg counter that will be updated by the OVN-IC once it is done and commit all needed changes to the ISB, and according to this AZ:nb_ic_cfg the ISB and INB will be updating about the status of the changes. Signed-off-by: Mohammad Heib --- ic/ovn-ic.c | 98 + 1 file changed, 92 insertions(+), 6 deletions(-) diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 8ceb34d7c..b6a813432 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -1782,16 +1782,96 @@ route_run(struct ic_context *ctx, hmap_destroy(&ic_lrs); } +/* + * This function implements a sequence number protocol that can be used by + * the INB end user to verify that ISB is synced with all the changes that + * are done be the user/AZs-controllers: + * + * Since we have multiple IC instances running in different regions + * we can't rely on one of them to update the ISB and sync that update + * to INB since other ICs can make changes in parallel. + * So to have a sequence number protocol working properly we must + * make sure that all the IC instances are synced with the ISB first + * and then update the INB. + * + * To guarantee that all instances are synced with ISB first, each IC + * will do the following steps: + * + * 1. when local ovn-ic sees that INB:nb_ic_cfg has updated we will set + *the ic_sb_loop->next_cfg to match the INB:nb_ic_cfg and increment + *the value of AZ:nb_ic_cfg and wait until we get confirmation from + *the server. + * + * 2. once this IC instance changes for ISB are committed successfully + *(next loop), the value of cur_cfg will be updated to match + *the INB:nb_ic_cfg that indicate that our local instance is up to date + *and no more changes need to be done for ISB. + * + * 3. validate that the AZ:nb_ic_cfg to match the INB:nb_ic_cfg. + * + * 4. Go through all the AZs and check if all have the same value of + *AZ:nb_ic_cfg that means all the AZs are done with ISB changes and ISB are + *up to date with INB, so we can set the values of ISB:nb_ic_cfg to + *INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg. + */ static void -ovn_db_run(struct ic_context *ctx) +update_sequence_numbers(const struct icsbrec_availability_zone *az, +struct ic_context *ctx, +struct ovsdb_idl_loop *ic_sb_loop) { -const struct icsbrec_availability_zone *az = az_run(ctx); -VLOG_DBG("Availability zone: %s", az ? az->name : "not created yet."); +bool azs_cfg_equals = true; -if (!az) { -return; +if (ctx->ovnisb_txn && ctx->ovninb_txn) { +const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first( + ctx->ovninb_idl); +if (!ic_nb) { +ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn); +} +const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first( + ctx->ovnisb_idl); +if (!ic_sb) { +ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn); +} + +if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) && + (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) { +/* Deal with potential overflows. */ +if (az->nb_ic_cfg == LLONG_MAX) { +icsbrec_availability_zone_set_nb_ic_cfg(az, 0); +} +ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg; +ovsdb_idl_txn_increment(ctx->ovnisb_txn, &az->header_, + &icsbrec_availability_zone_col_nb_ic_cfg, true); +goto done; +} + +/* handle cases where accidentally AZ:ic_nb_cfg exceeds + * the INB:ic_nb_cfg. + */ +if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) { +icsbrec_availability_zone_set_nb_ic_cfg(az, ic_sb_loop->cur_cfg); +goto done; +} + +const struct icsbrec_availability_zone *other_az; +ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) { +if (other_az->nb_ic_cfg != az->nb_ic_cfg) { +azs_cfg_equals = false; +} +} + +if (azs_cfg_equals && (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg)) { +icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg); +icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg); +} } +done: ; +} +static void +ovn_db_run(struct ic_context *ctx, + const struct icsbrec_availability_zone *az) +{ ts_run(ctx); gateway_run(ctx, az);
[ovs-dev] [PATCH ovn v2 1/4] IC: interconnect DBs add basic Information Flow columns
Add basic flow columns to interconnect northbound DB and interconnect Southbound DB. Those columns will be used by future patches to add basic support for Information Flow in OVN interconnect. Signed-off-by: Mohammad Heib --- v3: rebase over main. --- NEWS| 8 ovn-ic-nb.ovsschema | 6 -- ovn-ic-nb.xml | 17 + ovn-ic-sb.ovsschema | 8 +--- ovn-ic-sb.xml | 21 + 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index e10fb79dd..0be3b07cc 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,14 @@ Post v23.09.0 connection method and doesn't require additional probing. external_ids:ovn-openflow-probe-interval configuration option for ovn-controller no longer matters and is ignored. + - OVN Interconnection: +* INB provides basic feedback to the CMS about the ISB changes + handling status. +* IC_NB_Global now have "nb_ic_cfg" and "sb_ic_cfg" columns for + for ISB informational status. +* IC_SB_Global now have "nb_ic_cfg" column for ISB informational status. +* Availability_Zone now have "nb_ic_cfg" column for local AZ + informational status. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/ovn-ic-nb.ovsschema b/ovn-ic-nb.ovsschema index 894db8344..bee174357 100644 --- a/ovn-ic-nb.ovsschema +++ b/ovn-ic-nb.ovsschema @@ -1,10 +1,12 @@ { "name": "OVN_IC_Northbound", -"version": "1.0.0", -"cksum": "45589876 3383", +"version": "1.1.0", +"cksum": "3964083684 3501", "tables": { "IC_NB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, +"sb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, diff --git a/ovn-ic-nb.xml b/ovn-ic-nb.xml index 8c53bec3b..2ae9bf6d5 100644 --- a/ovn-ic-nb.xml +++ b/ovn-ic-nb.xml @@ -36,6 +36,23 @@ one row. + + These columns allow a client to track the overall configuration state of + the system. + + +Sequence number for client to increment. When a client modifies the +interconnect northbound database configuration and wishes to wait for +OVN-ICs to handle this change and update the Interconnect +southbound database, it may increment this sequence number. + + +Sequence number that one OVN-IC sets to the value of + after waiting to all the OVN-ICs +finish applying their changes to interconnect southbound database. + + + See External IDs at the beginning of this document. diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema index 1d60b36d1..5baf141cf 100644 --- a/ovn-ic-sb.ovsschema +++ b/ovn-ic-sb.ovsschema @@ -1,10 +1,11 @@ { "name": "OVN_IC_Southbound", -"version": "1.1.1", -"cksum": "3684563024 6914", +"version": "1.2.0", +"cksum": "1381014956 7032", "tables": { "IC_SB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, @@ -24,7 +25,8 @@ "isRoot": true}, "Availability_Zone": { "columns": { -"name": {"type": "string"}}, +"name": {"type": "string"}, +"nb_ic_cfg": {"type": {"key": "integer"}}}, "isRoot": true, "indexes": [["name"]]}, "Gateway": { diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml index f7e17e113..c3e7d2173 100644 --- a/ovn-ic-sb.xml +++ b/ovn-ic-sb.xml @@ -69,6 +69,21 @@ one row. + + This column allow a client to track the overall configuration state of + the system. + + +Sequence number for the configuration. When a CMS or +ovn-ic-nbctl updates the Interconnect northbound database, +it increments the nb_ic_cfg column in the +NB_IC_Global table in the Interconnect northbound +database. when OVN-ICs updates the southbound database to +bring it up to date with these changes, one OVN-IC updates +this column to the same value. + + + See External IDs at the beginning of this document. @@ -102,6 +117,12 @@ A name that uniquely identifies the availability zone. + + + This column is used by the OVN-IC to inform + that this IC instance is aligned with the changes in INB + + -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn 3/4] IC: Make it possible for CMS to detect when the ISB is up-to-date.
Until now, there has been no reliable for the CMS to detect when changes made to the INB configuration have been passed through to the ISB, This commit adds this feature to the system, by adding sequence numbers to the INB and ISB and adding code in ovn-ic-nbctl, ovn-ic to keep those sequence numbers up-to-date. The biggest user-visible change from this commit is a new option '--wait' and new command 'sync' to ovn-ic-nbctl. With --wait=sb, ovn-ic-nbctl now waits for ovn-ics to update the ISB database. Signed-off-by: Mohammad Heib --- utilities/ovn-ic-nbctl.8.xml | 46 ++ utilities/ovn-ic-nbctl.c | 76 +++- 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/utilities/ovn-ic-nbctl.8.xml b/utilities/ovn-ic-nbctl.8.xml index 4a70994b8..ccfacfaff 100644 --- a/utilities/ovn-ic-nbctl.8.xml +++ b/utilities/ovn-ic-nbctl.8.xml @@ -123,9 +123,55 @@ +Synchronization Commands + + + sync + +Ordinarily, --wait=sb only waits for changes by the current +ovn-ic-nbctl invocation to take effect. +This means that, if none of the commands supplied to +ovn-ic-nbctl change the database, then the command does not +wait at all. With the sync command, however, +ovn-ic-nbctl waits even for earlier changes to the database +to propagate down to the southbound database, according to the argument of --wait. + + + Options + --no-wait | --wait=none + --wait=sb + + + + These options control whether and how ovn-ic-nbctl waits + for the OVN system to become up-to-date with changes made in an + ovn-ic-nbctl invocation. + + + + By default, or if --no-wait or --wait=none, + ovn-ic-nbctl exits immediately after confirming that + changes have been committed to the Interconnect northbound database, + without waiting. + + + + With --wait=sb, before ovn-ic-nbctl exits, it + waits for ovn-ics to bring the Interconnect southbound database + up-to-date with the Interconnect northbound database updates. + + + + Ordinarily, --wait=sb only waits for changes by the current + ovn-ic-nbctl invocation to take effect. + This means that, if none of the commands supplied to ovn-ic-nbctl + change the database, then the command does not wait at all. + Use the sync command to override this behavior. + + --db database The OVSDB database remote to contact. If the OVN_IC_NB_DB diff --git a/utilities/ovn-ic-nbctl.c b/utilities/ovn-ic-nbctl.c index 721dc4586..2061b0c67 100644 --- a/utilities/ovn-ic-nbctl.c +++ b/utilities/ovn-ic-nbctl.c @@ -58,6 +58,13 @@ static bool oneline; /* --dry-run: Do not commit any changes. */ static bool dry_run; +/* --wait=TYPE: Wait for configuration change to take effect? */ +static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE; + +/* Should we wait (if specified by 'wait_type') even if the commands don't + * change the database at all */ +static bool force_wait = false; + /* --timeout: Time to wait for a connection to 'db'. */ static unsigned int timeout; @@ -161,6 +168,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) OPT_DB = UCHAR_MAX + 1, OPT_ONELINE, OPT_NO_SYSLOG, +OPT_NO_WAIT, +OPT_WAIT, OPT_DRY_RUN, OPT_LOCAL, OPT_COMMANDS, @@ -173,6 +182,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) static const struct option global_long_options[] = { {"db", required_argument, NULL, OPT_DB}, {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG}, +{"no-wait", no_argument, NULL, OPT_NO_WAIT}, +{"wait", required_argument, NULL, OPT_WAIT}, {"dry-run", no_argument, NULL, OPT_DRY_RUN}, {"oneline", no_argument, NULL, OPT_ONELINE}, {"timeout", required_argument, NULL, 't'}, @@ -234,7 +245,19 @@ parse_options(int argc, char *argv[], struct shash *local_options) case OPT_DRY_RUN: dry_run = true; break; - +case OPT_NO_WAIT: +wait_type = NBCTL_WAIT_NONE; +break; +case OPT_WAIT: +if (!strcmp(optarg, "none")) { +wait_type = NBCTL_WAIT_NONE; +} else if (!strcmp(optarg, "sb")) { +wait_type = NBCTL_WAIT_SB; +} else { +ctl_fatal("argument to --wait must be " + "\"none\", \"sb\" "); +} +break; case OPT_LOCAL: if (shash_find(local_options, opt
[ovs-dev] [PATCH ovn 1/4] IC: interconnect DBs add basic Information Flow columns
Add basic flow columns to interconnect northbound DB and interconnect Southbound DB. Those columns will be used by future patches to add basic support for Information Flow in OVN interconnect. Signed-off-by: Mohammad Heib --- NEWS| 8 ovn-ic-nb.ovsschema | 6 -- ovn-ic-nb.xml | 17 + ovn-ic-sb.ovsschema | 8 +--- ovn-ic-sb.xml | 20 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index acb3b854f..a715c1545 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,14 @@ Post v23.09.0 external_ids:ovn-openflow-probe-interval configuration option for ovn-controller no longer matters and is ignored. - Enable PMTU discovery on geneve tunnels for E/W traffic. + - OVN Interconnection: +* INB provides basic feedback to the CMS about the ISB changes + handling status. +* IC_NB_Global now have "nb_ic_cfg" and "sb_ic_cfg" columns for + for ISB informational status. +* IC_SB_Global now have "nb_ic_cfg" column for ISB informational status. +* Availability_Zone now have "nb_ic_cfg" column for local AZ + informational status. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/ovn-ic-nb.ovsschema b/ovn-ic-nb.ovsschema index 894db8344..bee174357 100644 --- a/ovn-ic-nb.ovsschema +++ b/ovn-ic-nb.ovsschema @@ -1,10 +1,12 @@ { "name": "OVN_IC_Northbound", -"version": "1.0.0", -"cksum": "45589876 3383", +"version": "1.1.0", +"cksum": "3964083684 3501", "tables": { "IC_NB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, +"sb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, diff --git a/ovn-ic-nb.xml b/ovn-ic-nb.xml index 8c53bec3b..2ae9bf6d5 100644 --- a/ovn-ic-nb.xml +++ b/ovn-ic-nb.xml @@ -36,6 +36,23 @@ one row. + + These columns allow a client to track the overall configuration state of + the system. + + +Sequence number for client to increment. When a client modifies the +interconnect northbound database configuration and wishes to wait for +OVN-ICs to handle this change and update the Interconnect +southbound database, it may increment this sequence number. + + +Sequence number that one OVN-IC sets to the value of + after waiting to all the OVN-ICs +finish applying their changes to interconnect southbound database. + + + See External IDs at the beginning of this document. diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema index 1d60b36d1..5baf141cf 100644 --- a/ovn-ic-sb.ovsschema +++ b/ovn-ic-sb.ovsschema @@ -1,10 +1,11 @@ { "name": "OVN_IC_Southbound", -"version": "1.1.1", -"cksum": "3684563024 6914", +"version": "1.2.0", +"cksum": "1381014956 7032", "tables": { "IC_SB_Global": { "columns": { +"nb_ic_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, @@ -24,7 +25,8 @@ "isRoot": true}, "Availability_Zone": { "columns": { -"name": {"type": "string"}}, +"name": {"type": "string"}, +"nb_ic_cfg": {"type": {"key": "integer"}}}, "isRoot": true, "indexes": [["name"]]}, "Gateway": { diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml index f7e17e113..0368315c7 100644 --- a/ovn-ic-sb.xml +++ b/ovn-ic-sb.xml @@ -69,6 +69,20 @@ one row. + + This column allow a client to track the overall configuration state of + the system. + + +Sequence number for the configuration. When a CMS or +ovn-ic-nbctl updates the Interconnect northbound database, +it increments the nb_ic_cfg column in the NB_IC_Global +table in the Interconnect northbound database. when OVN-ICs updates +the southbound database to bring it up to date with these changes, one +OVN-IC updates this column to the same value. + + + See External IDs at the beginning of this document. @@ -102,6 +116,12 @@ A name that uniquely identifies the availability zone. + + + This column is used by the OVN-IC to inform + that this IC instance is aligned with the changes in INB + + -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn 2/4] ovn-ic: implement basic INB change handling status
This patch implements a basic sequence number protocol that can be used by CMS to determine if the changes applied to INB are successfully propagated to ISB. The implementation of this patch relies on OVN-ICs instances to update the ISB by adding a per AZ a nb_ic_cfg counter that will be updated by the OVN-IC once it is done and commit all needed changes to the ISB, and according to this AZ:nb_ic_cfg the ISB and INB will be updating about the status of the changes. Signed-off-by: Mohammad Heib --- ic/ovn-ic.c | 98 + 1 file changed, 92 insertions(+), 6 deletions(-) diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 12e2729ce..b08b0e2d4 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -1786,16 +1786,96 @@ route_run(struct ic_context *ctx, hmap_destroy(&ic_lrs); } +/* + * This function implements a sequence number protocol that can be used by + * the INB end user to verify that ISB is synced with all the changes that + * are done be the user/AZs-controllers: + * + * Since we have multiple IC instances running in different regions + * we can't rely on one of them to update the ISB and sync that update + * to INB since other ICs can make changes in parallel. + * So to have a sequence number protocol working properly we must + * make sure that all the IC instances are synced with the ISB first + * and then update the INB. + * + * To guarantee that all instances are synced with ISB first, each IC + * will do the following steps: + * + * 1. when local ovn-ic sees that INB:nb_ic_cfg has updated we will set + *the ic_sb_loop->next_cfg to match the INB:nb_ic_cfg and increment + *the value of AZ:nb_ic_cfg and wait until we get confirmation from + *the server. + * + * 2. once this IC instance changes for ISB are committed successfully + *(next loop), the value of cur_cfg will be updated to match + *the INB:nb_ic_cfg that indicate that our local instance is up to date + *and no more changes need to be done for ISB. + * + * 3. validate that the AZ:nb_ic_cfg to match the INB:nb_ic_cfg. + * + * 4. Go through all the AZs and check if all have the same value of + *AZ:nb_ic_cfg that means all the AZs are done with ISB changes and ISB are + *up to date with INB, so we can set the values of ISB:nb_ic_cfg to + *INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg. + */ static void -ovn_db_run(struct ic_context *ctx) +update_sequence_numbers(const struct icsbrec_availability_zone *az, +struct ic_context *ctx, +struct ovsdb_idl_loop *ic_sb_loop) { -const struct icsbrec_availability_zone *az = az_run(ctx); -VLOG_DBG("Availability zone: %s", az ? az->name : "not created yet."); +bool azs_cfg_equals = true; -if (!az) { -return; +if (ctx->ovnisb_txn && ctx->ovninb_txn) { +const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first( + ctx->ovninb_idl); +if (!ic_nb) { +ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn); +} +const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first( + ctx->ovnisb_idl); +if (!ic_sb) { +ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn); +} + +if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) && + (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) { +/* Deal with potential overflows. */ +if (az->nb_ic_cfg == LLONG_MAX) { +icsbrec_availability_zone_set_nb_ic_cfg(az, 0); +} +ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg; +ovsdb_idl_txn_increment(ctx->ovnisb_txn, &az->header_, + &icsbrec_availability_zone_col_nb_ic_cfg, true); +goto done; +} + +/* handle cases where accidentally AZ:ic_nb_cfg exceeds + * the INB:ic_nb_cfg. + */ +if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) { +icsbrec_availability_zone_set_nb_ic_cfg(az, ic_sb_loop->cur_cfg); +goto done; +} + +const struct icsbrec_availability_zone *other_az; +ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) { +if (other_az->nb_ic_cfg != az->nb_ic_cfg) { +azs_cfg_equals = false; +} +} + +if (azs_cfg_equals && (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg)) { +icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg); +icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg); +} } +done: ; +} +static void +ovn_db_run(struct ic_context *ctx, + const struct icsbrec_availability_zone *az) +{ ts_run(ctx); gateway_run(ctx, az);
[ovs-dev] [PATCH ovn 4/4] ic/tests: add unit test for ic sync command
add unit test that check validate that sync command sync ISB properly Signed-off-by: Mohammad Heib --- tests/ovn-ic.at | 22 ++ 1 file changed, 22 insertions(+) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index 5cc504e17..7464658ff 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -1297,3 +1297,25 @@ OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) + +AT_SETUP([ovn-ic -- sync ISB status to INB]) +ovn_init_ic_db +net_add n1 + +ovn_start az1 +sim_add gw-az1 +as gw-az1 + +check ovs-vsctl add-br br-phys +ovn_az_attach az1 n1 br-phys 192.168.1.1 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true + +ovn-ic-nbctl --wait=sb sync +set -- $(ovn-ic-nbctl get ic_nb_global . nb_ic_cfg sb_ic_cfg) +AS_VAR_SET([ic_nb_cfg], [$1]) +AS_VAR_SET([ic_sb_cfg], [$2]) +check test $ic_nb_cfg == $ic_sb_cfg + +OVN_CLEANUP_IC([az1]) +AT_CLEANUP +]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn] ovn-ic: handle NB:name updates properly
When the user updates the NB_GLOBAL.name after registering to IC Databases if the user already has defined chassis as a gateway that will cause ovn-ic instance to run in an infinity loop trying to update the gateways and insert the current gateway to the SB.chassis tables as a remote chassis (we match on the new AZ ) which will fail since we already have this chassis with is-interconn in local SB. This patch aims to fix the above issues by updating the AZ.name only when the user updates the NB.name locally. Signed-off-by: Mohammad Heib --- ic/ovn-ic.c | 10 +++--- tests/ovn-ic.at | 23 +++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 8ceb34d7c..12e2729ce 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -132,14 +132,18 @@ az_run(struct ic_context *ctx) return NULL; } -/* Delete old AZ if name changes. Note: if name changed when ovn-ic - * is not running, one has to manually delete the old AZ with: +/* Update old AZ if name changes. Note: if name changed when ovn-ic + * is not running, one has to manually delete/update the old AZ with: * "ovn-ic-sbctl destroy avail ". */ static char *az_name; const struct icsbrec_availability_zone *az; if (az_name && strcmp(az_name, nb_global->name)) { ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) { -if (!strcmp(az->name, az_name)) { +/* AZ name update locally need to update az in ISB. */ +if (nb_global->name[0] && !strcmp(az->name, az_name)) { +icsbrec_availability_zone_set_name(az, nb_global->name); +break; +} else if (!nb_global->name[0] && !strcmp(az->name, az_name)) { icsbrec_availability_zone_delete(az); break; } diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index d4c436f84..5cc504e17 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -28,7 +28,30 @@ availability-zone az3 ]) OVN_CLEANUP_IC([az1], [az2]) +AT_CLEANUP +]) + + +AT_SETUP([ovn-ic -- AZ update in GW]) +ovn_init_ic_db +net_add n1 +ovn_start az1 +sim_add gw-az1 +as gw-az1 + +check ovs-vsctl add-br br-phys +ovn_az_attach az1 n1 br-phys 192.168.1.1 +check ovs-vsctl set open . external-ids:ovn-is-interconn=true + +az_uuid=$(fetch_column ic-sb:availability-zone _uuid name="az1") +ovn_as az1 ovn-nbctl set NB_Global . name="az2" +wait_column "$az_uuid" ic-sb:availability-zone _uuid name="az2" + +# make sure that gateway still point to the same AZ with new name +wait_column "$az_uuid" ic-sb:gateway availability_zone name="gw-az1" + +OVN_CLEANUP_IC([az1]) AT_CLEANUP ]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH v5 1/2] mcast-snooping: Store IGMP/MLD protocol version.
Store igmp/mld protocol version into the mcast_group internally, the multicast snooping feature is used by many OVS consumers and those consumers heavily rely on the OVS implementation to manage/deal with mcast groups, some of those consumers also need to deal/expose the mcast protocol to the end user for debuggability purposes. OVN for example needs to expose the protocol version to the end user to match between the protocol version used in the OVN logical switches and the uplink ports Therefore, instead of implementing this in each OVS consumer that needs to deal mcast group protocol version which will be very complicated implementation since it rely on the OVS code, saving the protocol to the mdb inside OVS will give that consumer access to the protocol version very easily. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c | 20 +--- lib/mcast-snooping.h | 21 ++--- ofproto/ofproto-dpif-xlate.c | 10 -- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 43805ae4d..5046e35d2 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -389,7 +389,8 @@ mcast_snooping_prune_expired(struct mcast_snooping *ms, bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { bool learned; @@ -415,6 +416,7 @@ mcast_snooping_add_group(struct mcast_snooping *ms, hmap_insert(&ms->table, &grp->hmap_node, hash); grp->addr = *addr; grp->vlan = vlan; +grp->protocol_version = grp_proto; ovs_list_init(&grp->bundle_lru); learned = true; ms->need_revalidate = true; @@ -431,17 +433,19 @@ mcast_snooping_add_group(struct mcast_snooping *ms, bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { struct in6_addr addr = in6_addr_mapped_ipv4(ip4); -return mcast_snooping_add_group(ms, &addr, vlan, port); +return mcast_snooping_add_group(ms, &addr, vlan, port, grp_proto); } int mcast_snooping_add_report(struct mcast_snooping *ms, const struct dp_packet *p, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) { ovs_be32 ip4; size_t offset; @@ -478,7 +482,7 @@ mcast_snooping_add_report(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group4(ms, ip4, vlan, port); } else { -ret = mcast_snooping_add_group4(ms, ip4, vlan, port); +ret = mcast_snooping_add_group4(ms, ip4, vlan, port, grp_proto); } if (ret) { count++; @@ -513,7 +517,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, switch (mld->type) { case MLD_REPORT: -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MCAST_GROUP_MLDV1); if (ret) { count++; } @@ -545,7 +550,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group(ms, addr, vlan, port); } else { -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MCAST_GROUP_MLDV2); } if (ret) { count++; diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f120405da..f54007740 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -39,6 +39,15 @@ struct mcast_snooping; /* Time, in seconds, before expiring a mrouter_port due to inactivity. */ #define MCAST_MROUTER_PORT_IDLE_TIME 180 +/* Multicast group protocol. */ +typedef enum { +MCAST_GROUP_IGMPV1 = 0, +MCAST_GROUP_IGMPV2, +MCAST_GROUP_IGMPV3, +MCAST_GROUP_MLDV1, +MCAST_GROUP_MLDV2, +} mcast_group_proto; + /* Multicast group entry. * Guarded by owning 'mcast_snooping''s rwlock. */ struct mcast_group { @@ -51,6 +60,9 @@ struct mcast_group { /* VLAN tag. */ uint16_t vlan; +/* Multicast group IPv6/IPv4 Protocol version IGMPv1,2,3 or MLDv1,2 */ +mcast_group_proto protocol_version; +
[ovs-dev] [PATCH v5 2/2] mcast-snooping: Add group protocol to mdb/show output.
Expose the mcast group protocol via the mdb/show command output. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c| 24 ++ lib/mcast-snooping.h| 1 + ofproto/ofproto-dpif.c | 6 ++- tests/mcast-snooping.at | 103 tests/stp.at| 6 +-- 5 files changed, 116 insertions(+), 24 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 5046e35d2..d72cac0a4 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -57,6 +57,30 @@ mcast_snooping_flood_unreg(const struct mcast_snooping *ms) return ms->flood_unreg; } +char * +mcast_snooping_group_proto_str(mcast_group_proto grp_proto) +{ +switch (grp_proto) { +case MCAST_GROUP_IGMPV1: +return "IGMPv1"; +break; +case MCAST_GROUP_IGMPV2: +return "IGMPv2"; +break; +case MCAST_GROUP_IGMPV3: +return "IGMPv3"; +break; +case MCAST_GROUP_MLDV1: +return "MLDv1"; +break; +case MCAST_GROUP_MLDV2: +return "MLDv2"; +break; +default: +return ""; +} +} + bool mcast_snooping_is_query(ovs_be16 igmp_type) { diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f54007740..4ab83b049 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -225,6 +225,7 @@ bool mcast_snooping_add_mrouter(struct mcast_snooping *ms, uint16_t vlan, OVS_REQ_WRLOCK(ms->rwlock); bool mcast_snooping_is_query(ovs_be16 igmp_type); bool mcast_snooping_is_membership(ovs_be16 igmp_type); +char * mcast_snooping_group_proto_str(mcast_group_proto grp_proto); /* Flush. */ void mcast_snooping_mdb_flush(struct mcast_snooping *ms); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 54e057d43..b116d84f9 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -6122,7 +6122,7 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, return; } -ds_put_cstr(&ds, " port VLAN GROUPAge\n"); +ds_put_cstr(&ds, " port VLAN PROTO GROUPAge\n"); ovs_rwlock_rdlock(&ofproto->ms->rwlock); LIST_FOR_EACH (grp, group_node, &ofproto->ms->group_lru) { LIST_FOR_EACH(b, bundle_node, &grp->bundle_lru) { @@ -6131,7 +6131,9 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, bundle = b->port; ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port, NULL, name, sizeof name); -ds_put_format(&ds, "%5s %4d ", name, grp->vlan); +ds_put_format(&ds, "%5s %4d %5s ", name, grp->vlan, + mcast_snooping_group_proto_str( + grp->protocol_version)); ipv6_format_mapped(&grp->addr, &ds); ds_put_format(&ds, " %3d\n", mcast_bundle_age(ofproto->ms, b)); diff --git a/tests/mcast-snooping.at b/tests/mcast-snooping.at index 890e6aca0..02be196e4 100644 --- a/tests/mcast-snooping.at +++ b/tests/mcast-snooping.at @@ -44,7 +44,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ '01005e015c8a38552552810006c0080046c0002401027c00ac111c01e00194041164ec1e027d']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUPAge 2 1725 querier 0 2 1728 querier 0 ]) @@ -75,7 +75,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ '01005e015c8a38552552810006bd080046c0002401027f00ac111901e00194041164ec10027d']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUPAge ]) @@ -87,8 +87,8 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ 'ff0e4c67000c290e4c6786dd6021ff020001ff0e4c673a00050201008300e7b8ff020001ff0e4c67']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge -2 0 ff02::1:ff0e:4c67 0 + port VLAN PROTO GROUPAge +2 0 MLDv1 ff02::1:ff0e:4c67 0 ]) AT_CHECK([ovs-appctl mdb/flush br0], [0], [dnl @@ -99,7 +99,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ 'ff0e4c67000c290e4c6786dd6021ff020001ff0e4c673a00050201008300e7b0ff020001ff0e4c67']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUP
Re: [ovs-dev] [PATCH v4 1/2] mcast-snooping: Store IGMP/MLD protocol version.
On Mon, Nov 20, 2023 at 6:09 PM Simon Horman wrote: > On Mon, Nov 20, 2023 at 04:22:44PM +0200, Mohammad Heib wrote: > > Store the igmp/mld protocol version into the > > mcast_group internally. > > > > This can be used by ovs consumers to update > > about the igmp/mld version of each group. > > Thanks Mohammad, > > I see in patch 2/2 that the user can now gain access to the igmp/mld > version of each group. But I am wondering if we could add some text > to the commit message to explain, perhaps via an example, why > a user might want such information. > Hi Simon, Thank you for the review. actually, i don't really have a good reason why the user will need the group protocol in OVS stand-alone case, but I'm trying to expand that here and save the protocol because i need it in the OVN/OVS case where we store each Mcast group information inside ovn-sb DB as raw in *the MCAST_GROUP* table, and i have to expose a protocol version for each Group in this table, cause OVN relies on the ovs mcast implementation to maintain this table, i thought this would be the cleaner way to accomplish that. so now i don't really know which example can be good to add :( do you think adding a small example of extracting the protocol will be good enough? Thanks, ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH v4 2/2] mcast-snooping: Add group protocol to mdb/show output.
Expose the mcast group protocol via the mdb/show command output. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c| 24 ++ lib/mcast-snooping.h| 1 + ofproto/ofproto-dpif.c | 6 ++- tests/mcast-snooping.at | 99 ++--- tests/stp.at| 6 +-- 5 files changed, 114 insertions(+), 22 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 99516bd43..1f4bcc865 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -57,6 +57,30 @@ mcast_snooping_flood_unreg(const struct mcast_snooping *ms) return ms->flood_unreg; } +char * +mcast_snooping_group_proto_str(mcast_group_proto grp_proto) +{ +switch (grp_proto) { +case MCAST_GROUP_IGMPV1: +return "IGMPv1"; +break; +case MCAST_GROUP_IGMPV2: +return "IGMPv2"; +break; +case MCAST_GROUP_IGMPV3: +return "IGMPv3"; +break; +case MCAST_GROUP_MLDV1: +return "MLDv1"; +break; +case MCAST_GROUP_MLDV2: +return "MLDv2"; +break; +default: +return ""; +} +} + bool mcast_snooping_is_query(ovs_be16 igmp_type) { diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f54007740..4ab83b049 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -225,6 +225,7 @@ bool mcast_snooping_add_mrouter(struct mcast_snooping *ms, uint16_t vlan, OVS_REQ_WRLOCK(ms->rwlock); bool mcast_snooping_is_query(ovs_be16 igmp_type); bool mcast_snooping_is_membership(ovs_be16 igmp_type); +char * mcast_snooping_group_proto_str(mcast_group_proto grp_proto); /* Flush. */ void mcast_snooping_mdb_flush(struct mcast_snooping *ms); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 54e057d43..b116d84f9 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -6122,7 +6122,7 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, return; } -ds_put_cstr(&ds, " port VLAN GROUPAge\n"); +ds_put_cstr(&ds, " port VLAN PROTO GROUPAge\n"); ovs_rwlock_rdlock(&ofproto->ms->rwlock); LIST_FOR_EACH (grp, group_node, &ofproto->ms->group_lru) { LIST_FOR_EACH(b, bundle_node, &grp->bundle_lru) { @@ -6131,7 +6131,9 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, bundle = b->port; ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port, NULL, name, sizeof name); -ds_put_format(&ds, "%5s %4d ", name, grp->vlan); +ds_put_format(&ds, "%5s %4d %5s ", name, grp->vlan, + mcast_snooping_group_proto_str( + grp->protocol_version)); ipv6_format_mapped(&grp->addr, &ds); ds_put_format(&ds, " %3d\n", mcast_bundle_age(ofproto->ms, b)); diff --git a/tests/mcast-snooping.at b/tests/mcast-snooping.at index d5b7c4774..dc20ac92f 100644 --- a/tests/mcast-snooping.at +++ b/tests/mcast-snooping.at @@ -44,7 +44,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ '01005e015c8a38552552810006c0080046c0002401027c00ac111c01e00194041164ec1e027d']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUPAge 2 1725 querier 0 2 1728 querier 0 ]) @@ -75,7 +75,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ '01005e015c8a38552552810006bd080046c0002401027f00ac111901e00194041164ec10027d']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUPAge ]) @@ -87,8 +87,8 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ 'ff0e4c67000c290e4c6786dd6021ff020001ff0e4c673a00050201008300e7b8ff020001ff0e4c67']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge -2 0 ff02::1:ff0e:4c67 0 + port VLAN PROTO GROUPAge +2 0 MLDv1 ff02::1:ff0e:4c67 0 ]) AT_CHECK([ovs-appctl mdb/flush br0], [0], [dnl @@ -99,7 +99,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ 'ff0e4c67000c290e4c6786dd6021ff020001ff0e4c673a00050201008300e7b0ff020001ff0e4c67']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUPAge ])
[ovs-dev] [PATCH v4 1/2] mcast-snooping: Store IGMP/MLD protocol version.
Store the igmp/mld protocol version into the mcast_group internally. This can be used by ovs consumers to update about the igmp/mld version of each group. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c | 20 +--- lib/mcast-snooping.h | 21 ++--- ofproto/ofproto-dpif-xlate.c | 10 -- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 029ca2855..99516bd43 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -389,7 +389,8 @@ mcast_snooping_prune_expired(struct mcast_snooping *ms, bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { bool learned; @@ -415,6 +416,7 @@ mcast_snooping_add_group(struct mcast_snooping *ms, hmap_insert(&ms->table, &grp->hmap_node, hash); grp->addr = *addr; grp->vlan = vlan; +grp->protocol_version = grp_proto; ovs_list_init(&grp->bundle_lru); learned = true; ms->need_revalidate = true; @@ -431,17 +433,19 @@ mcast_snooping_add_group(struct mcast_snooping *ms, bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { struct in6_addr addr = in6_addr_mapped_ipv4(ip4); -return mcast_snooping_add_group(ms, &addr, vlan, port); +return mcast_snooping_add_group(ms, &addr, vlan, port, grp_proto); } int mcast_snooping_add_report(struct mcast_snooping *ms, const struct dp_packet *p, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) { ovs_be32 ip4; size_t offset; @@ -478,7 +482,7 @@ mcast_snooping_add_report(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group4(ms, ip4, vlan, port); } else { -ret = mcast_snooping_add_group4(ms, ip4, vlan, port); +ret = mcast_snooping_add_group4(ms, ip4, vlan, port, grp_proto); } if (ret) { count++; @@ -513,7 +517,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, switch (mld->type) { case MLD_REPORT: -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MCAST_GROUP_MLDV1); if (ret) { count++; } @@ -545,7 +550,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group(ms, addr, vlan, port); } else { -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MCAST_GROUP_MLDV2); } if (ret) { count++; diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f120405da..f54007740 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -39,6 +39,15 @@ struct mcast_snooping; /* Time, in seconds, before expiring a mrouter_port due to inactivity. */ #define MCAST_MROUTER_PORT_IDLE_TIME 180 +/* Multicast group protocol. */ +typedef enum { +MCAST_GROUP_IGMPV1 = 0, +MCAST_GROUP_IGMPV2, +MCAST_GROUP_IGMPV3, +MCAST_GROUP_MLDV1, +MCAST_GROUP_MLDV2, +} mcast_group_proto; + /* Multicast group entry. * Guarded by owning 'mcast_snooping''s rwlock. */ struct mcast_group { @@ -51,6 +60,9 @@ struct mcast_group { /* VLAN tag. */ uint16_t vlan; +/* Multicast group IPv6/IPv4 Protocol version IGMPv1,2,3 or MLDv1,2 */ +mcast_group_proto protocol_version; + /* Node in parent struct mcast_snooping group_lru. */ struct ovs_list group_node OVS_GUARDED; @@ -185,14 +197,17 @@ mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4, /* Learning. */ bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock); bool mcast_snooping_add_group4(struct mcast_snooping *m
Re: [ovs-dev] [PATCH v2] mcast-snooping: Store IGMP/MLD protocol version.
Hi Eelco, On Thu, Nov 16, 2023 at 5:23 PM Eelco Chaudron wrote: > > > On 16 Nov 2023, at 15:58, Eelco Chaudron wrote: > > > On 16 Nov 2023, at 15:08, Mohammad Heib wrote: > > > >> Store the igmp/mld protocol version into the > >> mcast_group internally. > >> > >> This can be used by ovs consumers to update > >> about the igmp/mld version of each group. > >> > >> Signed-off-by: Mohammad Heib > > > > Hi Mohammad, > > > > Thanks for the patch, I have not reviewed the actual code yet, but it > would be good to include a use case for this patch (maybe expand this to a > series). This way it’s clear why we need to store this information. > > > > Cheers, > > > > Eelco > > After a quick code review I have one comment, see below. > > >> --- > >> lib/mcast-snooping.c | 16 +--- > >> lib/mcast-snooping.h | 9 ++--- > >> ofproto/ofproto-dpif-xlate.c | 6 -- > >> 3 files changed, 19 insertions(+), 12 deletions(-) > >> > >> diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c > >> index 029ca2855..926daf9ac 100644 > >> --- a/lib/mcast-snooping.c > >> +++ b/lib/mcast-snooping.c > >> @@ -389,7 +389,7 @@ mcast_snooping_prune_expired(struct mcast_snooping > *ms, > >> bool > >> mcast_snooping_add_group(struct mcast_snooping *ms, > >> const struct in6_addr *addr, > >> - uint16_t vlan, void *port) > >> + uint16_t vlan, void *port, uint8_t grp_proto) > >> OVS_REQ_WRLOCK(ms->rwlock) > >> { > >> bool learned; > >> @@ -415,6 +415,7 @@ mcast_snooping_add_group(struct mcast_snooping *ms, > >> hmap_insert(&ms->table, &grp->hmap_node, hash); > >> grp->addr = *addr; > >> grp->vlan = vlan; > >> +grp->protocol_version = grp_proto; > >> ovs_list_init(&grp->bundle_lru); > >> learned = true; > >> ms->need_revalidate = true; > >> @@ -431,17 +432,17 @@ mcast_snooping_add_group(struct mcast_snooping > *ms, > >> > >> bool > >> mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, > >> - uint16_t vlan, void *port) > >> + uint16_t vlan, void *port, uint8_t grp_proto) > >> OVS_REQ_WRLOCK(ms->rwlock) > >> { > >> struct in6_addr addr = in6_addr_mapped_ipv4(ip4); > >> -return mcast_snooping_add_group(ms, &addr, vlan, port); > >> +return mcast_snooping_add_group(ms, &addr, vlan, port, grp_proto); > >> } > >> > >> int > >> mcast_snooping_add_report(struct mcast_snooping *ms, > >>const struct dp_packet *p, > >> - uint16_t vlan, void *port) > >> + uint16_t vlan, void *port, uint8_t grp_proto) > >> { > >> ovs_be32 ip4; > >> size_t offset; > >> @@ -478,7 +479,7 @@ mcast_snooping_add_report(struct mcast_snooping *ms, > >> || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { > >> ret = mcast_snooping_leave_group4(ms, ip4, vlan, port); > >> } else { > >> -ret = mcast_snooping_add_group4(ms, ip4, vlan, port); > >> +ret = mcast_snooping_add_group4(ms, ip4, vlan, port, > grp_proto); > >> } > >> if (ret) { > >> count++; > >> @@ -513,7 +514,7 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, > >> > >> switch (mld->type) { > >> case MLD_REPORT: > >> -ret = mcast_snooping_add_group(ms, addr, vlan, port); > >> +ret = mcast_snooping_add_group(ms, addr, vlan, port, > MLD_REPORT); > >> if (ret) { > >> count++; > >> } > >> @@ -545,7 +546,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, > >> || record->type == > IGMPV3_CHANGE_TO_INCLUDE_MODE)) { > >> ret = mcast_snooping_leave_group(ms, addr, vlan, > port); > >> } else { > >> -ret = mcast_snooping_add_group(ms, addr, vlan, > port); > >> +ret = mcast_snooping_add_group(ms, addr, vlan, > port, > >> +
[ovs-dev] [PATCH v3 2/2] mcast-snooping: Add group protocol to mdb/show output.
Expose the mcast group protocol via the mdb/show command output. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c| 24 ++ lib/mcast-snooping.h| 1 + ofproto/ofproto-dpif.c | 6 ++- tests/mcast-snooping.at | 99 ++--- tests/stp.at| 6 +-- 5 files changed, 114 insertions(+), 22 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 99516bd43..1f4bcc865 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -57,6 +57,30 @@ mcast_snooping_flood_unreg(const struct mcast_snooping *ms) return ms->flood_unreg; } +char * +mcast_snooping_group_proto_str(mcast_group_proto grp_proto) +{ +switch (grp_proto) { +case MCAST_GROUP_IGMPV1: +return "IGMPv1"; +break; +case MCAST_GROUP_IGMPV2: +return "IGMPv2"; +break; +case MCAST_GROUP_IGMPV3: +return "IGMPv3"; +break; +case MCAST_GROUP_MLDV1: +return "MLDv1"; +break; +case MCAST_GROUP_MLDV2: +return "MLDv2"; +break; +default: +return ""; +} +} + bool mcast_snooping_is_query(ovs_be16 igmp_type) { diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f54007740..4ab83b049 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -225,6 +225,7 @@ bool mcast_snooping_add_mrouter(struct mcast_snooping *ms, uint16_t vlan, OVS_REQ_WRLOCK(ms->rwlock); bool mcast_snooping_is_query(ovs_be16 igmp_type); bool mcast_snooping_is_membership(ovs_be16 igmp_type); +char * mcast_snooping_group_proto_str(mcast_group_proto grp_proto); /* Flush. */ void mcast_snooping_mdb_flush(struct mcast_snooping *ms); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 54e057d43..b116d84f9 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -6122,7 +6122,7 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, return; } -ds_put_cstr(&ds, " port VLAN GROUPAge\n"); +ds_put_cstr(&ds, " port VLAN PROTO GROUPAge\n"); ovs_rwlock_rdlock(&ofproto->ms->rwlock); LIST_FOR_EACH (grp, group_node, &ofproto->ms->group_lru) { LIST_FOR_EACH(b, bundle_node, &grp->bundle_lru) { @@ -6131,7 +6131,9 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, bundle = b->port; ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port, NULL, name, sizeof name); -ds_put_format(&ds, "%5s %4d ", name, grp->vlan); +ds_put_format(&ds, "%5s %4d %5s ", name, grp->vlan, + mcast_snooping_group_proto_str( + grp->protocol_version)); ipv6_format_mapped(&grp->addr, &ds); ds_put_format(&ds, " %3d\n", mcast_bundle_age(ofproto->ms, b)); diff --git a/tests/mcast-snooping.at b/tests/mcast-snooping.at index d5b7c4774..dc20ac92f 100644 --- a/tests/mcast-snooping.at +++ b/tests/mcast-snooping.at @@ -44,7 +44,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ '01005e015c8a38552552810006c0080046c0002401027c00ac111c01e00194041164ec1e027d']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUPAge 2 1725 querier 0 2 1728 querier 0 ]) @@ -75,7 +75,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ '01005e015c8a38552552810006bd080046c0002401027f00ac111901e00194041164ec10027d']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUPAge ]) @@ -87,8 +87,8 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ 'ff0e4c67000c290e4c6786dd6021ff020001ff0e4c673a00050201008300e7b8ff020001ff0e4c67']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge -2 0 ff02::1:ff0e:4c67 0 + port VLAN PROTO GROUPAge +2 0 MLDv1 ff02::1:ff0e:4c67 0 ]) AT_CHECK([ovs-appctl mdb/flush br0], [0], [dnl @@ -99,7 +99,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 \ 'ff0e4c67000c290e4c6786dd6021ff020001ff0e4c673a00050201008300e7b0ff020001ff0e4c67']) AT_CHECK([ovs-appctl mdb/show br0], [0], [dnl - port VLAN GROUPAge + port VLAN PROTO GROUPAge ])
[ovs-dev] [PATCH v3 1/2] mcast-snooping: Store IGMP/MLD protocol version.
Store the igmp/mld protocol version into the mcast_group internally. This can be used by ovs consumers to update about the igmp/mld version of each group. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c | 20 +--- lib/mcast-snooping.h | 21 ++--- ofproto/ofproto-dpif-xlate.c | 10 -- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 029ca2855..99516bd43 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -389,7 +389,8 @@ mcast_snooping_prune_expired(struct mcast_snooping *ms, bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { bool learned; @@ -415,6 +416,7 @@ mcast_snooping_add_group(struct mcast_snooping *ms, hmap_insert(&ms->table, &grp->hmap_node, hash); grp->addr = *addr; grp->vlan = vlan; +grp->protocol_version = grp_proto; ovs_list_init(&grp->bundle_lru); learned = true; ms->need_revalidate = true; @@ -431,17 +433,19 @@ mcast_snooping_add_group(struct mcast_snooping *ms, bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { struct in6_addr addr = in6_addr_mapped_ipv4(ip4); -return mcast_snooping_add_group(ms, &addr, vlan, port); +return mcast_snooping_add_group(ms, &addr, vlan, port, grp_proto); } int mcast_snooping_add_report(struct mcast_snooping *ms, const struct dp_packet *p, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) { ovs_be32 ip4; size_t offset; @@ -478,7 +482,7 @@ mcast_snooping_add_report(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group4(ms, ip4, vlan, port); } else { -ret = mcast_snooping_add_group4(ms, ip4, vlan, port); +ret = mcast_snooping_add_group4(ms, ip4, vlan, port, grp_proto); } if (ret) { count++; @@ -513,7 +517,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, switch (mld->type) { case MLD_REPORT: -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MCAST_GROUP_MLDV1); if (ret) { count++; } @@ -545,7 +550,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group(ms, addr, vlan, port); } else { -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MCAST_GROUP_MLDV2); } if (ret) { count++; diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f120405da..f54007740 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -39,6 +39,15 @@ struct mcast_snooping; /* Time, in seconds, before expiring a mrouter_port due to inactivity. */ #define MCAST_MROUTER_PORT_IDLE_TIME 180 +/* Multicast group protocol. */ +typedef enum { +MCAST_GROUP_IGMPV1 = 0, +MCAST_GROUP_IGMPV2, +MCAST_GROUP_IGMPV3, +MCAST_GROUP_MLDV1, +MCAST_GROUP_MLDV2, +} mcast_group_proto; + /* Multicast group entry. * Guarded by owning 'mcast_snooping''s rwlock. */ struct mcast_group { @@ -51,6 +60,9 @@ struct mcast_group { /* VLAN tag. */ uint16_t vlan; +/* Multicast group IPv6/IPv4 Protocol version IGMPv1,2,3 or MLDv1,2 */ +mcast_group_proto protocol_version; + /* Node in parent struct mcast_snooping group_lru. */ struct ovs_list group_node OVS_GUARDED; @@ -185,14 +197,17 @@ mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4, /* Learning. */ bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, + mcast_group_proto grp_proto) OVS_REQ_WRLOCK(ms->rwlock); bool mcast_snooping_add_group4(struct mcast_snooping *m
[ovs-dev] [PATCH v2] mcast-snooping: Store IGMP/MLD protocol version.
Store the igmp/mld protocol version into the mcast_group internally. This can be used by ovs consumers to update about the igmp/mld version of each group. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c | 16 +--- lib/mcast-snooping.h | 9 ++--- ofproto/ofproto-dpif-xlate.c | 6 -- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 029ca2855..926daf9ac 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -389,7 +389,7 @@ mcast_snooping_prune_expired(struct mcast_snooping *ms, bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { bool learned; @@ -415,6 +415,7 @@ mcast_snooping_add_group(struct mcast_snooping *ms, hmap_insert(&ms->table, &grp->hmap_node, hash); grp->addr = *addr; grp->vlan = vlan; +grp->protocol_version = grp_proto; ovs_list_init(&grp->bundle_lru); learned = true; ms->need_revalidate = true; @@ -431,17 +432,17 @@ mcast_snooping_add_group(struct mcast_snooping *ms, bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { struct in6_addr addr = in6_addr_mapped_ipv4(ip4); -return mcast_snooping_add_group(ms, &addr, vlan, port); +return mcast_snooping_add_group(ms, &addr, vlan, port, grp_proto); } int mcast_snooping_add_report(struct mcast_snooping *ms, const struct dp_packet *p, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) { ovs_be32 ip4; size_t offset; @@ -478,7 +479,7 @@ mcast_snooping_add_report(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group4(ms, ip4, vlan, port); } else { -ret = mcast_snooping_add_group4(ms, ip4, vlan, port); +ret = mcast_snooping_add_group4(ms, ip4, vlan, port, grp_proto); } if (ret) { count++; @@ -513,7 +514,7 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, switch (mld->type) { case MLD_REPORT: -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, MLD_REPORT); if (ret) { count++; } @@ -545,7 +546,8 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group(ms, addr, vlan, port); } else { -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, + MLD2_REPORT); } if (ret) { count++; diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f120405da..6321b63ab 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -51,6 +51,9 @@ struct mcast_group { /* VLAN tag. */ uint16_t vlan; +/* Multicast group IPv6/IPv4 Protocol version IGMPv1,2,3 or MLDv1,2 */ +uint8_t protocol_version; + /* Node in parent struct mcast_snooping group_lru. */ struct ovs_list group_node OVS_GUARDED; @@ -185,14 +188,14 @@ mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4, /* Learning. */ bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock); bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock); int mcast_snooping_add_report(struct mcast_snooping *ms, const struct dp_packet *p, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock); int mcast_snooping_add_mld(struct mcast_snooping *ms, const struct dp_packet *p, diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index e24377330..26bd678cd 100644 --- a/ofproto/ofproto-d
[ovs-dev] [PATCH] mcast-snooping: store IGMP/MLD protocol version
Store the igmp/mld protocol version into the mcast_group internally. This can be used by ovs consumers to update about the igmp/mld version of each group. Signed-off-by: Mohammad Heib --- lib/mcast-snooping.c | 15 --- lib/mcast-snooping.h | 9 ++--- ofproto/ofproto-dpif-xlate.c | 6 -- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c index 029ca2855..185723861 100644 --- a/lib/mcast-snooping.c +++ b/lib/mcast-snooping.c @@ -389,7 +389,7 @@ mcast_snooping_prune_expired(struct mcast_snooping *ms, bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { bool learned; @@ -415,6 +415,7 @@ mcast_snooping_add_group(struct mcast_snooping *ms, hmap_insert(&ms->table, &grp->hmap_node, hash); grp->addr = *addr; grp->vlan = vlan; +grp->protocol_version = grp_proto; ovs_list_init(&grp->bundle_lru); learned = true; ms->need_revalidate = true; @@ -431,17 +432,17 @@ mcast_snooping_add_group(struct mcast_snooping *ms, bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock) { struct in6_addr addr = in6_addr_mapped_ipv4(ip4); -return mcast_snooping_add_group(ms, &addr, vlan, port); +return mcast_snooping_add_group(ms, &addr, vlan, port, grp_proto); } int mcast_snooping_add_report(struct mcast_snooping *ms, const struct dp_packet *p, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) { ovs_be32 ip4; size_t offset; @@ -478,7 +479,7 @@ mcast_snooping_add_report(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group4(ms, ip4, vlan, port); } else { -ret = mcast_snooping_add_group4(ms, ip4, vlan, port); +ret = mcast_snooping_add_group4(ms, ip4, vlan, port, grp_proto); } if (ret) { count++; @@ -513,7 +514,7 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, switch (mld->type) { case MLD_REPORT: -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, MLD_REPORT); if (ret) { count++; } @@ -545,7 +546,7 @@ mcast_snooping_add_mld(struct mcast_snooping *ms, || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) { ret = mcast_snooping_leave_group(ms, addr, vlan, port); } else { -ret = mcast_snooping_add_group(ms, addr, vlan, port); +ret = mcast_snooping_add_group(ms, addr, vlan, port, MLD2_REPORT); } if (ret) { count++; diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h index f120405da..6321b63ab 100644 --- a/lib/mcast-snooping.h +++ b/lib/mcast-snooping.h @@ -51,6 +51,9 @@ struct mcast_group { /* VLAN tag. */ uint16_t vlan; +/* Multicast group IPv6/IPv4 Protocol version IGMPv1,2,3 or MLDv1,2 */ +uint8_t protocol_version; + /* Node in parent struct mcast_snooping group_lru. */ struct ovs_list group_node OVS_GUARDED; @@ -185,14 +188,14 @@ mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4, /* Learning. */ bool mcast_snooping_add_group(struct mcast_snooping *ms, const struct in6_addr *addr, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock); bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock); int mcast_snooping_add_report(struct mcast_snooping *ms, const struct dp_packet *p, - uint16_t vlan, void *port) + uint16_t vlan, void *port, uint8_t grp_proto) OVS_REQ_WRLOCK(ms->rwlock); int mcast_snooping_add_mld(struct mcast_snooping *ms, const struct dp_packet *p, diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index e24377330..26bd678cd 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2781,7 +2781,8 @@ update_mcast_s
[ovs-dev] [PATCH ovn v2] DNS: allow defining records that owned by OVN only
Currently OVN allows users to create DNS records and define domains within these records. These domains can be associated with IPV4 or IPv6 or both, when the user creates a domain with both IPv4 and IPv6 ovn will answer each query for this domain immediately and everything works as expected. But if the user only creates a domain with only IPv4 or IPv6 this will cause the DNS queries respond take longer than the usual since OVN will forward query and user will keep waiting for an answer until someone else replies for this query or timeout occur. The above behavior is a bit problematic if the user knows that this domain is only configured in OVN we should not forward queries for this domain to the outside. This patch adds an option:ovn-owned for the DNS table that can be set to "true" when creating a DNS. When setting this option to "true" all the domains within this table will be treated as local domains only, and queries for domains within this table that don't have an accurate IP will be refused immediately to save the time of waiting for timeout. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1946662 Signed-off-by: Mohammad Heib --- NEWS | 4 +++ controller/pinctrl.c | 43 - northd/northd.c | 13 + ovn-nb.ovsschema | 9 -- ovn-nb.xml | 14 ++ ovn-sb.ovsschema | 9 -- ovn-sb.xml | 6 tests/ovn.at | 65 8 files changed, 158 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 30f6edb28..e10fb79dd 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ Post v23.09.0 - + - DNS now have an "options" column for configuration of extra options. + - A new DNS option "ovn-owned" has been added to allow defining domains +that are owned only by ovn, queries for that domain will not be processed +externally. - Disable OpenFlow inactivity probing between ovn-controller and OVS. OF connection is established over unix socket, which is a reliable connection method and doesn't require additional probing. diff --git a/controller/pinctrl.c b/controller/pinctrl.c index d88e951a6..cf48089b6 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -179,6 +179,7 @@ struct pinctrl { struct latch pinctrl_thread_exit; bool mac_binding_can_timestamp; bool fdb_can_timestamp; +bool dns_supports_ovn_owned; }; static struct pinctrl pinctrl; @@ -2713,6 +2714,7 @@ struct dns_data { uint64_t *dps; size_t n_dps; struct smap records; +struct smap options; bool delete; }; @@ -2741,6 +2743,7 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) if (!dns_data) { dns_data = xmalloc(sizeof *dns_data); smap_init(&dns_data->records); +smap_init(&dns_data->options); shash_add(&dns_cache, dns_id, dns_data); dns_data->n_dps = 0; dns_data->dps = NULL; @@ -2755,6 +2758,12 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) smap_clone(&dns_data->records, &sbrec_dns->records); } +if (pinctrl.dns_supports_ovn_owned +&& !smap_equal(&dns_data->options, &sbrec_dns->options)) { +smap_destroy(&dns_data->options); +smap_clone(&dns_data->options, &sbrec_dns->options); +} + dns_data->n_dps = sbrec_dns->n_datapaths; dns_data->dps = xcalloc(dns_data->n_dps, sizeof(uint64_t)); for (size_t i = 0; i < sbrec_dns->n_datapaths; i++) { @@ -2767,6 +2776,7 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) if (d->delete) { shash_delete(&dns_cache, iter); smap_destroy(&d->records); +smap_destroy(&d->options); free(d->dps); free(d); } @@ -2781,6 +2791,7 @@ destroy_dns_cache(void) struct dns_data *d = iter->data; shash_delete(&dns_cache, iter); smap_destroy(&d->records); +smap_destroy(&d->options); free(d->dps); free(d); } @@ -2854,6 +2865,8 @@ dns_build_ptr_answer( free(encoded); } +#define DNS_RCODE_SERVER_REFUSE 0x5 + /* Called with in the pinctrl_handler thread context. */ static void pinctrl_handle_dns_lookup( @@ -2867,6 +2880,7 @@ pinctrl_handle_dns_lookup( enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); struct dp_packet *pkt_out_ptr = NULL; uint32_t success = 0; +bool send_refuse = false; /* Parse result field. */ const struct mf_field *f; @@ -2966,6 +2980,7 @@ pinctrl_handle_dns_lookup( uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata); const char *answer_da
[ovs-dev] [PATCH ovn v2] controller: release container lport when releasing parent port
Currently if the user sets the container parent_port:requested-chassis option after the VIF/CIF is bonded to the chassis, this will migrate the VIF/CIF flows to the new chassis but will still have the container flows installed in the old chassis which can allow unwanted tagged traffic to reach VMS/containers on the old chassis. This patch will resolve the above issue by remove the CIF flows from the old chassis and prevent the CIF from being bonded to a chassis different from the parent port VIF binding chassis. Rreported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2220938 Signed-off-by: Mohammad Heib --- controller/binding.c| 19 +++ controller/physical.c | 9 +++ tests/ovn-controller.at | 53 + 3 files changed, 81 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 8020d052f..0b64a1226 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -1600,6 +1600,22 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, b_lport->lbinding->iface->name, &b_lport->lbinding->iface->header_.uuid); + +struct binding_lport *tmp_b_lport = b_lport; +LIST_FOR_EACH (tmp_b_lport, list_node, + &tmp_b_lport->lbinding->binding_lports) { +/* release children lports of type container if the primary + * binding lport cannot be bind to this chassis. + */ +if (tmp_b_lport->type == LP_CONTAINER) { +if (!release_lport(tmp_b_lport->pb, b_ctx_in->chassis_rec, + !b_ctx_in->ovnsb_idl_txn, + b_ctx_out->tracked_dp_bindings, + b_ctx_out->if_mgr)) { +return false; +} +} +} } if (!lbinding_set || !can_bind) { @@ -1734,6 +1750,9 @@ consider_container_lport(const struct sbrec_port_binding *pb, ovs_assert(parent_b_lport && parent_b_lport->pb); bool can_bind = lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, pb); +/* cannot bind to this chassis if the parent_port cannot be bounded. */ +can_bind &= lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, + parent_b_lport->pb); return consider_vif_lport_(pb, can_bind, b_ctx_in, b_ctx_out, container_b_lport); diff --git a/controller/physical.c b/controller/physical.c index 2338561ec..4e169e35f 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -1573,6 +1573,15 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, nested_container = true; parent_port = lport_lookup_by_name( sbrec_port_binding_by_name, binding->parent_port); + +if (parent_port +&& !lport_can_bind_on_this_chassis(chassis, parent_port)) { +/* Even though there is an ofport for this container + * parent port, it is requested on different chassis ignore + * this container port. + */ +return; +} } } else if (!strcmp(binding->type, "localnet") || !strcmp(binding->type, "l2gateway")) { diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index e72438fbf..8a1904378 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -2700,3 +2700,56 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=40 | grep -q controller], [1] OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller - cleanup VIF/CIF related flows/fields when updating requested-chassis]) +ovn_start + +net_add n1 +sim_add hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int vif1 -- \ +set Interface vif1 external-ids:iface-id=lsp1 \ +ofport-request=8 + +check ovn-nbctl ls-add lsw0 + +check ovn-nbctl lsp-add lsw0 lsp1 +check ovn-nbctl lsp-add lsw0 sw0-port1.1 lsp1 7 + +# wait for the VIF to be claimed to this chassis +wait_row_count Chassis 1 name=hv1 +hv1_uuid=$(fetch_column Chassis _uuid name=hv1) +wait_for_ports_up lsp1 +wait_for_ports_up sw0-port1.1 +wait_column "$hv1_uuid" Port_Binding chassis logical_port=lsp1 +wait_column "$hv1_uuid" Port_Binding chassis logical_port=sw0-port1.1 + +# check that flows is installed +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=100 | grep -c in_port=8], [0],[dnl +1 +]) +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=150|grep dl_vlan=7| g
[ovs-dev] [PATCH ovn] DNS: allow defining records that owned by OVN only
Currently OVN allows users to create DNS records and define domains within these records. These domains can be associated with IPV4 or IPv6 or both, when the user creates a domain with both IPv4 and IPv6 ovn will answer each query for this domain immediately and everything works as expected. But if the user only creates a domain with only IPv4 or IPv6 this will cause the DNS queries respond take longer than the usual since OVN will forward query and user will keep waiting for an answer until someone else replies for this query or timeout occur. The above behavior is a bit problematic if the user knows that this domain is only configured in OVN we should not forward queries for this domain to the outside. This patch adds an option:ovn-owned for the DNS table that can be set to "true" when creating a DNS. When setting this option to "true" all the domains within this table will be treated as local domains only, and queries for domains within this table that don't have an accurate IP will be refused immediately to save the time of waiting for timeout. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1946662 Signed-off-by: Mohammad Heib --- NEWS | 5 controller/pinctrl.c | 47 ++-- northd/northd.c | 11 ovn-nb.ovsschema | 9 -- ovn-nb.xml | 14 ++ ovn-sb.ovsschema | 9 -- ovn-sb.xml | 6 tests/ovn.at | 65 8 files changed, 160 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 425dfe0a8..465649430 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ Post v23.09.0 - + - DNS now have an "options" column for configuration of extra options. + - A new DNS option "ovn-owned" has been added to allow defining domains +that are owned only by ovn, queries for that domain will not be processed +externally. + OVN v23.09.0 - 15 Sep 2023 -- diff --git a/controller/pinctrl.c b/controller/pinctrl.c index ff5a3444c..e1e558595 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -179,6 +179,7 @@ struct pinctrl { struct latch pinctrl_thread_exit; bool mac_binding_can_timestamp; bool fdb_can_timestamp; +bool dns_can_ovn_owned; }; static struct pinctrl pinctrl; @@ -2709,6 +2710,7 @@ struct dns_data { uint64_t *dps; size_t n_dps; struct smap records; +struct smap options; bool delete; }; @@ -2737,6 +2739,7 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) if (!dns_data) { dns_data = xmalloc(sizeof *dns_data); smap_init(&dns_data->records); +smap_init(&dns_data->options); shash_add(&dns_cache, dns_id, dns_data); dns_data->n_dps = 0; dns_data->dps = NULL; @@ -2751,6 +2754,12 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) smap_clone(&dns_data->records, &sbrec_dns->records); } +if (pinctrl.dns_can_ovn_owned +&& !smap_equal(&dns_data->options, &sbrec_dns->options)) { +smap_destroy(&dns_data->options); +smap_clone(&dns_data->options, &sbrec_dns->options); +} + dns_data->n_dps = sbrec_dns->n_datapaths; dns_data->dps = xcalloc(dns_data->n_dps, sizeof(uint64_t)); for (size_t i = 0; i < sbrec_dns->n_datapaths; i++) { @@ -2763,6 +2772,7 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) if (d->delete) { shash_delete(&dns_cache, iter); smap_destroy(&d->records); +smap_destroy(&d->options); free(d->dps); free(d); } @@ -2777,6 +2787,7 @@ destroy_dns_cache(void) struct dns_data *d = iter->data; shash_delete(&dns_cache, iter); smap_destroy(&d->records); +smap_destroy(&d->options); free(d->dps); free(d); } @@ -2850,6 +2861,8 @@ dns_build_ptr_answer( free(encoded); } +#define DNS_RCODE_SERVER_REFUSE 0x5 + /* Called with in the pinctrl_handler thread context. */ static void pinctrl_handle_dns_lookup( @@ -2863,6 +2876,7 @@ pinctrl_handle_dns_lookup( enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); struct dp_packet *pkt_out_ptr = NULL; uint32_t success = 0; +bool send_query_rejection = false; /* Parse result field. */ const struct mf_field *f; @@ -2962,6 +2976,7 @@ pinctrl_handle_dns_lookup( uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata); const char *answer_data = NULL; +bool ovn_owned = false; struct shash_node *iter; SHASH_FOR_EACH (iter, &dns_cache) { struct dns_data *d = iter-&g
[ovs-dev] DNS: allow defining records that owned by OVN only
Currently OVN allows users to create DNS records and define domains within these records. These domains can be associated with IPV4 or IPv6 or both, when the user creates a domain with both IPv4 and IPv6 ovn will answer each query for this domain immediately and everything works as expected. But if the user only creates a domain with only IPv4 or IPv6 this will cause the DNS queries respond take longer than the usual since OVN will forward query and user will keep waiting for an answer until someone else replies for this query or timeout occur. The above behavior is a bit problematic if the user knows that this domain is only configured in OVN we should not forward queries for this domain to the outside. This patch adds an option:ovn-owned for the DNS table that can be set to "true" when creating a DNS. When setting this option to "true" all the domains within this table will be treated as local domains only, and queries for domains within this table that don't have an accurate IP will be refused immediately to save the time of waiting for timeout. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1946662 Signed-off-by: Mohammad Heib --- NEWS | 5 controller/pinctrl.c | 47 ++-- northd/northd.c | 11 ovn-nb.ovsschema | 9 -- ovn-nb.xml | 14 ++ ovn-sb.ovsschema | 9 -- ovn-sb.xml | 6 tests/ovn.at | 65 8 files changed, 160 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 425dfe0a8..465649430 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ Post v23.09.0 - + - DNS now have an "options" column for configuration of extra options. + - A new DNS option "ovn-owned" has been added to allow defining domains +that are owned only by ovn, queries for that domain will not be processed +externally. + OVN v23.09.0 - 15 Sep 2023 -- diff --git a/controller/pinctrl.c b/controller/pinctrl.c index ff5a3444c..e1e558595 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -179,6 +179,7 @@ struct pinctrl { struct latch pinctrl_thread_exit; bool mac_binding_can_timestamp; bool fdb_can_timestamp; +bool dns_can_ovn_owned; }; static struct pinctrl pinctrl; @@ -2709,6 +2710,7 @@ struct dns_data { uint64_t *dps; size_t n_dps; struct smap records; +struct smap options; bool delete; }; @@ -2737,6 +2739,7 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) if (!dns_data) { dns_data = xmalloc(sizeof *dns_data); smap_init(&dns_data->records); +smap_init(&dns_data->options); shash_add(&dns_cache, dns_id, dns_data); dns_data->n_dps = 0; dns_data->dps = NULL; @@ -2751,6 +2754,12 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) smap_clone(&dns_data->records, &sbrec_dns->records); } +if (pinctrl.dns_can_ovn_owned +&& !smap_equal(&dns_data->options, &sbrec_dns->options)) { +smap_destroy(&dns_data->options); +smap_clone(&dns_data->options, &sbrec_dns->options); +} + dns_data->n_dps = sbrec_dns->n_datapaths; dns_data->dps = xcalloc(dns_data->n_dps, sizeof(uint64_t)); for (size_t i = 0; i < sbrec_dns->n_datapaths; i++) { @@ -2763,6 +2772,7 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) if (d->delete) { shash_delete(&dns_cache, iter); smap_destroy(&d->records); +smap_destroy(&d->options); free(d->dps); free(d); } @@ -2777,6 +2787,7 @@ destroy_dns_cache(void) struct dns_data *d = iter->data; shash_delete(&dns_cache, iter); smap_destroy(&d->records); +smap_destroy(&d->options); free(d->dps); free(d); } @@ -2850,6 +2861,8 @@ dns_build_ptr_answer( free(encoded); } +#define DNS_RCODE_SERVER_REFUSE 0x5 + /* Called with in the pinctrl_handler thread context. */ static void pinctrl_handle_dns_lookup( @@ -2863,6 +2876,7 @@ pinctrl_handle_dns_lookup( enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); struct dp_packet *pkt_out_ptr = NULL; uint32_t success = 0; +bool send_query_rejection = false; /* Parse result field. */ const struct mf_field *f; @@ -2962,6 +2976,7 @@ pinctrl_handle_dns_lookup( uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata); const char *answer_data = NULL; +bool ovn_owned = false; struct shash_node *iter; SHASH_FOR_EACH (iter, &dns_cache) { struct dns_data *d = iter-&g
[ovs-dev] [PATCH ovn] controller: release container lport when releasing parent port
Currently if the user sets the container parent_port:requested-chassis option after the VIF/CIF is bonded to the chassis, this will migrate the VIF/CIF flows to the new chassis but will still have the container flows installed in the old chassis which can allow unwanted tagged traffic to reach VMS/containers on the old chassis. This patch will resolve the above issue by remove the CIF flows from the old chassis and prevent the CIF from being bonded to a chassis different from the parent port VIF binding chassis. Rreported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2220938 Signed-off-by: Mohammad Heib --- controller/binding.c| 18 ++ controller/physical.c | 9 +++ tests/ovn-controller.at | 55 + 3 files changed, 82 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index fd08aaafa..2e58fb0cd 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -1599,6 +1599,21 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, b_lport->lbinding->iface->name, &b_lport->lbinding->iface->header_.uuid); + +LIST_FOR_EACH (b_lport, list_node, + &b_lport->lbinding->binding_lports) { +/* release children lports of type container if the primary + * binding lport cannot be bind to this chassis. + */ +if (b_lport->type == LP_CONTAINER) { +if (!release_lport(b_lport->pb, b_ctx_in->chassis_rec, + !b_ctx_in->ovnsb_idl_txn, + b_ctx_out->tracked_dp_bindings, + b_ctx_out->if_mgr)) { +return false; +} +} +} } if (!lbinding_set || !can_bind) { @@ -1733,6 +1748,9 @@ consider_container_lport(const struct sbrec_port_binding *pb, ovs_assert(parent_b_lport && parent_b_lport->pb); bool can_bind = lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, pb); +/* cannot bind to this chassis if the parent_port cannot be bounded. */ +can_bind &= lport_can_bind_on_this_chassis(b_ctx_in->chassis_rec, + parent_b_lport->pb); return consider_vif_lport_(pb, can_bind, b_ctx_in, b_ctx_out, container_b_lport); diff --git a/controller/physical.c b/controller/physical.c index 75257bc85..5a5824f39 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -1573,6 +1573,15 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, nested_container = true; parent_port = lport_lookup_by_name( sbrec_port_binding_by_name, binding->parent_port); + +if (parent_port +&& !lport_can_bind_on_this_chassis(chassis, parent_port)) { +/* Even though there is an ofport for this container + * parent port, it is requested on different chassis ignore + * this container port. + */ +return; +} } } else if (!strcmp(binding->type, "localnet") || !strcmp(binding->type, "l2gateway")) { diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index 4212d601a..65c3aa84b 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -2651,3 +2651,58 @@ OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 | grep -c in_por OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller - cleanup VIF/CIF related flows/fields when updating requested-chassis]) +ovn_start + +net_add n1 +sim_add hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int vif1 -- \ +set Interface vif1 external-ids:iface-id=lsp1 \ +ofport-request=8 + +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-add lsw0 sw0-port1.1 lsp1 7 +check ovn-nbctl lsp-set-addresses sw0-port1.1 "f0:00:00:01:02:07 192.168.2.2" + +# wait for the VIF to be claimed to this chassis +wait_row_count Chassis 1 name=hv1 +hv1_uuid=$(fetch_column Chassis _uuid name=hv1) +wait_for_ports_up lsp1 +wait_for_ports_up sw0-port1.1 +wait_column "$hv1_uuid" Port_Binding chassis logical_port=lsp1 +wait_column "$hv1_uuid" Port_Binding chassis logical_port=sw0-port1.1 + +# check that flows is installed +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=100 | grep -c in_port=8], [0],[dnl +1 +]) +OVS_WA
[ovs-dev] [PATCH ovn] pinctrl: DNS refuse inapplicable AAAA queries
Currently ovn ignores DNS queries that has record in the DNS tables but no ipv6 associated with this record, this will incress the DNS processing time for the custmer since they will keep waiting for reply or a timeout. To improve the DNS processing time this patch will immediately send a DNS reply with DNS RCODE flag set to 0x5 (server refuses to perform the specified operation) and no DNS answers. Reported-at: https://issues.redhat.com/browse/FD-1211 Signed-off-by: Mohammad Heib --- controller/pinctrl.c | 28 +--- tests/ovn.at | 32 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 1884e9f1b..3212900c5 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -2815,6 +2815,7 @@ pinctrl_handle_dns_lookup( enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); struct dp_packet *pkt_out_ptr = NULL; uint32_t success = 0; +bool send__query_rejection = false; /* Parse result field. */ const struct mf_field *f; @@ -2972,6 +2973,18 @@ pinctrl_handle_dns_lookup( ancount++; } } + +/* DNS is configured with a record for this domain with + * an IPv4 only, so instead of ignoring this query, + * we can reply with RCODE = 5 (server refuses) and that + * will speed up the DNS process by not letting the customer + * wait for a timeout. + */ +if (query_type == DNS_QUERY_TYPE_ && !ancount) { +ancount = 1; +send__query_rejection = true; +} + destroy_lport_addresses(&ip_addrs); } @@ -3009,15 +3022,24 @@ pinctrl_handle_dns_lookup( out_dns_header->lo_flag |= 0x80; /* Set the answer RRs. */ -out_dns_header->ancount = htons(ancount); +if (!send__query_rejection) { +out_dns_header->ancount = htons(ancount); +} else { +/* set RCODE = 5 (server refuses). */ +out_dns_header->ancount = 0; +out_dns_header->hi_flag |= 0x5; +ofpbuf_uninit(&dns_answer); +} out_dns_header->arcount = 0; /* Copy the Query section. */ dp_packet_put(&pkt_out, dp_packet_data(pkt_in), dp_packet_size(pkt_in)); /* Copy the answer sections. */ -dp_packet_put(&pkt_out, dns_answer.data, dns_answer.size); -ofpbuf_uninit(&dns_answer); +if (!send__query_rejection) { +dp_packet_put(&pkt_out, dns_answer.data, dns_answer.size); +ofpbuf_uninit(&dns_answer); +} out_udp->udp_len = htons(new_l4_size); out_udp->udp_csum = 0; diff --git a/tests/ovn.at b/tests/ovn.at index c6c5f920f..7b90a991d 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -11290,6 +11290,38 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected +# send query for a server known domain that don't have +# any IPV6 address associated with this domain, and expected +# server refused DNS reply to save the sender time of waiting for timeout. +AS_BOX([Test IPv6 ( records) NO timeout.]) +# Add back the DNS options for ls1-lp1 without ipv6. +ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org +ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org="10.0.0.4" +ovn-sbctl list DNS > dns4 +AT_CAPTURE_FILE([dns4]) +ovn-sbctl dump-flows > sbflows4 +AT_CAPTURE_FILE([sbflows4]) + +set_dns_params vm1_ipv6_only +src_ip=`ip_to_hex 10 0 0 6` +dst_ip=`ip_to_hex 10 0 0 1` +dns_reply=1 +test_dns 2 f002 f0f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data + +# NXT_RESUMEs should be 5. +OVS_WAIT_UNTIL([test 13 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets +# dns hdr with server refuse RCODE +echo "01028125" > expout +#only check for the DNS HDR flags since we are not getting any DNS answer +AT_CHECK([cat 2.packets | cut -c -92 | cut -c 85-], [0], [expout]) + +reset_pcap_file hv1-vif1 hv1/vif1 +reset_pcap_file hv1-vif2 hv1/vif2 +rm -f 1.expected +rm -f 2.expected + OVN_CLEANUP([hv1]) AT_CLEANUP -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn] binding: handle ovs ofport update
Hi Mark, thank you for reviewing my patch is submitted v2 addressing your comments. On 7/28/23 23:16, Mark Michelson wrote: Hi Mohammad, The actual code change looks good, but I have some other minor comments to address. See inline below. On 7/26/23 12:12, Mohammad Heib wrote: Currently when ovs interface ofport is updated after setting external_ids:iface_id, the ovn-controller will see this change but will not do much if it handles this change incrementally. This behavior leads to a mismatch between the ovs openflow flows in table=0 (inaccurate in_port) and the ofport number that the packet was received at which will lead to packets drop in table=0. This patch will resolve the above issue by triggering flows recompute during the I-P processing only if the affected port are associated with lport and has flows that need to be updated. Reported-at: https://issues.redhat.com/browse/FD-3063 Signed-off-by: Mohammad Heib --- controller/binding.c | 35 +++ tests/ovn-controller.at | 39 +++ 2 files changed, 74 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 9aa3fc6c4..d28548d93 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -1514,6 +1514,35 @@ release_lport(const struct sbrec_port_binding *pb, return true; } +/* + * This function will update the tracked_dp_bindings + * whenever an ofport on a specific ovs port. s/specific ovs port/specific ovs port changes/ + * This update will trigger flow recomputation during + * the incremental processing run which updates the local + * flows in_port filed. + * + * This function will trigger flow recomputation only for + * affected local_bindings that have port_binding associated + * with it, otherwise, no flows are installed and we don't + * have to update any in_port field. + */ +static void +handle_ovs_ofport_update(const char *iface_id, + struct binding_ctx_out *b_ctx_out) +{ + struct shash *local_bindings = &b_ctx_out->lbinding_data->bindings; + struct local_binding *lbinding = local_binding_find(local_bindings, + iface_id); + struct binding_lport *b_lport = + local_binding_get_primary_or_localport_lport(lbinding); + + if (b_lport) { + tracked_datapath_lport_add(b_lport->pb, TRACKED_RESOURCE_UPDATED, + b_ctx_out->tracked_dp_bindings); + b_ctx_out->local_lports_changed = true; + } +} I think this logic should move into consider_iface_claim() in binding.c. It is called for all relevant OVS interfaces, and that function also retrieves the local_binding and binding_lport. In addition to saving a bit of computation, putting this change there would also prevent a potential crash, since it is possible that b_lport->pb may be NULL. We have a NULL check already in consider_iface_claim(), so you could insert this new code below that NULL check. + static bool is_lbinding_set(struct local_binding *lbinding) { @@ -2681,6 +2710,12 @@ binding_handle_ovs_interface_changes(struct binding_ctx_in *b_ctx_in, if (!handled) { break; } + + if (!b_ctx_out->local_lports_changed + && ovsrec_interface_is_updated(iface_rec, + OVSREC_INTERFACE_COL_OFPORT)) { + handle_ovs_ofport_update(iface_id, b_ctx_out); + } } } diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index 28c13234c..1461cade6 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -2608,3 +2608,42 @@ AT_CHECK([ovn-sbctl get chassis $chassis_id other_config:unsupported], [1], [ign OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller - ovs iface change ofport]) +AT_KEYWORDS([ovn]) +ovn_start + +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + + +ovn-nbctl ls-add sw0 + +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3 1000::3" + +wait_for_ports_up +ovn-nbctl --wait=hv sync + +OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int table=0 | grep priority=100 | grep in_port=1 | grep "resubmit(,8)" | grep -c n_packets=0`]) A couple of things: * Do we need to grep for the priority, the resubmit action, and "n_packets=0" ? Isn't it enough to just grep for in_port=1 in table 0? * While this syntax works fine, there is an OVS_WAIT_FOR_OUTPUT macro that is more commonly used for this type of test. OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 | grep -c in_port=1], [0],[dnl 1 ] + +# update the ovs interface ofport from
[ovs-dev] [PATCH ovn v2] binding: handle ovs ofport update
Currently when ovs interface ofport is updated after setting external_ids:iface_id, the ovn-controller will see this change but will not do much if it handles this change incrementally. This behavior leads to a mismatch between the ovs openflow flows in table=0 (inaccurate in_port) and the ofport number that the packet was received at which will lead to packets drop in table=0. This patch will resolve the above issue by triggering flows recompute during the I-P processing only if the affected port are associated with lport and has flows that need to be updated. Reported-at: https://issues.redhat.com/browse/FD-3063 Signed-off-by: Mohammad Heib --- controller/binding.c| 15 ++ tests/ovn-controller.at | 45 + 2 files changed, 60 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 9aa3fc6c4..cc4c2b0bb 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -2360,6 +2360,21 @@ consider_iface_claim(const struct ovsrec_interface *iface_rec, /* Get the (updated) b_lport again for the lbinding. */ b_lport = local_binding_get_primary_lport(lbinding); +/* + * Update the tracked_dp_bindings whenever an ofport + * on a specific ovs port changes. + * This update will trigger flow recomputation during + * the incremental processing run which updates the local + * flows in_port filed. + */ +if (b_lport && ovsrec_interface_is_updated(iface_rec, +OVSREC_INTERFACE_COL_OFPORT)) { +tracked_datapath_lport_add(b_lport->pb, TRACKED_RESOURCE_UPDATED, + b_ctx_out->tracked_dp_bindings); +b_ctx_out->local_lports_changed = true; +} + + /* Update the child local_binding's iface (if any children) and try to * claim the container lbindings. */ LIST_FOR_EACH (b_lport, list_node, &lbinding->binding_lports) { diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index e1b6491b3..f2216d245 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -2606,3 +2606,48 @@ AT_CHECK([ovn-sbctl get chassis $chassis_id other_config:unsupported], [1], [ign OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller - ovs iface change ofport]) +AT_KEYWORDS([ovn]) +ovn_start + +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ +options:tx_pcap=hv1/vif1-tx.pcap \ +options:rxq_pcap=hv1/vif1-rx.pcap \ +ofport-request=1 + + +ovn-nbctl ls-add sw0 + +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3 1000::3" + +wait_for_ports_up +ovn-nbctl --wait=hv sync + +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 | grep -c in_port=1], [0],[dnl +1 +]) + +# update the ovs interface ofport from 1 to 24 +check as hv1 ovs-vsctl set Interface hv1-vif1 ofport-request=24 +OVS_WAIT_UNTIL([test x`as hv1 ovs-vsctl get Interface hv1-vif1 ofport` = x24]) + +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 | grep -c in_port=24], [0],[dnl +1 +]) +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 | grep -c in_port=1], [1],[dnl +0 +]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn] binding: handle ovs ofport update
Currently when ovs interface ofport is updated after setting external_ids:iface_id, the ovn-controller will see this change but will not do much if it handles this change incrementally. This behavior leads to a mismatch between the ovs openflow flows in table=0 (inaccurate in_port) and the ofport number that the packet was received at which will lead to packets drop in table=0. This patch will resolve the above issue by triggering flows recompute during the I-P processing only if the affected port are associated with lport and has flows that need to be updated. Reported-at: https://issues.redhat.com/browse/FD-3063 Signed-off-by: Mohammad Heib --- controller/binding.c| 35 +++ tests/ovn-controller.at | 39 +++ 2 files changed, 74 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 9aa3fc6c4..d28548d93 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -1514,6 +1514,35 @@ release_lport(const struct sbrec_port_binding *pb, return true; } +/* + * This function will update the tracked_dp_bindings + * whenever an ofport on a specific ovs port. + * This update will trigger flow recomputation during + * the incremental processing run which updates the local + * flows in_port filed. + * + * This function will trigger flow recomputation only for + * affected local_bindings that have port_binding associated + * with it, otherwise, no flows are installed and we don't + * have to update any in_port field. + */ +static void +handle_ovs_ofport_update(const char *iface_id, + struct binding_ctx_out *b_ctx_out) +{ +struct shash *local_bindings = &b_ctx_out->lbinding_data->bindings; +struct local_binding *lbinding = local_binding_find(local_bindings, +iface_id); +struct binding_lport *b_lport = +local_binding_get_primary_or_localport_lport(lbinding); + +if (b_lport) { +tracked_datapath_lport_add(b_lport->pb, TRACKED_RESOURCE_UPDATED, + b_ctx_out->tracked_dp_bindings); +b_ctx_out->local_lports_changed = true; +} +} + static bool is_lbinding_set(struct local_binding *lbinding) { @@ -2681,6 +2710,12 @@ binding_handle_ovs_interface_changes(struct binding_ctx_in *b_ctx_in, if (!handled) { break; } + +if (!b_ctx_out->local_lports_changed + && ovsrec_interface_is_updated(iface_rec, +OVSREC_INTERFACE_COL_OFPORT)) { +handle_ovs_ofport_update(iface_id, b_ctx_out); +} } } diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index 28c13234c..1461cade6 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -2608,3 +2608,42 @@ AT_CHECK([ovn-sbctl get chassis $chassis_id other_config:unsupported], [1], [ign OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-controller - ovs iface change ofport]) +AT_KEYWORDS([ovn]) +ovn_start + +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ +options:tx_pcap=hv1/vif1-tx.pcap \ +options:rxq_pcap=hv1/vif1-rx.pcap \ +ofport-request=1 + + +ovn-nbctl ls-add sw0 + +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3 1000::3" + +wait_for_ports_up +ovn-nbctl --wait=hv sync + +OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int table=0 | grep priority=100 | grep in_port=1 | grep "resubmit(,8)" | grep -c n_packets=0`]) + +# update the ovs interface ofport from 1 to 24 +check as hv1 ovs-vsctl set Interface hv1-vif1 ofport-request=24 +OVS_WAIT_UNTIL([test x`as hv1 ovs-vsctl get Interface hv1-vif1 ofport` = x24]) + +OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int table=0 | grep priority=100 | grep in_port=24 | grep "resubmit(,8)" | grep -c n_packets=0`]) +OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int table=0 | grep priority=100 | grep in_port=1 | grep "resubmit(,8)" | grep -c n_packets=0`]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) -- 2.34.3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn v3] binding.c: update ld->peers when lsp type updated
Hi Mark, Thank you for reviewing the patch. actually, the test here is less interested in the type update but more in the LSP deletion from the ld->peer_ports list i don't have a way to see if the ld->n_peer_ports updated properly from the tests units when we change the port type, but i know that if something wrong happens in the ovn-controller and ld->peer_ports keeps pointing to the deleted LSP( which is what this patch comes to fix ) the command* "check ovn-nbctl lrp-del lrp"* will cause some invalid memory access and that will lead to a core dump in the ovn-controller and then the test case will fail with dump in the ovn-controller logs. i know it is a bad way to test it like that but as i mentioned i don't have a way to see the content of ld->peer_ports from the test :(. see comments in the tests below. On Thu, Aug 18, 2022 at 9:18 PM Mark Michelson wrote: > Hi Mohammad. The code changes look good, but I'm a bit confused about > what the test case is intending to prove. It updates the type of the > LSP, but there is no check to ensure that the change was successful, as > far as I can tell. > > > On 8/16/22 06:56, Mohammad Heib wrote: > > The local_datapath->peer_ports list contains peers pointers > > to lsp<-->lrp ports that are supposed to be router end ports, > > those pointers are added and deleted to the local_datapath->peer_ports > > when logical switch port of type router are added or deleted from the > database. > > > > The deletion and creation of those ports are handled very well when the > LSP type > > is a router, but if in any case, the user has changed the LSP type from > router > > port to any other LSP type the ld->peer_ports will keep pointing to this > port > > and if it was deleted it will keep pointing to invalid memory regions > and that > > could lead to invalid memory access in the ovn-controller. > > > > To solve the above issue this patch will update the > local_dataoath->peer_ports > > whenever a lport is updated. > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078 > > Co-authored-by: Xavier Simonart > > Signed-off-by: Mohammad Heib > > Signed-off-by: Xavier Simonart > > Signed-off-by: Mohammad Heib > > --- > > controller/binding.c | 37 + > > tests/ovn.at | 37 + > > 2 files changed, 74 insertions(+) > > > > diff --git a/controller/binding.c b/controller/binding.c > > index 9f5393a92..1221419a9 100644 > > --- a/controller/binding.c > > +++ b/controller/binding.c > > @@ -566,6 +566,39 @@ remove_related_lport(const struct > sbrec_port_binding *pb, > > } > > } > > > > +/* > > + * Update local_datapath peers when port type changed > > + * and remove irrelevant ports from this list. > > + */ > > +static void > > +update_ld_peers(const struct sbrec_port_binding *pb, > > + struct hmap *local_datapaths) > > +{ > > +struct local_datapath *ld = > > +get_local_datapath(local_datapaths, pb->datapath->tunnel_key); > > + > > +if (!ld) { > > +return; > > +} > > + > > +/* > > + * This will handle cases where the pb type was explicitly > > + * changed from router type to any other port type and will > > + * remove it from the ld peers list. > > + */ > > +enum en_lport_type type = get_lport_type(pb); > > +int num_peers = ld->n_peer_ports; > > +if (type != LP_PATCH) { > > +remove_local_datapath_peer_port(pb, ld, local_datapaths); > > +if (num_peers != ld->n_peer_ports) { > > +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, > 5); > > +VLOG_DBG_RL(&rl, > > +"removing lport %s from the ld peers list", > > +pb->logical_port); > > +} > > +} > > +} > > + > > static void > > delete_active_pb_ras_pd(const struct sbrec_port_binding *pb, > > struct shash *ras_pd_map) > > @@ -2585,6 +2618,10 @@ handle_updated_port(struct binding_ctx_in > *b_ctx_in, > > return true; > > } > > > > +if (sbrec_port_binding_is_updated(pb, SBREC_PORT_BINDING_COL_TYPE)) > { > > +update_ld_peers(pb, b_ctx_out->local_datapaths); > > +} > > + > > update_active_pb_ras_pd(pb, b_ctx_out->local_active_ports_ipv6_pd, > > "ipv6
[ovs-dev] [PATCH ovn v3] binding.c: update ld->peers when lsp type updated
The local_datapath->peer_ports list contains peers pointers to lsp<-->lrp ports that are supposed to be router end ports, those pointers are added and deleted to the local_datapath->peer_ports when logical switch port of type router are added or deleted from the database. The deletion and creation of those ports are handled very well when the LSP type is a router, but if in any case, the user has changed the LSP type from router port to any other LSP type the ld->peer_ports will keep pointing to this port and if it was deleted it will keep pointing to invalid memory regions and that could lead to invalid memory access in the ovn-controller. To solve the above issue this patch will update the local_dataoath->peer_ports whenever a lport is updated. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078 Co-authored-by: Xavier Simonart Signed-off-by: Mohammad Heib Signed-off-by: Xavier Simonart Signed-off-by: Mohammad Heib --- controller/binding.c | 37 + tests/ovn.at | 37 + 2 files changed, 74 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 9f5393a92..1221419a9 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -566,6 +566,39 @@ remove_related_lport(const struct sbrec_port_binding *pb, } } +/* + * Update local_datapath peers when port type changed + * and remove irrelevant ports from this list. + */ +static void +update_ld_peers(const struct sbrec_port_binding *pb, + struct hmap *local_datapaths) +{ +struct local_datapath *ld = +get_local_datapath(local_datapaths, pb->datapath->tunnel_key); + +if (!ld) { +return; +} + +/* + * This will handle cases where the pb type was explicitly + * changed from router type to any other port type and will + * remove it from the ld peers list. + */ +enum en_lport_type type = get_lport_type(pb); +int num_peers = ld->n_peer_ports; +if (type != LP_PATCH) { +remove_local_datapath_peer_port(pb, ld, local_datapaths); +if (num_peers != ld->n_peer_ports) { +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); +VLOG_DBG_RL(&rl, +"removing lport %s from the ld peers list", +pb->logical_port); +} +} +} + static void delete_active_pb_ras_pd(const struct sbrec_port_binding *pb, struct shash *ras_pd_map) @@ -2585,6 +2618,10 @@ handle_updated_port(struct binding_ctx_in *b_ctx_in, return true; } +if (sbrec_port_binding_is_updated(pb, SBREC_PORT_BINDING_COL_TYPE)) { +update_ld_peers(pb, b_ctx_out->local_datapaths); +} + update_active_pb_ras_pd(pb, b_ctx_out->local_active_ports_ipv6_pd, "ipv6_prefix_delegation"); diff --git a/tests/ovn.at b/tests/ovn.at index c8cc8cde4..79eda21d3 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -32404,3 +32404,40 @@ AT_CHECK([test $(ovn-sbctl list fdb | grep -c "00:00:00:00:10:30") = 0]) OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([router port type update and then remove]) +ovn_start +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ +options:tx_pcap=hv1/vif1-tx.pcap \ +options:rxq_pcap=hv1/vif1-rx.pcap \ +ofport-request=1 + +check ovn-nbctl ls-add sw0 +check ovn-nbctl lr-add ro0 +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-add sw0 lsp +check ovn-nbctl lsp-set-type lsp router +check ovn-nbctl lsp-set-options lsp router-port=lrp +check ovn-nbctl lsp-set-addresses lsp 00:00:00:00:00:1 +check ovn-nbctl lrp-add ro0 lrp 00:00:00:00:00:1 aef0:0:0:0:0:0:0:1/64 +check ovn-nbctl set Logical_Router_Port lrp ipv6_ra_configs:send_periodic=true \ +-- set Logical_Router_Port lrp ipv6_ra_configs:address_mode=slaac \ +-- set Logical_Router_Port lrp ipv6_ra_configs:mtu=1280 \ +-- set Logical_Router_Port lrp ipv6_ra_configs:max_interval=2 \ +-- set Logical_Router_Port lrp ipv6_ra_configs:min_interval=1 +check ovn-nbctl lsp-set-type lsp localnet +check ovn-nbctl --wait=hv sync +check ovn-nbctl lsp-del lsp +check ovn-nbctl lrp-del lrp +check ovn-nbctl --wait=hv sync +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) -- 2.34.1 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn v3] ci: Add missing tests after switch to parallel jobs
Acked-by: Mohammad Heib thanks, On Wed, Aug 10, 2022 at 3:02 PM Ales Musil wrote: > After switch to parallel jobs some tests > were missing due to way how filtering in autotest > works. Add additional jobs that filter the !ovn-northd > which is currently always present when the test calls > OVN_FOR_EACH_NORTHD. > > Fixes: d093905 ("OVN-CI: ovn unit tests run in parallel jobs.") > Signed-off-by: Ales Musil > --- > v3: Switch to !ovn-northd after suggestion from Mohammad. > --- > .github/workflows/test.yml | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml > index afa984345..7a59cd478 100644 > --- a/.github/workflows/test.yml > +++ b/.github/workflows/test.yml > @@ -40,22 +40,27 @@ jobs: > - { compiler: gcc, testsuite: test, testsuite_kw: > "parallelization=yes,ovn_monitor_all=no" } > - { compiler: gcc, testsuite: test, testsuite_kw: > "parallelization=no,ovn_monitor_all=yes" } > - { compiler: gcc, testsuite: test, testsuite_kw: > "parallelization=no,ovn_monitor_all=no" } > +- { compiler: gcc, testsuite: test, testsuite_kw: "!ovn-northd" } > - { compiler: clang, testsuite: test, sanitizers: sanitizers, > testsuite_kw: "parallelization=yes,ovn_monitor_all=yes" } > - { compiler: clang, testsuite: test, sanitizers: sanitizers, > testsuite_kw: "parallelization=yes,ovn_monitor_all=no" } > - { compiler: clang, testsuite: test, sanitizers: sanitizers, > testsuite_kw: "parallelization=no,ovn_monitor_all=yes" } > - { compiler: clang, testsuite: test, sanitizers: sanitizers, > testsuite_kw: "parallelization=no,ovn_monitor_all=no" } > +- { compiler: clang, testsuite: test, sanitizers: sanitizers, > testsuite_kw: "!ovn-northd" } > - { compiler: gcc, testsuite: test, libs: -ljemalloc, > testsuite_kw: "parallelization=yes,ovn_monitor_all=yes" } > - { compiler: gcc, testsuite: test, libs: -ljemalloc, > testsuite_kw: "parallelization=yes,ovn_monitor_all=no" } > - { compiler: gcc, testsuite: test, libs: -ljemalloc, > testsuite_kw: "parallelization=no,ovn_monitor_all=yes" } > - { compiler: gcc, testsuite: test, libs: -ljemalloc, > testsuite_kw: "parallelization=no,ovn_monitor_all=no" } > +- { compiler: gcc, testsuite: test, libs: -ljemalloc, > testsuite_kw: "!ovn-northd" } > - { compiler: clang, testsuite: test, libs: -ljemalloc, > testsuite_kw: "parallelization=yes,ovn_monitor_all=yes" } > - { compiler: clang, testsuite: test, libs: -ljemalloc, > testsuite_kw: "parallelization=yes,ovn_monitor_all=no" } > - { compiler: clang, testsuite: test, libs: -ljemalloc, > testsuite_kw: "parallelization=no,ovn_monitor_all=yes" } > - { compiler: clang, testsuite: test, libs: -ljemalloc, > testsuite_kw: "parallelization=no,ovn_monitor_all=no" } > +- { compiler: clang, testsuite: test, libs: -ljemalloc, > testsuite_kw: "!ovn-northd" } > - { compiler: gcc, testsuite: system-test, testsuite_kw: > "parallelization=yes,ovn_monitor_all=yes" } > - { compiler: gcc, testsuite: system-test, testsuite_kw: > "parallelization=yes,ovn_monitor_all=no" } > - { compiler: gcc, testsuite: system-test, testsuite_kw: > "parallelization=no,ovn_monitor_all=yes" } > - { compiler: gcc, testsuite: system-test, testsuite_kw: > "parallelization=no,ovn_monitor_all=no" } > +- { compiler: gcc, testsuite: system-test, testsuite_kw: > "!ovn-northd" } > - { compiler: gcc, m32: m32, opts: --disable-ssl} > > steps: > -- > 2.37.1 > > ___ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn]OVN-CI: ovn unit tests run in parallel jobs.
Ovn unit tests supported matrix size has been increased after adding support to monitor_all and northd_parallelization options recently, and that increased the execution time of the ovn-ci jobs. This patch aims to reduce the execution time of those jobs by splitting them into smaller jobs that runs in parallel and each one will execute a subset of unit test. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2114862 Signed-off-by: Mohammad Heib --- .ci/linux-build.sh | 9 +++-- .github/workflows/test.yml | 26 +- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh index dc32564fa..2b0782aea 100755 --- a/.ci/linux-build.sh +++ b/.ci/linux-build.sh @@ -47,10 +47,15 @@ else fi if [ "$TESTSUITE" ]; then +TESTSUITEFLAGS="" +if [[ ! -z $TESTSUITE_KW ]]; then +TESTSUITEFLAGS="-k $TESTSUITE_KW" +fi + if [ "$TESTSUITE" = "system-test" ]; then configure_ovn $OPTS make -j4 || { cat config.log; exit 1; } -if ! sudo make -j4 check-kernel RECHECK=yes; then +if ! sudo make -j4 check-kernel TESTSUITEFLAGS="$TESTSUITEFLAGS" RECHECK=yes; then # system-kmod-testsuite.log is necessary for debugging. cat tests/system-kmod-testsuite.log exit 1 @@ -62,7 +67,7 @@ if [ "$TESTSUITE" ]; then export DISTCHECK_CONFIGURE_FLAGS="$OPTS" if ! make distcheck CFLAGS="${COMMON_CFLAGS} ${OVN_CFLAGS}" -j4 \ -TESTSUITEFLAGS="-j4" RECHECK=yes +TESTSUITEFLAGS="$TESTSUITEFLAGS -j4" RECHECK=yes then # testsuite.log is necessary for debugging. cat */_build/sub/tests/testsuite.log diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3b7283229..83d7c2386 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,6 +24,7 @@ jobs: M32: ${{ matrix.cfg.m32 }} OPTS:${{ matrix.cfg.opts }} TESTSUITE: ${{ matrix.cfg.testsuite }} + TESTSUITE_KW: ${{ matrix.cfg.testsuite_kw }} SANITIZERS: ${{ matrix.cfg.sanitizers }} name: linux ${{ join(matrix.cfg.*, ' ') }} @@ -35,11 +36,26 @@ jobs: cfg: - { compiler: gcc, opts: --disable-ssl } - { compiler: clang, opts: --disable-ssl } -- { compiler: gcc, testsuite: test } -- { compiler: gcc, testsuite: system-test } -- { compiler: clang, testsuite: test, sanitizers: sanitizers } -- { compiler: gcc, testsuite: test, libs: -ljemalloc } -- { compiler: clang, testsuite: test, libs: -ljemalloc } +- { compiler: gcc, testsuite: test, testsuite_kw: "parallelization=yes,ovn_monitor_all=yes" } +- { compiler: gcc, testsuite: test, testsuite_kw: "parallelization=yes,ovn_monitor_all=no" } +- { compiler: gcc, testsuite: test, testsuite_kw: "parallelization=no,ovn_monitor_all=yes" } +- { compiler: gcc, testsuite: test, testsuite_kw: "parallelization=no,ovn_monitor_all=no" } +- { compiler: clang, testsuite: test, sanitizers: sanitizers, testsuite_kw: "parallelization=yes,ovn_monitor_all=yes" } +- { compiler: clang, testsuite: test, sanitizers: sanitizers, testsuite_kw: "parallelization=yes,ovn_monitor_all=no" } +- { compiler: clang, testsuite: test, sanitizers: sanitizers, testsuite_kw: "parallelization=no,ovn_monitor_all=yes" } +- { compiler: clang, testsuite: test, sanitizers: sanitizers, testsuite_kw: "parallelization=no,ovn_monitor_all=no" } +- { compiler: gcc, testsuite: test, libs: -ljemalloc, testsuite_kw: "parallelization=yes,ovn_monitor_all=yes" } +- { compiler: gcc, testsuite: test, libs: -ljemalloc, testsuite_kw: "parallelization=yes,ovn_monitor_all=no" } +- { compiler: gcc, testsuite: test, libs: -ljemalloc, testsuite_kw: "parallelization=no,ovn_monitor_all=yes" } +- { compiler: gcc, testsuite: test, libs: -ljemalloc, testsuite_kw: "parallelization=no,ovn_monitor_all=no" } +- { compiler: clang, testsuite: test, libs: -ljemalloc, testsuite_kw: "parallelization=yes,ovn_monitor_all=yes" } +- { compiler: clang, testsuite: test, libs: -ljemalloc, testsuite_kw: "parallelization=yes,ovn_monitor_all=no" } +- { compiler: clang, testsuite: test, libs: -ljemalloc, testsuite_kw: "parallelization=no,ovn_monitor_all=yes" } +- { compiler: clang, testsuite: test, libs: -ljemalloc, testsuite_kw: "parallelization=no,ovn_monitor_all=no" } +- { compiler: gcc, testsuite: system-test, testsuite_kw: "parallelization=yes,ovn_monitor_all=yes" } +- { com
[ovs-dev] [PATCH ovn v2] binding.c: update ld->peers when lsp type updated
The local_datapath->peer_ports list contains peers pointers to lsp<-->lrp ports that are supposed to be router end ports, those pointers are added and deleted to the local_datapath->peer_ports when logical switch port of type router are added or deleted from the database. The deletion and creation of those ports are handled very well when the LSP type is a router, but if in any case, the user has changed the LSP type from router port to any other LSP type the ld->peer_ports will keep pointing to this port and if it was deleted it will keep pointing to invalid memory regions and that could lead to invalid memory access in the ovn-controller. To solve the above issue this patch will update the local_dataoath->peer_ports whenever a lport is updated. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078 Co-authored-by: Xavier Simonart Signed-off-by: Mohammad Heib Signed-off-by: Xavier Simonart --- controller/binding.c | 33 + tests/ovn.at | 33 + 2 files changed, 66 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 19b28369f..3bd8f2ada 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -505,6 +505,38 @@ remove_related_lport(const struct sbrec_port_binding *pb, } } +/* + * Update local_datapath peers when port type changed + * and remove irrelevant ports from this list. + */ +static void +update_ld_peers(const struct sbrec_port_binding *pb, + struct hmap *local_datapaths) +{ +struct local_datapath *ld = get_local_datapath( +local_datapaths, pb->datapath->tunnel_key); +if (!ld) { +return; +} + +/* + * This will handle cases where the pb type was explicitly + * changed from router type to any other port type and will + * remove it from the ld peers list. + */ +enum en_lport_type type = get_lport_type(pb); +int num_peers = ld->n_peer_ports; +if (type != LP_PATCH) { +remove_local_datapath_peer_port(pb, ld, local_datapaths); +if (num_peers != ld->n_peer_ports) { +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); +VLOG_DBG_RL(&rl, +"removing lport %s from the ld peers list", +pb->logical_port); +} +} +} + static void delete_active_pb_ras_pd(const struct sbrec_port_binding *pb, struct shash *ras_pd_map) @@ -2612,6 +2644,7 @@ delete_done: continue; } +update_ld_peers(pb, b_ctx_out->local_datapaths); update_active_pb_ras_pd(pb, b_ctx_out->local_active_ports_ipv6_pd, "ipv6_prefix_delegation"); diff --git a/tests/ovn.at b/tests/ovn.at index 3ba6ced4e..54673e9ec 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -32349,3 +32349,36 @@ AT_CHECK([test $(ovn-sbctl list fdb | grep -c "00:00:00:00:10:30") = 0]) OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([router port type update and then remove]) +ovn_start +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ +options:tx_pcap=hv1/vif1-tx.pcap \ +options:rxq_pcap=hv1/vif1-rx.pcap \ +ofport-request=1 + +check ovn-nbctl ls-add sw0 +check ovn-nbctl lr-add ro0 +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-add sw0 lsp +check ovn-nbctl lsp-set-type lsp router +check ovn-nbctl lsp-set-options lsp router-port=lrp +check ovn-nbctl lsp-set-addresses lsp 00:00:00:00:00:1 +check ovn-nbctl lrp-add ro0 lrp 00:00:00:00:00:1 aef0:0:0:0:0:0:0:1/64 +check ovn-nbctl set Logical_Router_Port lrp ipv6_ra_configs:send_periodic=true -- set Logical_Router_Port lrp ipv6_ra_configs:address_mode=slaac -- set Logical_Router_Port lrp ipv6_ra_configs:mtu=1280 -- set Logical_Router_Port lrp ipv6_ra_configs:max_interval=2 -- set Logical_Router_Port lrp ipv6_ra_configs:min_interval=1 +check ovn-nbctl lsp-set-type lsp localnet +check ovn-nbctl --wait=hv sync +check ovn-nbctl lsp-del lsp +check ovn-nbctl lrp-del lrp +check ovn-nbctl --wait=hv sync +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) -- 2.34.1 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] binding.c: update ld->peers when lsp type updated
The local_datapath->peer_ports list contains peers pointers to lsp<-->lrp ports that are supposed to be router end ports, those pointers are added and deleted to the local_datapath->peer_ports when logical switch port of type router are added or deleted from the database. The deletion and creation of those ports are handled very well when the LSP type is a router, but if in any case, the user has changed the LSP type from router port to any other LSP type the ld->peer_ports will keep pointing to this port and if it was deleted it will keep pointing to invalid memory regions and that could lead to invalid memory access in the ovn-controller. To solve the above issue this patch will update the local_dataoath->peer_ports whenever a lport is updated. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078 Co-authored-by: Xavier Simonart Signed-off-by: Mohammad Heib Signed-off-by: Xavier Simonart --- controller/binding.c | 33 + tests/ovn.at | 33 + 2 files changed, 66 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 19b28369f..3bd8f2ada 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -505,6 +505,38 @@ remove_related_lport(const struct sbrec_port_binding *pb, } } +/* + * Update local_datapath peers when port type changed + * and remove irrelevant ports from this list. + */ +static void +update_ld_peers(const struct sbrec_port_binding *pb, + struct hmap *local_datapaths) +{ +struct local_datapath *ld = get_local_datapath( +local_datapaths, pb->datapath->tunnel_key); +if (!ld) { +return; +} + +/* + * This will handle cases where the pb type was explicitly + * changed from router type to any other port type and will + * remove it from the ld peers list. + */ +enum en_lport_type type = get_lport_type(pb); +int num_peers = ld->n_peer_ports; +if (type != LP_PATCH) { +remove_local_datapath_peer_port(pb, ld, local_datapaths); +if (num_peers != ld->n_peer_ports) { +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); +VLOG_DBG_RL(&rl, +"removing lport %s from the ld peers list", +pb->logical_port); +} +} +} + static void delete_active_pb_ras_pd(const struct sbrec_port_binding *pb, struct shash *ras_pd_map) @@ -2612,6 +2644,7 @@ delete_done: continue; } +update_ld_peers(pb, b_ctx_out->local_datapaths); update_active_pb_ras_pd(pb, b_ctx_out->local_active_ports_ipv6_pd, "ipv6_prefix_delegation"); diff --git a/tests/ovn.at b/tests/ovn.at index 3ba6ced4e..54673e9ec 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -32349,3 +32349,36 @@ AT_CHECK([test $(ovn-sbctl list fdb | grep -c "00:00:00:00:10:30") = 0]) OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([router port type update and then remove]) +ovn_start +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ +set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ +options:tx_pcap=hv1/vif1-tx.pcap \ +options:rxq_pcap=hv1/vif1-rx.pcap \ +ofport-request=1 + +check ovn-nbctl ls-add sw0 +check ovn-nbctl lr-add ro0 +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-add sw0 lsp +check ovn-nbctl lsp-set-type lsp router +check ovn-nbctl lsp-set-options lsp router-port=lrp +check ovn-nbctl lsp-set-addresses lsp 00:00:00:00:00:1 +check ovn-nbctl lrp-add ro0 lrp 00:00:00:00:00:1 aef0:0:0:0:0:0:0:1/64 +check ovn-nbctl set Logical_Router_Port lrp ipv6_ra_configs:send_periodic=true -- set Logical_Router_Port lrp ipv6_ra_configs:address_mode=slaac -- set Logical_Router_Port lrp ipv6_ra_configs:mtu=1280 -- set Logical_Router_Port lrp ipv6_ra_configs:max_interval=2 -- set Logical_Router_Port lrp ipv6_ra_configs:min_interval=1 +check ovn-nbctl lsp-set-type lsp localnet +check ovn-nbctl --wait=hv sync +check ovn-nbctl lsp-del lsp +check ovn-nbctl lrp-del lrp +check ovn-nbctl --wait=hv sync +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) -- 2.34.1 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn] CI-Actions: define matrix as a list
Defining the matrix as a list will make it more readable and easy to extend also users can exclude and add new cases without using include, exclude just add a new combination to the list. Signed-off-by: Mohammad Heib --- .github/workflows/test.yml | 55 ++ 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 49c20f589..3b7283229 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,43 +19,28 @@ jobs: libssl-dev llvm-dev libelf-dev libnuma-dev libpcap-dev \ selinux-policy-dev ncat python3-scapy isc-dhcp-server m32_dependecies: gcc-multilib - CC: ${{ matrix.compiler }} - LIBS:${{ matrix.libs }} - M32: ${{ matrix.m32 }} - OPTS:${{ matrix.opts }} - TESTSUITE: ${{ matrix.testsuite }} - SANITIZERS: ${{ matrix.sanitizers }} - -name: linux ${{ join(matrix.*, ' ') }} + CC: ${{ matrix.cfg.compiler }} + LIBS:${{ matrix.cfg.libs }} + M32: ${{ matrix.cfg.m32 }} + OPTS:${{ matrix.cfg.opts }} + TESTSUITE: ${{ matrix.cfg.testsuite }} + SANITIZERS: ${{ matrix.cfg.sanitizers }} + +name: linux ${{ join(matrix.cfg.*, ' ') }} runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: -include: - - compiler: gcc -opts: --disable-ssl - - compiler: clang -opts: --disable-ssl - - - compiler: gcc -testsuite:test - - compiler: gcc -testsuite:system-test - - compiler: clang -testsuite:test -sanitizers: sanitizers - - - compiler: gcc -testsuite:test -libs: -ljemalloc - - compiler: clang -testsuite:test -libs: -ljemalloc - - - compiler: gcc -m32: m32 -opts: --disable-ssl +cfg: +- { compiler: gcc, opts: --disable-ssl } +- { compiler: clang, opts: --disable-ssl } +- { compiler: gcc, testsuite: test } +- { compiler: gcc, testsuite: system-test } +- { compiler: clang, testsuite: test, sanitizers: sanitizers } +- { compiler: gcc, testsuite: test, libs: -ljemalloc } +- { compiler: clang, testsuite: test, libs: -ljemalloc } +- { compiler: gcc, m32: m32, opts: --disable-ssl} steps: - name: checkout @@ -89,11 +74,11 @@ jobs: run: sudo apt install -y ${{ env.dependencies }} - name: install libunbound libunwind - if: matrix.m32 == '' + if: matrix.cfg.m32 == '' run: sudo apt install -y libunbound-dev libunwind-dev - name: install 32-bit dependencies - if: matrix.m32 != '' + if: matrix.cfg.m32 != '' run: sudo apt install -y ${{ env.m32_dependecies }} - name: update PATH @@ -131,7 +116,7 @@ jobs: if: failure() || cancelled() uses: actions/upload-artifact@v2 with: -name: logs-linux-${{ join(matrix.*, '-') }} +name: logs-linux-${{ join(matrix.cfg.*, '-') }} path: logs.tgz build-osx: -- 2.34.1 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v2] northd: handle virtual lport type update
ovn-northd re-create sbrec row for lport of type virtual when the type explicitly updated in NBDB. This approach was applied to handle container lport type updates and avoid handling issues in the ovn-controller, this patch expanded that approach to handle lport of type virtual in the same way. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2099288 Fixes: cd3b685043fa (northd: handle container lport type update) Signed-off-by: Mohammad Heib Acked-by: Dumitru Ceara --- northd/northd.c | 31 ++- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/northd/northd.c b/northd/northd.c index d31cb1688..5ce352666 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -1856,9 +1856,9 @@ localnet_can_learn_mac(const struct nbrec_logical_switch_port *nbsp) static bool lsp_is_type_changed(const struct sbrec_port_binding *sb, const struct nbrec_logical_switch_port *nbsp, -bool *is_old_container_lport) +bool *update_sbrec) { -*is_old_container_lport = false; +*update_sbrec = false; if (!sb || !nbsp) { return false; } @@ -1870,13 +1870,19 @@ lsp_is_type_changed(const struct sbrec_port_binding *sb, */ if ((!sb->parent_port && nbsp->parent_name) || (sb->parent_port && !nbsp->parent_name)) { -*is_old_container_lport = true; +*update_sbrec = true; return true; } else { return false; } } +/* Cover cases where port changed to/from virtual port */ +if (!strcmp(sb->type, "virtual") || +!strcmp(nbsp->type, "virtual")) { +*update_sbrec = true; +} + /* Both lports are not "VIF's" it is safe to use strcmp. */ if (sb->type[0] && nbsp->type[0]) { return strcmp(sb->type, nbsp->type); @@ -2598,19 +2604,18 @@ join_logical_ports(struct northd_input *input_data, *created one and recompute everything that is needed *for this lport. * - * This change will affect container lport type changes - * only for now, this change is needed in container - * lport cases to avoid port type conflicts in the - * ovn-controller when the user clears the parent_port - * field in the container lport. + * This change will affect container/virtual lport type + * changes only for now, this change is needed in + * contaier/virtual lport cases to avoid port type + * conflicts in the ovn-controller when the user clears + * the parent_port field in the container lport or updated + * the lport type. * - * This approach can be applied to all other lport types - * changes by removing the is_old_container_lport. */ -bool is_old_container_lport = false; +bool update_sbrec = false; if (op->sb && lsp_is_type_changed(op->sb, nbsp, - &is_old_container_lport) - && is_old_container_lport) { + &update_sbrec) + && update_sbrec) { ovs_list_remove(&op->list); sbrec_port_binding_delete(op->sb); ovn_port_destroy(ports, op); -- 2.34.1 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev