Hi Lei, No it is not possible to include this in 26.03. The soft freeze date for new features in 26.03 was January 23. Any new features had to be submitted and receive review feedback before that date. At this point, we have also created the 26.03 branch in github, so we are only considering bugfixes for that branch. This will be a candidate for 26.09, though.
On Sat, Feb 21, 2026 at 11:00 AM Lei Huang <[email protected]> wrote: > > Hi Mark, is it possible to include this patch in v26.03? - Lei > > > On Sat, Feb 21, 2026 at 3:50 AM Lei Huang <[email protected]> wrote: > > > > Use requested-encap-ip (with requested-chassis) to set Port_Binding.encap, > > clear on removal, and prefer geneve when both types exist. Add a northd > > test and document the ovn-k8s interconnect use case. > > > > CC: Han Zhou <[email protected]> > > Signed-off-by: Lei Huang <[email protected]> > > --- > > NEWS | 6 +-- > > northd/en-northd.c | 4 ++ > > northd/inc-proc-northd.c | 8 ++++ > > northd/northd.c | 81 +++++++++++++++++++++++++++++--- > > northd/northd.h | 1 + > > ovn-nb.xml | 18 +++++++ > > tests/ovn-inc-proc-graph-dump.at | 2 + > > tests/ovn-northd.at | 71 ++++++++++++++++++++++++++++ > > 8 files changed, 181 insertions(+), 10 deletions(-) > > > > diff --git a/NEWS b/NEWS > > index ef7b4210b..5a7d2347d 100644 > > --- a/NEWS > > +++ b/NEWS > > @@ -1,8 +1,8 @@ > > Post v26.03.0 > > ------------- > > - > > -OVN v26.03.0 - xxx xx xxxx > > --------------------------- > > + - Added LSP/LRP option "requested-encap-ip" to let CMS request a > > specific > > + SB Port_Binding encap IP (e.g., for remote transit ports in ovn-k8s > > + interconnect mode). > > - Added DNS query statistics tracking in ovn-controller using OVS > > coverage > > counters. Statistics can be queried using "ovn-appctl -t > > ovn-controller > > coverage/read-counter <counter_name>" or "coverage/show". Tracked > > metrics > > diff --git a/northd/en-northd.c b/northd/en-northd.c > > index a828f9a5f..f4107fbee 100644 > > --- a/northd/en-northd.c > > +++ b/northd/en-northd.c > > @@ -51,6 +51,10 @@ northd_get_input_data(struct engine_node *node, > > engine_ovsdb_node_get_index( > > engine_get_input("SB_chassis", node), > > "sbrec_chassis_by_hostname"); > > + input_data->sbrec_encap_by_chassis_ip = > > + engine_ovsdb_node_get_index( > > + engine_get_input("SB_encap", node), > > + "sbrec_encap_by_chassis_ip"); > > input_data->sbrec_ha_chassis_grp_by_name = > > engine_ovsdb_node_get_index( > > engine_get_input("SB_ha_chassis_group", node), > > diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c > > index b79272324..56409ff22 100644 > > --- a/northd/inc-proc-northd.c > > +++ b/northd/inc-proc-northd.c > > @@ -97,6 +97,7 @@ static unixctl_cb_func chassis_features_list; > > #define SB_NODES \ > > SB_NODE(sb_global) \ > > SB_NODE(chassis) \ > > + SB_NODE(encap) \ > > SB_NODE(address_set) \ > > SB_NODE(port_group) \ > > SB_NODE(logical_flow) \ > > @@ -261,6 +262,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, > > NULL); > > > > engine_add_input(&en_northd, &en_sb_chassis, NULL); > > + engine_add_input(&en_northd, &en_sb_encap, NULL); > > engine_add_input(&en_northd, &en_sb_mirror, NULL); > > engine_add_input(&en_northd, &en_sb_meter, NULL); > > engine_add_input(&en_northd, &en_sb_dns, NULL); > > @@ -514,6 +516,9 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, > > ip_mcast_index_create(sb->idl); > > struct ovsdb_idl_index *sbrec_chassis_by_hostname = > > chassis_hostname_index_create(sb->idl); > > + struct ovsdb_idl_index *sbrec_encap_by_chassis_ip = > > + ovsdb_idl_index_create2(sb->idl, &sbrec_encap_col_chassis_name, > > + &sbrec_encap_col_ip); > > struct ovsdb_idl_index *sbrec_mac_binding_by_datapath > > = mac_binding_by_datapath_index_create(sb->idl); > > struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip > > @@ -529,6 +534,9 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, > > engine_ovsdb_node_add_index(&en_sb_chassis, > > "sbrec_chassis_by_hostname", > > sbrec_chassis_by_hostname); > > + engine_ovsdb_node_add_index(&en_sb_encap, > > + "sbrec_encap_by_chassis_ip", > > + sbrec_encap_by_chassis_ip); > > engine_ovsdb_node_add_index(&en_sb_ha_chassis_group, > > "sbrec_ha_chassis_grp_by_name", > > sbrec_ha_chassis_grp_by_name); > > diff --git a/northd/northd.c b/northd/northd.c > > index 983975dac..9b0e6480f 100644 > > --- a/northd/northd.c > > +++ b/northd/northd.c > > @@ -2546,6 +2546,58 @@ ovn_port_update_sbrec_chassis( > > free(requested_chassis_sb); > > } > > > > +static const struct sbrec_encap * > > +encap_lookup_by_chassis_ip(struct ovsdb_idl_index > > *sbrec_encap_by_chassis_ip, > > + const char *chassis_name, const char *ip) > > +{ > > + struct sbrec_encap *key = > > + sbrec_encap_index_init_row(sbrec_encap_by_chassis_ip); > > + sbrec_encap_index_set_chassis_name(key, chassis_name); > > + sbrec_encap_index_set_ip(key, ip); > > + > > + const struct sbrec_encap *best = NULL; > > + const struct sbrec_encap *encap; > > + SBREC_ENCAP_FOR_EACH_EQUAL (encap, key, sbrec_encap_by_chassis_ip) { > > + enum chassis_tunnel_type tun_type = get_tunnel_type(encap->type); > > + if (tun_type == TUNNEL_TYPE_INVALID) { > > + continue; > > + } > > + /* Pick the highest-preference tunnel type (geneve > vxlan) > > + * when multiple encap types share the same chassis+IP. */ > > + if (!best || get_tunnel_type(best->type) < tun_type) { > > + best = encap; > > + } > > + } > > + sbrec_encap_index_destroy_row(key); > > + > > + return best; > > +} > > + > > +static void > > +ovn_port_update_requested_encap( > > + struct ovsdb_idl_index *sbrec_encap_by_chassis_ip, > > + const struct ovn_port *op) > > +{ > > + if (is_cr_port(op)) { > > + return; > > + } > > + > > + /* requested-chassis is resolved into SB first; reuse that binding. */ > > + const struct smap *options = op->nbsp ? &op->nbsp->options > > + : &op->nbrp->options; > > + const char *requested_ip = smap_get(options, "requested-encap-ip"); > > + const struct sbrec_encap *encap = NULL; > > + if (requested_ip && requested_ip[0] && op->sb->requested_chassis) { > > + encap = encap_lookup_by_chassis_ip(sbrec_encap_by_chassis_ip, > > + op->sb->requested_chassis->name, > > + requested_ip); > > + } > > + > > + if (op->sb->encap != encap) { > > + sbrec_port_binding_set_encap(op->sb, encap); > > + } > > +} > > + > > static void > > check_and_do_sb_mirror_deletion(const struct ovn_port *op) > > { > > @@ -2616,6 +2668,7 @@ ovn_port_update_sbrec(struct ovsdb_idl_txn *ovnsb_txn, > > struct ovsdb_idl_index *sbrec_chassis_by_hostname, > > struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name, > > const struct sbrec_mirror_table *sbrec_mirror_table, > > + struct ovsdb_idl_index *sbrec_encap_by_chassis_ip, > > const struct ovn_port *op, > > unsigned long *queue_id_bitmap, > > struct sset *active_ha_chassis_grps) > > @@ -2952,6 +3005,8 @@ common: > > sbrec_port_binding_set_tunnel_key(op->sb, op->tunnel_key); > > } > > > > + ovn_port_update_requested_encap(sbrec_encap_by_chassis_ip, op); > > + > > /* ovn-controller will update 'Port_Binding.up' only if it was > > explicitly > > * set to 'false'. > > */ > > @@ -4232,6 +4287,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn, > > const struct sbrec_ha_chassis_group_table > > *sbrec_ha_chassis_group_table, > > struct ovsdb_idl_index *sbrec_chassis_by_name, > > struct ovsdb_idl_index *sbrec_chassis_by_hostname, > > + struct ovsdb_idl_index *sbrec_encap_by_chassis_ip, > > struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name, > > struct hmap *ls_datapaths, struct hmap *lr_datapaths, > > struct hmap *ls_ports, struct hmap *lr_ports, > > @@ -4307,6 +4363,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn, > > sbrec_chassis_by_hostname, > > sbrec_ha_chassis_grp_by_name, > > sbrec_mirror_table, > > + sbrec_encap_by_chassis_ip, > > op, queue_id_bitmap, > > &active_ha_chassis_grps); > > op->od->is_transit_router |= is_transit_router_port(op); > > @@ -4321,6 +4378,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn, > > sbrec_chassis_by_hostname, > > sbrec_ha_chassis_grp_by_name, > > sbrec_mirror_table, > > + sbrec_encap_by_chassis_ip, > > op, queue_id_bitmap, > > &active_ha_chassis_grps); > > sbrec_port_binding_set_logical_port(op->sb, op->key); > > @@ -4543,7 +4601,8 @@ ls_port_init(struct ovn_port *op, struct > > ovsdb_idl_txn *ovnsb_txn, > > const struct sbrec_port_binding *sb, > > const struct sbrec_mirror_table *sbrec_mirror_table, > > struct ovsdb_idl_index *sbrec_chassis_by_name, > > - struct ovsdb_idl_index *sbrec_chassis_by_hostname) > > + struct ovsdb_idl_index *sbrec_chassis_by_hostname, > > + struct ovsdb_idl_index *sbrec_encap_by_chassis_ip) > > { > > op->od = od; > > parse_lsp_addrs(op); > > @@ -4573,6 +4632,7 @@ ls_port_init(struct ovn_port *op, struct > > ovsdb_idl_txn *ovnsb_txn, > > } > > ovn_port_update_sbrec(ovnsb_txn, sbrec_chassis_by_name, > > sbrec_chassis_by_hostname, NULL, > > sbrec_mirror_table, > > + sbrec_encap_by_chassis_ip, > > op, NULL, NULL); > > return true; > > } > > @@ -4583,13 +4643,15 @@ ls_port_create(struct ovsdb_idl_txn *ovnsb_txn, > > struct hmap *ls_ports, > > struct ovn_datapath *od, > > const struct sbrec_mirror_table *sbrec_mirror_table, > > struct ovsdb_idl_index *sbrec_chassis_by_name, > > - struct ovsdb_idl_index *sbrec_chassis_by_hostname) > > + struct ovsdb_idl_index *sbrec_chassis_by_hostname, > > + struct ovsdb_idl_index *sbrec_encap_by_chassis_ip) > > { > > struct ovn_port *op = ovn_port_create(ls_ports, key, nbsp, NULL, > > NULL); > > hmap_insert(&od->ports, &op->dp_node, hmap_node_hash(&op->key_node)); > > if (!ls_port_init(op, ovnsb_txn, od, NULL, sbrec_mirror_table, > > - sbrec_chassis_by_name, sbrec_chassis_by_hostname)) { > > + sbrec_chassis_by_name, sbrec_chassis_by_hostname, > > + sbrec_encap_by_chassis_ip)) { > > ovn_port_destroy(ls_ports, op); > > return NULL; > > } > > @@ -4604,14 +4666,16 @@ ls_port_reinit(struct ovn_port *op, struct > > ovsdb_idl_txn *ovnsb_txn, > > const struct sbrec_port_binding *sb, > > const struct sbrec_mirror_table *sbrec_mirror_table, > > struct ovsdb_idl_index *sbrec_chassis_by_name, > > - struct ovsdb_idl_index *sbrec_chassis_by_hostname) > > + struct ovsdb_idl_index *sbrec_chassis_by_hostname, > > + struct ovsdb_idl_index *sbrec_encap_by_chassis_ip) > > { > > ovn_port_cleanup(op); > > op->sb = sb; > > ovn_port_set_nb(op, nbsp, NULL); > > op->primary_port = op->cr_port = NULL; > > return ls_port_init(op, ovnsb_txn, od, sb, sbrec_mirror_table, > > - sbrec_chassis_by_name, sbrec_chassis_by_hostname); > > + sbrec_chassis_by_name, sbrec_chassis_by_hostname, > > + sbrec_encap_by_chassis_ip); > > } > > > > /* Returns true if the logical switch has changes which can be > > @@ -4810,7 +4874,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn > > *ovnsb_idl_txn, > > new_nbsp->name, new_nbsp, od, > > ni->sbrec_mirror_table, > > ni->sbrec_chassis_by_name, > > - ni->sbrec_chassis_by_hostname); > > + ni->sbrec_chassis_by_hostname, > > + ni->sbrec_encap_by_chassis_ip); > > if (!op) { > > goto fail; > > } > > @@ -4853,7 +4918,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn > > *ovnsb_idl_txn, > > new_nbsp, > > od, sb, ni->sbrec_mirror_table, > > ni->sbrec_chassis_by_name, > > - ni->sbrec_chassis_by_hostname)) { > > + ni->sbrec_chassis_by_hostname, > > + ni->sbrec_encap_by_chassis_ip)) { > > if (sb) { > > sbrec_port_binding_delete(sb); > > } > > @@ -20959,6 +21025,7 @@ ovnnb_db_run(struct northd_input *input_data, > > input_data->sbrec_ha_chassis_group_table, > > input_data->sbrec_chassis_by_name, > > input_data->sbrec_chassis_by_hostname, > > + input_data->sbrec_encap_by_chassis_ip, > > input_data->sbrec_ha_chassis_grp_by_name, > > &data->ls_datapaths.datapaths, > > &data->lr_datapaths.datapaths, > > &data->ls_ports, &data->lr_ports, > > diff --git a/northd/northd.h b/northd/northd.h > > index 4dcd128cc..38092bb57 100644 > > --- a/northd/northd.h > > +++ b/northd/northd.h > > @@ -86,6 +86,7 @@ struct northd_input { > > struct ovsdb_idl_index *nbrec_mirror_by_type_and_sink; > > struct ovsdb_idl_index *sbrec_chassis_by_name; > > struct ovsdb_idl_index *sbrec_chassis_by_hostname; > > + struct ovsdb_idl_index *sbrec_encap_by_chassis_ip; > > struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name; > > struct ovsdb_idl_index *sbrec_ip_mcast_by_dp; > > struct ovsdb_idl_index *sbrec_fdb_by_dp_and_port; > > diff --git a/ovn-nb.xml b/ovn-nb.xml > > index 954ed1166..f1cd89509 100644 > > --- a/ovn-nb.xml > > +++ b/ovn-nb.xml > > @@ -1567,6 +1567,15 @@ > > </p> > > </column> > > > > + <column name="options" key="requested-encap-ip"> > > + Requests the encapsulation IP address for the port binding. If > > set, > > + <code>ovn-northd</code> uses this IP to select the > > + <ref table="Encap" db="OVN_Southbound"/> entry written to > > + <ref table="Port_Binding" column="encap" db="OVN_Southbound"/>. > > + This is intended for ports without a local OVS interface, e.g. > > remote > > + transit switch ports in ovn-kubernetes interconnect mode. > > + </column> > > + > > <column name="options" key="activation-strategy"> > > If used with multiple chassis set in > > <ref column="requested-chassis"/>, specifies an activation > > strategy > > @@ -4543,6 +4552,15 @@ or > > </p> > > </column> > > > > + <column name="options" key="requested-encap-ip"> > > + Requests the encapsulation IP address for the port binding. If set, > > + <code>ovn-northd</code> uses this IP to select the > > + <ref table="Encap" db="OVN_Southbound"/> entry written to > > + <ref table="Port_Binding" column="encap" db="OVN_Southbound"/>. > > + This is intended for ports without a local OVS interface, e.g. > > remote > > + transit router ports in ovn-kubernetes interconnect mode. > > + </column> > > + > > <column name="options" key="dynamic-routing-redistribute" > > type='{"type": "string"}'> > > <p> > > diff --git a/tests/ovn-inc-proc-graph-dump.at > > b/tests/ovn-inc-proc-graph-dump.at > > index a31aad6e7..44fa4dee9 100644 > > --- a/tests/ovn-inc-proc-graph-dump.at > > +++ b/tests/ovn-inc-proc-graph-dump.at > > @@ -20,6 +20,7 @@ digraph "Incremental-Processing-Engine" { > > NB_network_function_group [[style=filled, shape=box, > > fillcolor=white, label="NB_network_function_group"]]; > > NB_logical_switch_port_health_check [[style=filled, shape=box, > > fillcolor=white, label="NB_logical_switch_port_health_check"]]; > > SB_chassis [[style=filled, shape=box, fillcolor=white, > > label="SB_chassis"]]; > > + SB_encap [[style=filled, shape=box, fillcolor=white, > > label="SB_encap"]]; > > SB_mirror [[style=filled, shape=box, fillcolor=white, > > label="SB_mirror"]]; > > SB_meter [[style=filled, shape=box, fillcolor=white, > > label="SB_meter"]]; > > SB_dns [[style=filled, shape=box, fillcolor=white, label="SB_dns"]]; > > @@ -78,6 +79,7 @@ digraph "Incremental-Processing-Engine" { > > NB_network_function_group -> northd [[label=""]]; > > NB_logical_switch_port_health_check -> northd [[label=""]]; > > SB_chassis -> northd [[label=""]]; > > + SB_encap -> northd [[label=""]]; > > SB_mirror -> northd [[label=""]]; > > SB_meter -> northd [[label=""]]; > > SB_dns -> northd [[label=""]]; > > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > > index e29f6d7b5..3593ea04c 100644 > > --- a/tests/ovn-northd.at > > +++ b/tests/ovn-northd.at > > @@ -2896,6 +2896,77 @@ OVN_CLEANUP_NORTHD > > AT_CLEANUP > > ]) > > > > +OVN_FOR_EACH_NORTHD_NO_HV([ > > +AT_SETUP([check options:requested-encap-ip fills port binding encap col]) > > +AT_KEYWORDS([requested encap ip]) > > +ovn_start > > + > > +check_uuid ovn-sbctl \ > > + -- --id=@e11 create encap chassis_name=ch1 ip="192.168.1.1" > > type="vxlan" \ > > + -- --id=@e12 create encap chassis_name=ch1 ip="192.168.1.2" > > type="geneve" \ > > + -- --id=@c1 create chassis name=ch1 encaps=@e11,@e12 > > +check_uuid ovn-sbctl \ > > + -- --id=@e21 create encap chassis_name=ch2 ip="192.168.2.1" > > type="geneve" \ > > + -- --id=@e22 create encap chassis_name=ch2 ip="192.168.2.2" > > type="geneve" \ > > + -- --id=@c2 create chassis name=ch2 encaps=@e21,@e22 > > + > > +wait_row_count Chassis 2 > > +wait_row_count Encap 4 > > +en11_uuid=$(fetch_column Encap _uuid ip="192.168.1.1") > > +en12_uuid=$(fetch_column Encap _uuid ip="192.168.1.2") > > +en21_uuid=$(fetch_column Encap _uuid ip="192.168.2.1") > > +en22_uuid=$(fetch_column Encap _uuid ip="192.168.2.2") > > +ovn-sbctl show > > + > > +echo "__file__:__line__: encap uuid: $en11_uuid, ip: 192.168.1.1" > > +echo "__file__:__line__: encap uuid: $en12_uuid, ip: 192.168.1.2" > > +echo "__file__:__line__: encap uuid: $en21_uuid, ip: 192.168.2.1" > > +echo "__file__:__line__: encap uuid: $en22_uuid, ip: 192.168.2.2" > > + > > +check ovn-nbctl --wait=sb ls-add ls1 > > +check ovn-nbctl --wait=sb lsp-add ls1 lsp1 > > +check ovn-nbctl --wait=sb lsp-add ls1 lsp2 > > +ovn-nbctl show > > + > > +echo "options:requested-chassis is required to set > > options:requested-encap-ip" > > +check ovn-nbctl --wait=sb set logical-switch-port lsp1 \ > > + options:requested-encap-ip=192.168.1.1 > > +check ovn-nbctl --wait=sb sync > > +wait_row_count Port_Binding 1 logical_port=lsp1 'encap=[[]]' > > + > > +# Now set both options > > +check ovn-nbctl --wait=sb set logical-switch-port lsp1 \ > > + options:requested-chassis=ch1 \ > > + options:requested-encap-ip=192.168.1.1 > > +check ovn-nbctl --wait=sb set logical-switch-port lsp2 \ > > + options:requested-chassis=ch2 \ > > + options:requested-encap-ip=192.168.2.2 > > + > > +wait_row_count Port_Binding 1 logical_port=lsp1 encap="$en11_uuid" > > +wait_row_count Port_Binding 1 logical_port=lsp2 encap="$en22_uuid" > > + > > +# Add geneve encap with the same IP and ensure it is preferred over vxlan. > > +check_uuid ovn-sbctl \ > > + -- --id=@e11g create encap chassis_name=ch1 ip="192.168.1.1" > > type="geneve" \ > > + -- add chassis ch1 encaps @e11g > > +wait_row_count Encap 5 > > +en11g_uuid=$(fetch_column Encap _uuid chassis_name=ch1 ip="192.168.1.1" > > type=geneve) > > +wait_row_count Port_Binding 1 logical_port=lsp1 encap="$en11g_uuid" > > + > > +# remove options:requested-encap-ip from lsp1 > > +check ovn-nbctl --wait=sb remove logical_switch_port lsp1 \ > > + options requested-encap-ip=192.168.1.1 > > +wait_row_count Port_Binding 1 logical_port=lsp1 'encap=[[]]' > > + > > +# remove options:requested-chassis from lsp2 > > +check ovn-nbctl --wait=sb remove logical_switch_port lsp2 \ > > + options requested-chassis=ch2 > > +wait_row_count Port_Binding 1 logical_port=lsp2 'encap=[[]]' > > + > > +OVN_CLEANUP_NORTHD > > +AT_CLEANUP > > +]) > > + > > OVN_FOR_EACH_NORTHD_NO_HV([ > > AT_SETUP([port requested-tnl-key]) > > AT_KEYWORDS([requested tnl tunnel key keys]) > > -- > > 2.43.0 > > > _______________________________________________ > dev mailing list > [email protected] > https://mail.openvswitch.org/mailman/listinfo/ovs-dev _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
