diff --git a/.ci/ovn-kubernetes/Dockerfile b/.ci/ovn-kubernetes/Dockerfile index eda8b6d02..554b5551b 100644 --- a/.ci/ovn-kubernetes/Dockerfile +++ b/.ci/ovn-kubernetes/Dockerfile @@ -1,4 +1,4 @@ -ARG OVNKUBE_COMMIT=master +ARG OVNKUBE_COMMIT ARG GO_VERSION FROM fedora:37 AS ovnbuilder diff --git a/.github/workflows/ovn-kubernetes.yml b/.github/workflows/ovn-kubernetes.yml index 0f2b30497..f7dfd1c39 100644 --- a/.github/workflows/ovn-kubernetes.yml +++ b/.github/workflows/ovn-kubernetes.yml @@ -13,7 +13,7 @@ concurrency: cancel-in-progress: true env: - OVNKUBE_COMMIT: "master" + OVNKUBE_COMMIT: "release-1.0" KIND_CLUSTER_NAME: ovn KIND_INSTALL_INGRESS: true KIND_ALLOW_SYSTEM_WRITES: true @@ -41,6 +41,7 @@ jobs: with: path: src/github.com/ovn-org/ovn-kubernetes repository: ovn-org/ovn-kubernetes + ref: ${{ env.OVNKUBE_COMMIT }} - name: Prepare run: | @@ -108,6 +109,7 @@ jobs: with: path: src/github.com/ovn-org/ovn-kubernetes repository: ovn-org/ovn-kubernetes + ref: ${{ env.OVNKUBE_COMMIT }} - name: Prepare run: | diff --git a/AUTHORS.rst b/AUTHORS.rst index 65c8761f4..351523fd1 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -448,6 +448,7 @@ xushengping shengping.xu@huawei.com yinpeijun yinpeijun@huawei.com zangchuanqiang zangchuanqiang@huawei.com zhang yanxian zhangyanxian@pmlabs.com.cn +zhangqiang45 zhangqiang45@lenovo.com zhaojingjing zhao.jingjing1@zte.com.cn zhongbaisong zhongbaisong@huawei.com zhaozhanxu zhaozhanxu@163.com diff --git a/Documentation/automake.mk b/Documentation/automake.mk index 7fcd186ca..6628bd3e0 100644 --- a/Documentation/automake.mk +++ b/Documentation/automake.mk @@ -59,6 +59,7 @@ DOC_SOURCE = \ Documentation/internals/security.rst \ Documentation/internals/contributing/index.rst \ Documentation/internals/contributing/backporting-patches.rst \ + Documentation/internals/contributing/inclusive-language.rst \ Documentation/internals/contributing/coding-style.rst \ Documentation/internals/contributing/documentation-style.rst \ Documentation/internals/contributing/libopenvswitch-abi.rst \ diff --git a/Documentation/index.rst b/Documentation/index.rst index 730595c05..6dabd8a28 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -82,6 +82,7 @@ Learn more about the Open Virtual Network (OVN) project and about how you can co - **Contributing:** :doc:`internals/contributing/submitting-patches` | :doc:`internals/contributing/backporting-patches` | + :doc:`internals/contributing/inclusive-language` | :doc:`internals/contributing/coding-style` - **Maintaining:** :doc:`internals/maintainers` | diff --git a/Documentation/internals/contributing/inclusive-language.rst b/Documentation/internals/contributing/inclusive-language.rst new file mode 100644 index 000000000..65e9c4fbd --- /dev/null +++ b/Documentation/internals/contributing/inclusive-language.rst @@ -0,0 +1,57 @@ +.. + Licensed under the Apache License, Version 2.0 (the "License"); you may + not use this file except in compliance with the License. You may obtain + a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + License for the specific language governing permissions and limitations + under the License. + + Convention for heading levels in OVN documentation: + + ======= Heading 0 (reserved for the title in a document) + ------- Heading 1 + ~~~~~~~ Heading 2 + +++++++ Heading 3 + ''''''' Heading 4 + + Avoid deeper levels because they do not render well. + +================== +Inclusive Language +================== + +In order to help facilitate an inclusive environment in the OVN +community we recognise the role of language in framing our +communication with each other. It is important that terms that +may exclude people through racial, cultural or other bias, are avoided +as they may make people feel excluded. + +We recognise that this is subjective, and to some extent is a journey. +But we also recognise that we cannot begin that journey without taking +positive action. To this end OVN is adopting the practice of an +inclusive word list, which helps to guide the use of language within +the project. + +.. _word list: + +Word List +--------- + +The intent of this document is to formally document the acceptance of a +inclusive word list by OVN. Accordingly, this document specifies +use of the use the `Inclusive Naming Word List +`__ v1.0 (the word list) for +OVN. + +The adoption of the word list intended that this act as a guide for +developers creating patches to the OVN repository, including both +source code and documentation. And to aid maintainers in their role of +shepherding changes into the repository. + +Further steps to align usage of language in OVN, including clarification +of application of the word list, to new and existing work, may follow. diff --git a/Documentation/internals/contributing/index.rst b/Documentation/internals/contributing/index.rst index 77b52964b..4f09ad473 100644 --- a/Documentation/internals/contributing/index.rst +++ b/Documentation/internals/contributing/index.rst @@ -31,6 +31,7 @@ The below guides provide information on contributing to OVN itself. :maxdepth: 2 submitting-patches + inclusive-language backporting-patches coding-style documentation-style diff --git a/NEWS b/NEWS index 5c80fa482..9265e0836 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +OVN v23.09.6 - xx xxx xxxx +-------------------------- + +OVN v23.09.5 - 16 Aug 2024 +-------------------------- + - Bug fixes + OVN v23.09.4 - 09 May 2024 -------------------------- - Bug fixes diff --git a/configure.ac b/configure.ac index c71ade236..055d339e3 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ # limitations under the License. AC_PREREQ(2.63) -AC_INIT(ovn, 23.09.4, bugs@openvswitch.org) +AC_INIT(ovn, 23.09.6, bugs@openvswitch.org) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/controller/if-status.c b/controller/if-status.c index 6e8aa1f7e..2d6d06d9b 100644 --- a/controller/if-status.c +++ b/controller/if-status.c @@ -219,7 +219,8 @@ ovs_iface_create(struct if_status_mgr *, const char *iface_id, static void add_to_ovn_uninstall_hash(struct if_status_mgr *, const char *, const struct uuid *); static void ovs_iface_destroy(struct if_status_mgr *, struct ovs_iface *); -static void ovn_uninstall_hash_destroy(struct if_status_mgr *mgr, char *name); +static void ovn_uninstall_hash_destroy(struct if_status_mgr *mgr, + struct shash_node *node); static void ovs_iface_set_state(struct if_status_mgr *, struct ovs_iface *, enum if_state); @@ -256,7 +257,7 @@ if_status_mgr_clear(struct if_status_mgr *mgr) ovs_assert(shash_is_empty(&mgr->ifaces)); SHASH_FOR_EACH_SAFE (node, &mgr->ovn_uninstall_hash) { - ovn_uninstall_hash_destroy(mgr, node->data); + ovn_uninstall_hash_destroy(mgr, node); } ovs_assert(shash_is_empty(&mgr->ovn_uninstall_hash)); @@ -789,20 +790,13 @@ ovs_iface_destroy(struct if_status_mgr *mgr, struct ovs_iface *iface) } static void -ovn_uninstall_hash_destroy(struct if_status_mgr *mgr, char *name) +ovn_uninstall_hash_destroy(struct if_status_mgr *mgr, struct shash_node *node) { - struct shash_node *node = shash_find(&mgr->ovn_uninstall_hash, name); - char *node_name = NULL; - if (node) { - free(node->data); - VLOG_DBG("Interface name %s destroy", name); - node_name = shash_steal(&mgr->ovn_uninstall_hash, node); - ovn_uninstall_hash_account_mem(name, true); - free(node_name); - } else { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Interface name %s not found", name); - } + free(node->data); + VLOG_DBG("Interface name %s destroy", node->name); + char *node_name = shash_steal(&mgr->ovn_uninstall_hash, node); + ovn_uninstall_hash_account_mem(node_name, true); + free(node_name); } static void diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index e8e7ac6bd..66b656044 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -750,7 +750,7 @@ update_ct_zones(const struct sset *local_lports, const char *user; struct sset all_users = SSET_INITIALIZER(&all_users); struct simap req_snat_zones = SIMAP_INITIALIZER(&req_snat_zones); - unsigned long unreq_snat_zones_map[BITMAP_N_LONGS(MAX_CT_ZONES)]; + unsigned long *unreq_snat_zones_map = bitmap_allocate(MAX_CT_ZONES); struct simap unreq_snat_zones = SIMAP_INITIALIZER(&unreq_snat_zones); const char *local_lport; @@ -861,6 +861,7 @@ update_ct_zones(const struct sset *local_lports, simap_destroy(&req_snat_zones); simap_destroy(&unreq_snat_zones); sset_destroy(&all_users); + bitmap_free(unreq_snat_zones_map); } static void @@ -1146,6 +1147,7 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) ovsdb_idl_add_table(ovs_idl, &ovsrec_table_queue); ovsdb_idl_add_column(ovs_idl, &ovsrec_queue_col_other_config); ovsdb_idl_add_column(ovs_idl, &ovsrec_queue_col_external_ids); + ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_link_state); chassis_register_ovs_idl(ovs_idl); encaps_register_ovs_idl(ovs_idl); @@ -2990,7 +2992,7 @@ lb_data_local_lb_add(struct ed_type_lb_data *lb_data, static void lb_data_local_lb_remove(struct ed_type_lb_data *lb_data, - struct ovn_controller_lb *lb, bool tracked) + struct ovn_controller_lb *lb) { const struct uuid *uuid = &lb->slb->header_.uuid; @@ -2999,12 +3001,8 @@ lb_data_local_lb_remove(struct ed_type_lb_data *lb_data, lb_data_removed_five_tuples_add(lb_data, lb); - if (tracked) { - hmap_insert(&lb_data->old_lbs, &lb->hmap_node, uuid_hash(uuid)); - uuidset_insert(&lb_data->deleted, uuid); - } else { - ovn_controller_lb_destroy(lb); - } + hmap_insert(&lb_data->old_lbs, &lb->hmap_node, uuid_hash(uuid)); + uuidset_insert(&lb_data->deleted, uuid); } static bool @@ -3029,7 +3027,7 @@ lb_data_handle_changed_ref(enum objdep_type type, const char *res_name, continue; } - lb_data_local_lb_remove(lb_data, lb, true); + lb_data_local_lb_remove(lb_data, lb); const struct sbrec_load_balancer *sbrec_lb = sbrec_load_balancer_table_get_for_uuid(ctx_in->lb_table, uuid); @@ -3075,9 +3073,13 @@ en_lb_data_run(struct engine_node *node, void *data) const struct sbrec_load_balancer_table *lb_table = EN_OVSDB_GET(engine_get_input("SB_load_balancer", node)); + objdep_mgr_clear(&lb_data->deps_mgr); + struct ovn_controller_lb *lb; HMAP_FOR_EACH_SAFE (lb, hmap_node, &lb_data->local_lbs) { - lb_data_local_lb_remove(lb_data, lb, false); + hmap_remove(&lb_data->local_lbs, &lb->hmap_node); + lb_data_removed_five_tuples_add(lb_data, lb); + ovn_controller_lb_destroy(lb); } const struct sbrec_load_balancer *sbrec_lb; @@ -3115,7 +3117,7 @@ lb_data_sb_load_balancer_handler(struct engine_node *node, void *data) continue; } - lb_data_local_lb_remove(lb_data, lb, true); + lb_data_local_lb_remove(lb_data, lb); } if (sbrec_load_balancer_is_deleted(sbrec_lb) || @@ -4054,6 +4056,8 @@ en_lflow_output_run(struct engine_node *node, void *data) EN_OVSDB_GET(engine_get_input("OVS_bridge", node)); const struct ovsrec_bridge *br_int = get_br_int(bridge_table, ovs_table); const char *chassis_id = get_ovs_chassis_id(ovs_table); + const struct ovsrec_flow_sample_collector_set_table *flow_collector_table = + EN_OVSDB_GET(engine_get_input("OVS_flow_sample_collector_set", node)); struct ovsdb_idl_index *sbrec_chassis_by_name = engine_ovsdb_node_get_index( @@ -4067,6 +4071,17 @@ en_lflow_output_run(struct engine_node *node, void *data) ovs_assert(br_int && chassis); + const struct ovsrec_flow_sample_collector_set *set; + OVSREC_FLOW_SAMPLE_COLLECTOR_SET_TABLE_FOR_EACH (set, + flow_collector_table) { + if (set->bridge == br_int) { + struct ed_type_lflow_output *lfo = data; + flow_collector_ids_clear(&lfo->collector_ids); + flow_collector_ids_init_from_table(&lfo->collector_ids, + flow_collector_table); + } + } + struct ed_type_lflow_output *fo = data; struct ovn_desired_flow_table *lflow_table = &fo->flow_table; struct ovn_extend_table *group_table = &fo->group_table; @@ -5719,17 +5734,14 @@ main(int argc, char *argv[]) br_int ? br_int->name : NULL)) { VLOG_INFO("OVS feature set changed, force recompute."); engine_set_force_recompute(true); - if (ovs_feature_set_discovered()) { - uint32_t max_groups = ovs_feature_max_select_groups_get(); - uint32_t max_meters = ovs_feature_max_meters_get(); - struct ed_type_lflow_output *lflow_out_data = - engine_get_internal_data(&en_lflow_output); - - ovn_extend_table_reinit(&lflow_out_data->group_table, - max_groups); - ovn_extend_table_reinit(&lflow_out_data->meter_table, - max_meters); - } + + struct ed_type_lflow_output *lflow_out_data = + engine_get_internal_data(&en_lflow_output); + + ovn_extend_table_reinit(&lflow_out_data->group_table, + ovs_feature_max_select_groups_get()); + ovn_extend_table_reinit(&lflow_out_data->meter_table, + ovs_feature_max_meters_get()); } if (br_int) { diff --git a/controller/physical.c b/controller/physical.c index c93fe9aa6..54bae81d1 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -1212,6 +1212,12 @@ reply_imcp_error_if_pkt_too_big(struct ovn_desired_flow_table *flow_table, ofpact_put_set_field( &inner_ofpacts, mf_from_id(MFF_LOG_FLAGS), &value, &mask); + /* inport <-> outport */ + put_stack(MFF_LOG_INPORT, ofpact_put_STACK_PUSH(&inner_ofpacts)); + put_stack(MFF_LOG_OUTPORT, ofpact_put_STACK_PUSH(&inner_ofpacts)); + put_stack(MFF_LOG_INPORT, ofpact_put_STACK_POP(&inner_ofpacts)); + put_stack(MFF_LOG_OUTPORT, ofpact_put_STACK_POP(&inner_ofpacts)); + /* eth.src <-> eth.dst */ put_stack(MFF_ETH_DST, ofpact_put_STACK_PUSH(&inner_ofpacts)); put_stack(MFF_ETH_SRC, ofpact_put_STACK_PUSH(&inner_ofpacts)); diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 98821d275..9e80556ef 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -655,8 +655,6 @@ 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_SNOOP_INJECT_BIT, 1, &ofpacts); struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); resubmit->in_port = OFPP_CONTROLLER; @@ -5756,6 +5754,10 @@ get_localnet_vifs_l3gwports( if (!pb || pb->chassis != chassis) { continue; } + if (!iface_rec->link_state || + strcmp(iface_rec->link_state, "up")) { + continue; + } struct local_datapath *ld = get_local_datapath(local_datapaths, pb->datapath->tunnel_key); @@ -6687,6 +6689,9 @@ struct svc_monitor { long long int timestamp; bool is_ip6; + struct eth_addr src_mac; + struct in6_addr src_ip; + long long int wait_time; long long int next_send_time; @@ -6881,6 +6886,9 @@ sync_svc_monitors(struct ovsdb_idl_txn *ovnsb_idl_txn, svc_mon->n_success = 0; svc_mon->n_failures = 0; + eth_addr_from_string(sb_svc_mon->src_mac, &svc_mon->src_mac); + ip46_parse(sb_svc_mon->src_ip, &svc_mon->src_ip); + hmap_insert(&svc_monitors_map, &svc_mon->hmap_node, hash); ovs_list_push_back(&svc_monitors, &svc_mon->list_node); changed = true; @@ -7639,19 +7647,14 @@ svc_monitor_send_tcp_health_check__(struct rconn *swconn, struct dp_packet packet; dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); - struct eth_addr eth_src; - eth_addr_from_string(svc_mon->sb_svc_mon->src_mac, ð_src); if (svc_mon->is_ip6) { - struct in6_addr ip6_src; - ipv6_parse(svc_mon->sb_svc_mon->src_ip, &ip6_src); - pinctrl_compose_ipv6(&packet, eth_src, svc_mon->ea, - &ip6_src, &svc_mon->ip, IPPROTO_TCP, + pinctrl_compose_ipv6(&packet, svc_mon->src_mac, svc_mon->ea, + &svc_mon->src_ip, &svc_mon->ip, IPPROTO_TCP, 63, TCP_HEADER_LEN); } else { - ovs_be32 ip4_src; - ip_parse(svc_mon->sb_svc_mon->src_ip, &ip4_src); - pinctrl_compose_ipv4(&packet, eth_src, svc_mon->ea, - ip4_src, in6_addr_get_mapped_ipv4(&svc_mon->ip), + pinctrl_compose_ipv4(&packet, svc_mon->src_mac, svc_mon->ea, + in6_addr_get_mapped_ipv4(&svc_mon->src_ip), + in6_addr_get_mapped_ipv4(&svc_mon->ip), IPPROTO_TCP, 63, TCP_HEADER_LEN); } @@ -7707,24 +7710,18 @@ svc_monitor_send_udp_health_check(struct rconn *swconn, struct svc_monitor *svc_mon, ovs_be16 udp_src) { - struct eth_addr eth_src; - eth_addr_from_string(svc_mon->sb_svc_mon->src_mac, ð_src); - uint64_t packet_stub[128 / 8]; struct dp_packet packet; dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); if (svc_mon->is_ip6) { - struct in6_addr ip6_src; - ipv6_parse(svc_mon->sb_svc_mon->src_ip, &ip6_src); - pinctrl_compose_ipv6(&packet, eth_src, svc_mon->ea, - &ip6_src, &svc_mon->ip, IPPROTO_UDP, + pinctrl_compose_ipv6(&packet, svc_mon->src_mac, svc_mon->ea, + &svc_mon->src_ip, &svc_mon->ip, IPPROTO_UDP, 63, UDP_HEADER_LEN + 8); } else { - ovs_be32 ip4_src; - ip_parse(svc_mon->sb_svc_mon->src_ip, &ip4_src); - pinctrl_compose_ipv4(&packet, eth_src, svc_mon->ea, - ip4_src, in6_addr_get_mapped_ipv4(&svc_mon->ip), + pinctrl_compose_ipv4(&packet, svc_mon->src_mac, svc_mon->ea, + in6_addr_get_mapped_ipv4(&svc_mon->src_ip), + in6_addr_get_mapped_ipv4(&svc_mon->ip), IPPROTO_UDP, 63, UDP_HEADER_LEN + 8); } diff --git a/debian/changelog b/debian/changelog index e06f13536..244bb95ce 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +ovn (23.09.6-1) unstable; urgency=low + [ OVN team ] + * New upstream version + + -- OVN team Fri, 16 Aug 2024 13:51:01 -0400 + +OVN (23.09.5-1) unstable; urgency=low + [ OVN team ] + * New upstream version + + -- OVN team Fri, 16 Aug 2024 13:51:01 -0400 + OVN (23.09.4-1) unstable; urgency=low [ OVN team ] * New upstream version diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 7446accad..cf0558c0e 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -2324,7 +2324,7 @@ ovn_ic_resume(struct unixctl_conn *conn, int argc OVS_UNUSED, { struct ic_state *state = state_; state->paused = false; - + poll_immediate_wake(); unixctl_command_reply(conn, NULL); } diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h index e3236fa24..f07c4c42e 100644 --- a/include/ovn/logical-fields.h +++ b/include/ovn/logical-fields.h @@ -80,7 +80,6 @@ enum mff_log_flags_bits { MLF_LOCALNET_BIT = 15, MLF_RX_FROM_TUNNEL_BIT = 16, MLF_ICMP_SNAT_BIT = 17, - MLF_IGMP_IGMP_SNOOP_INJECT_BIT = 18, }; /* MFF_LOG_FLAGS_REG flag assignments */ @@ -136,8 +135,6 @@ enum mff_log_flags { MLF_RX_FROM_TUNNEL = (1 << MLF_RX_FROM_TUNNEL_BIT), MLF_ICMP_SNAT = (1 << MLF_ICMP_SNAT_BIT), - - MLF_IGMP_IGMP_SNOOP = (1 << MLF_IGMP_IGMP_SNOOP_INJECT_BIT), }; /* OVN logical fields diff --git a/lib/actions.c b/lib/actions.c index 2b3fc915c..5c10edf53 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -875,6 +875,9 @@ encode_CT_COMMIT_V2(const struct ovnact_nest *on, const struct ovnact_encode_params *ep OVS_UNUSED, struct ofpbuf *ofpacts) { + size_t ct_offset = ofpacts->size; + ofpbuf_pull(ofpacts, ct_offset); + struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts); ct->flags = NX_CT_F_COMMIT; ct->recirc_table = NX_CT_RECIRC_NONE; @@ -906,6 +909,7 @@ encode_CT_COMMIT_V2(const struct ovnact_nest *on, ofpacts->header = ofpbuf_push_uninit(ofpacts, set_field_offset); ct = ofpacts->header; ofpact_finish(ofpacts, &ct->ofpact); + ofpbuf_push_uninit(ofpacts, ct_offset); } static void diff --git a/lib/logical-fields.c b/lib/logical-fields.c index 68892dba5..d84528ef5 100644 --- a/lib/logical-fields.c +++ b/lib/logical-fields.c @@ -139,10 +139,6 @@ ovn_init_symtab(struct shash *symtab) flags_str); snprintf(flags_str, sizeof flags_str, "flags[%d]", MLF_RX_FROM_TUNNEL_BIT); expr_symtab_add_subfield(symtab, "flags.tunnel_rx", NULL, flags_str); - snprintf(flags_str, sizeof flags_str, "flags[%d]", - MLF_IGMP_IGMP_SNOOP_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, @@ -247,7 +243,7 @@ ovn_init_symtab(struct shash *symtab) expr_symtab_add_field(symtab, "icmp4.code", MFF_ICMPV4_CODE, "icmp4", false); - expr_symtab_add_predicate(symtab, "igmp", "ip4 && ip.proto == 2"); + expr_symtab_add_predicate(symtab, "igmp", "ip4.mcast && ip.proto == 2"); expr_symtab_add_field(symtab, "ip6.src", MFF_IPV6_SRC, "ip6", false); expr_symtab_add_field(symtab, "ip6.dst", MFF_IPV6_DST, "ip6", false); @@ -307,6 +303,9 @@ ovn_init_symtab(struct shash *symtab) "icmp6.type == {135, 136} && icmp6.code == 0 && ip.ttl == 255"); expr_symtab_add_predicate(symtab, "nd_ns", "icmp6.type == 135 && icmp6.code == 0 && ip.ttl == 255"); + expr_symtab_add_predicate(symtab, "nd_ns_mcast", + "ip6.mcast && icmp6.type == 135 && icmp6.code == 0 && " + "ip.ttl == 255"); expr_symtab_add_predicate(symtab, "nd_na", "icmp6.type == 136 && icmp6.code == 0 && ip.ttl == 255"); expr_symtab_add_predicate(symtab, "nd_rs", @@ -321,11 +320,12 @@ ovn_init_symtab(struct shash *symtab) * (RFC 2710 and RFC 3810). */ expr_symtab_add_predicate(symtab, "mldv1", - "ip6.src == fe80::/10 && " + "eth.mcastv6 && ip6.src == fe80::/10 && " "icmp6.type == {130, 131, 132}"); /* MLDv2 packets are sent to ff02::16 (RFC 3810, 5.2.14) */ expr_symtab_add_predicate(symtab, "mldv2", - "ip6.dst == ff02::16 && icmp6.type == 143"); + "eth.mcastv6 && ip6.dst == ff02::16 && " + "icmp6.type == 143"); expr_symtab_add_predicate(symtab, "tcp", "ip.proto == 6"); expr_symtab_add_field(symtab, "tcp.src", MFF_TCP_SRC, "tcp", false); diff --git a/northd/northd.c b/northd/northd.c index 32240b856..6a4f8f222 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -119,6 +119,7 @@ static bool default_acl_drop; #define REGBIT_PORT_SEC_DROP "reg0[15]" #define REGBIT_ACL_STATELESS "reg0[16]" #define REGBIT_ACL_HINT_ALLOW_REL "reg0[17]" +#define REGBIT_FROM_ROUTER_PORT "reg0[18]" #define REG_ORIG_DIP_IPV4 "reg1" #define REG_ORIG_DIP_IPV6 "xxreg1" @@ -805,12 +806,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; -} - static struct ovn_datapath * ovn_datapath_from_sbrec(const struct hmap *ls_datapaths, const struct hmap *lr_datapaths, @@ -6126,13 +6121,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; } @@ -6956,6 +6949,12 @@ build_lswitch_port_sec_op(struct ovn_port *op, struct hmap *lflows, op->od->localnet_ports[0]->key, &op->od->localnet_ports[0]->nbsp->header_); } + } else if (lsp_is_router(op->nbsp)) { + ds_put_format(actions, REGBIT_FROM_ROUTER_PORT" = 1; next;"); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_CHECK_PORT_SEC, 70, + ds_cstr(match), ds_cstr(actions), + op->key, &op->nbsp->header_); } } @@ -7252,8 +7251,7 @@ build_interconn_mcast_snoop_flows(struct ovn_datapath *od, continue; } /* Punt IGMP traffic to controller. */ - char *match = xasprintf("inport == %s && igmp && " - "flags.igmp_loopback == 0", op->json_key); + char *match = xasprintf("inport == %s && igmp", 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, @@ -7261,8 +7259,7 @@ build_interconn_mcast_snoop_flows(struct ovn_datapath *od, free(match); /* Punt MLD traffic to controller. */ - match = xasprintf("inport == %s && (mldv1 || mldv2) && " - "flags.igmp_loopback == 0", op->json_key); + match = xasprintf("inport == %s && (mldv1 || mldv2)", 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, @@ -8933,13 +8930,16 @@ build_fwd_group_lflows(struct ovn_datapath *od, struct hmap *lflows) struct ds actions = DS_EMPTY_INITIALIZER; struct ds group_ports = DS_EMPTY_INITIALIZER; - for (int i = 0; i < od->nbs->n_forwarding_groups; ++i) { + for (size_t i = 0; i < od->nbs->n_forwarding_groups; ++i) { const struct nbrec_forwarding_group *fwd_group = NULL; fwd_group = od->nbs->forwarding_groups[i]; if (!fwd_group->n_child_port) { continue; } + ds_clear(&match); + ds_clear(&actions); + /* ARP responder for the forwarding group's virtual IP */ ds_put_format(&match, "arp.tpa == %s && arp.op == 1", fwd_group->vip); @@ -8970,9 +8970,9 @@ build_fwd_group_lflows(struct ovn_datapath *od, struct hmap *lflows) ds_put_cstr(&group_ports, "liveness=\"true\","); } ds_put_cstr(&group_ports, "childports="); - for (i = 0; i < (fwd_group->n_child_port - 1); ++i) { + for (size_t j = 0; j < (fwd_group->n_child_port - 1); ++j) { ds_put_format(&group_ports, "\"%s\",", - fwd_group->child_port[i]); + fwd_group->child_port[j]); } ds_put_format(&group_ports, "\"%s\"", fwd_group->child_port[fwd_group->n_child_port - 1]); @@ -9912,16 +9912,21 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, &op->nbsp->header_); } - /* For ND solicitations, we need to listen for both the - * unicast IPv6 address and its all-nodes multicast address, - * but always respond with the unicast IPv6 address. */ + /* For ND solicitations: + * - Reply only for the all-nodes multicast address(es) of the + * logical port IPv6 address(es). + * + * - Do not reply for unicast ND solicitations. Let the target + * reply to it, so that the sender has the ability to monitor + * the target liveness via the unicast ND solicitations. + */ for (size_t j = 0; j < op->lsp_addrs[i].n_ipv6_addrs; j++) { ds_clear(match); - ds_put_format(match, - "nd_ns && ip6.dst == {%s, %s} && nd.target == %s", - op->lsp_addrs[i].ipv6_addrs[j].addr_s, - op->lsp_addrs[i].ipv6_addrs[j].sn_addr_s, - op->lsp_addrs[i].ipv6_addrs[j].addr_s); + ds_put_format( + match, + "nd_ns_mcast && ip6.dst == %s && nd.target == %s", + op->lsp_addrs[i].ipv6_addrs[j].sn_addr_s, + op->lsp_addrs[i].ipv6_addrs[j].addr_s); ds_clear(actions); ds_put_format(actions, @@ -9977,7 +9982,9 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, if (op->proxy_arp_addrs.n_ipv4_addrs) { /* Match rule on all proxy ARP IPs. */ ds_clear(match); - ds_put_cstr(match, "arp.op == 1 && arp.tpa == {"); + ds_put_cstr(match, + REGBIT_FROM_ROUTER_PORT" == 0 " + "&& arp.op == 1 && arp.tpa == {"); for (i = 0; i < op->proxy_arp_addrs.n_ipv4_addrs; i++) { ds_put_format(match, "%s/%u,", @@ -10027,7 +10034,8 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, ds_truncate(&nd_target_match, nd_target_match.length - 2); ds_clear(match); ds_put_format(match, - "nd_ns " + REGBIT_FROM_ROUTER_PORT" == 0 " + "&& nd_ns " "&& ip6.dst == { %s } " "&& nd.target == { %s }", ds_cstr(&ip6_dst_match), @@ -10288,14 +10296,13 @@ 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, - "flags.igmp_loopback == 0 && igmp", ds_cstr(actions), + "igmp", ds_cstr(actions), copp_meter_get(COPP_IGMP, od->nbs->copp, meter_groups)); /* Punt MLD traffic to controller. */ ovn_lflow_metered(lflows, od, S_SWITCH_IN_L2_LKUP, 100, - "flags.igmp_loopback == 0 && (mldv1 || mldv2)", - ds_cstr(actions), + "mldv1 || mldv2", ds_cstr(actions), copp_meter_get(COPP_IGMP, od->nbs->copp, meter_groups)); @@ -10359,16 +10366,8 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, } -/* Ingress table 27: Add IP multicast flows learnt from IGMP/MLD - * (priority 90). - * - * OR, for transit switches: - * - * 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 MROUTER Ports. - * (priority 90). - */ +/* Ingress table 25: Add IP multicast flows learnt from IGMP/MLD + * (priority 90). */ static void build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, struct hmap *lflows, @@ -10382,9 +10381,6 @@ 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; @@ -10430,7 +10426,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 && !transit_switch) { + if (mcast_sw_info->flood_relay) { ds_put_cstr(actions, "clone { " "outport = \""MC_MROUTER_FLOOD "\"; " @@ -10779,8 +10775,9 @@ build_bfd_table(struct ovsdb_idl_txn *ovnsb_txn, } build_bfd_update_sb_conf(nb_bt, bfd_e->sb_bt); if (op && op->sb && op->sb->chassis && - strcmp(op->sb->chassis->name, sb_bt->chassis_name)) { - sbrec_bfd_set_chassis_name(sb_bt, op->sb->chassis->name); + strcmp(op->sb->chassis->name, bfd_e->sb_bt->chassis_name)) { + sbrec_bfd_set_chassis_name(bfd_e->sb_bt, + op->sb->chassis->name); } hmap_remove(&sb_only, &bfd_e->hmap_node); @@ -17618,7 +17615,8 @@ build_static_mac_binding_table( struct hmap *lr_ports) { /* Cleanup SB Static_MAC_Binding entries which do not have corresponding - * NB Static_MAC_Binding entries. */ + * NB Static_MAC_Binding entries, and SB Static_MAC_Binding entries for + * which there is not a NB Logical_Router_Port of the same name. */ const struct nbrec_static_mac_binding *nb_smb; const struct sbrec_static_mac_binding *sb_smb; SBREC_STATIC_MAC_BINDING_TABLE_FOR_EACH_SAFE (sb_smb, @@ -17628,6 +17626,12 @@ build_static_mac_binding_table( sb_smb->ip); if (!nb_smb) { sbrec_static_mac_binding_delete(sb_smb); + continue; + } + + struct ovn_port *op = ovn_port_find(lr_ports, nb_smb->logical_port); + if (!op || !op->nbrp || !op->od || !op->od->sb) { + sbrec_static_mac_binding_delete(sb_smb); } } diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 897e626b4..f36afd999 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -1983,13 +1983,13 @@ output;
  • - Priority-90 flows for non-transit switches that forward registered - IP multicast traffic to their corresponding multicast group, which - ovn-northd creates based on learnt - entries. The flows - also forward packets to the MC_MROUTER_FLOOD multicast - group, which ovn-nortdh populates with all the logical - ports that are connected to logical routers with + Priority-90 flows that forward registered IP multicast traffic to + their corresponding multicast group, which ovn-northd + creates based on learnt + entries. The flows also forward packets to the + MC_MROUTER_FLOOD multicast group, which + ovn-nortdh populates with all the logical ports that + are connected to logical routers with :mcast_relay='true'.
  • diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 00ff6ea4f..22c392b67 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -1098,6 +1098,7 @@ ovn_northd_resume(struct unixctl_conn *conn, int argc OVS_UNUSED, { struct northd_state *state = state_; state->paused = false; + poll_immediate_wake(); unixctl_command_reply(conn, NULL); } diff --git a/ovn-sb.xml b/ovn-sb.xml index 94e722512..01d1a3f4d 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -1155,6 +1155,7 @@
    • eth.bcast expands to eth.dst == ff:ff:ff:ff:ff:ff
    • eth.mcast expands to eth.dst[40]
    • +
    • eth.mcastv6 expands to eth.dst[32..47] == 0x3333
    • vlan.present expands to vlan.tci[12]
    • ip4 expands to eth.type == 0x800
    • ip4.src_mcast expands to @@ -1170,8 +1171,10 @@
    • ip.first_frag expands to ip.is_frag && !ip.later_frag
    • arp expands to eth.type == 0x806
    • rarp expands to eth.type == 0x8035
    • +
    • ip6.mcast expands to eth.mcastv6 && ip6.dst[120..127] == 0xff
    • nd expands to icmp6.type == {135, 136} && icmp6.code == 0 && ip.ttl == 255
    • nd_ns expands to icmp6.type == 135 && icmp6.code == 0 && ip.ttl == 255
    • +
    • nd_ns_mcast expands to ip6.mcast && icmp6.type == 135 && icmp6.code == 0 && ip.ttl == 255
    • nd_na expands to icmp6.type == 136 && icmp6.code == 0 && ip.ttl == 255
    • nd_rs expands to icmp6.type == 133 && icmp6.code == 0 && ip.ttl == 255
    • diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index 83d13213f..678afe462 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -2772,3 +2772,41 @@ priority=1100,ip,reg15=0x1,metadata=0x1,nw_src=10.0.0.4 actions=load:0x1->OXM_OF OVN_CLEANUP([hv1]) AT_CLEANUP + +AT_SETUP([ovn-controller - LB remove after disconnect]) +ovn_start + +net_add n1 +sim_add hv1 +as hv1 +check 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=lsp + +check ovs-vsctl set Open_vSwitch . external-ids:ovn-remote-probe-interval="5000" + +check ovn-nbctl ls-add ls +check ovn-nbctl lsp-add ls lsp \ +-- lsp-set-addresses lsp "f0:00:00:00:00:01 172.16.0.10" + +check ovn-nbctl lb-add lb 192.168.100.100 172.16.0.10 +check ovn-nbctl ls-lb-add ls lb + +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +sleep_sb +OVS_WAIT_UNTIL([grep -q 'OVNSB commit failed' hv1/ovn-controller.log]) + +sleep_controller hv1 +wake_up_sb + +ovn-nbctl lb-del lb + +wake_up_controller hv1 +check ovn-nbctl --wait=hv sync + +OVN_CLEANUP([hv1 +/no response to inactivity probe after .* seconds, disconnecting/d]) +AT_CLEANUP diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at index f5de46a0b..fc89b5bab 100644 --- a/tests/ovn-macros.at +++ b/tests/ovn-macros.at @@ -957,16 +957,18 @@ stop_ovsdb_controller_updates() { TCP_PORT=$1 echo Stopping updates from ovn-controller to ovsdb using port $TCP_PORT on_exit 'nft list tables | grep ovn-test && nft delete table ip ovn-test' - nft add table ip ovn-test - nft 'add chain ip ovn-test INPUT { type filter hook input priority 0; policy accept; }' - nft add rule ip ovn-test INPUT tcp dport $TCP_PORT counter drop + # Report the test as skipped if proper nft related packages are not installed. + AT_SKIP_IF([! which nft]) + AT_CHECK([nft add table ip ovn-test]) + AT_CHECK([nft 'add chain ip ovn-test INPUT { type filter hook input priority 0; policy accept; }']) + AT_CHECK([nft add rule ip ovn-test INPUT tcp dport $TCP_PORT counter drop]) } restart_ovsdb_controller_updates() { TCP_PORT=$1 echo Restarting updates from ovn-controller to ovsdb - nft list ruleset | grep $TCP_PORT - nft delete table ip ovn-test + AT_CHECK([nft list ruleset | grep $TCP_PORT], [0], [ignore]) + AT_CHECK([nft delete table ip ovn-test]) } trim_zeros() { diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 4bebb2673..22c881d6a 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -7619,6 +7619,19 @@ wait_row_count Static_MAC_Binding 1 logical_port=lr0-p0 ip=192.168.10.100 mac="0 AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([LR NB Static_MAC_Binding garbage collection]) +ovn_start + +check ovn-nbctl lr-add lr -- lrp-add lr lr-lrp 00:00:00:00:00:01 1.1.1.1/24 +check ovn-nbctl static-mac-binding-add lr-lrp 1.1.1.2 00:00:00:00:00:02 +wait_row_count sb:Static_MAC_Binding 1 logical_port=lr-lrp ip=1.1.1.2 mac="00\:00\:00\:00\:00\:02" +check ovn-nbctl lr-del lr +wait_row_count sb:Static_MAC_Binding 0 + +AT_CLEANUP +]) + OVN_FOR_EACH_NORTHD_NO_HV([ AT_SETUP([LR neighbor lookup and learning flows]) ovn_start diff --git a/tests/ovn.at b/tests/ovn.at index ffd9f653e..d44a36be9 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1304,6 +1304,9 @@ ct_commit { ct_label=0x181716151413121110090807060504030201; }; 141-bit constant is not compatible with 128-bit field ct_label. ct_commit { ip4.dst = 192.168.0.1; }; Field ip4.dst is not modifiable. +reg8[17] = 1; ct_commit { ct_mark.blocked = 1; }; + encodes as set_field:0x2000000000000/0x2000000000000->xreg4,ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark)) + has prereqs ip # Legact ct_commit_v1 action. ct_commit(); @@ -5767,13 +5770,24 @@ for i in 1 2 3; do # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD sip=00000000000000000000000000000000 - test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 83 21 - test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 8f 21 - test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff0200000000000000ea2aeafffe2800 87 21 + # Multicast traffic is delivered to all ports, except for the source. + out_ports= + for j in 1 2 3; do + for k in 1 2 3; do + if test "${j}${k}" -eq "${i}3"; then + continue + else + out_ports="$out_ports ${j}${k}" + fi + done + done + test_icmpv6 ${i}3 f00000000${i}${i}3 333300160000 $sip ff020000000000000000000000160000 83 ${out_ports} + test_icmpv6 ${i}3 f00000000${i}${i}3 333300160000 $sip ff020000000000000000000000160000 8f ${out_ports} + test_icmpv6 ${i}3 f00000000${i}${i}3 3333fffe2800 $sip ff0200000000000000ea2aeafffe2800 87 ${out_ports} # Traffic to non-multicast traffic should be dropped test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 83 # Traffic of other ICMPv6 types should be dropped - test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 80 + test_icmpv6 ${i}3 f00000000${i}${i}3 333300160000 $sip ff020000000000000000000000160000 80 # should be dropped sip=ae80000000000000ea2aeafffe2800aa @@ -8428,7 +8442,7 @@ done # Complete Neighbor Solicitation packet and Neighbor Advertisement packet # vif1 -> NS -> vif2. vif1 <- NA <- ovn-controller. # vif2 will not receive NS packet, since ovn-controller will reply for it. -ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598fd81ce49a9480000f8163efffea1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598 +ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598ff0200000000000000000001ffa1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598 na_packet=fa163e940598fa163ea1f9ae86dd6000000000203afffd81ce49a9480000f8163efffea1f9aefd81ce49a9480000f8163efffe9405988800e9ed60000000fd81ce49a9480000f8163efffea1f9ae0201fa163ea1f9ae as hv1 ovs-appctl netdev-dummy/receive vif1 $ns_packet @@ -14131,7 +14145,7 @@ test_ns_na() { local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 packet=$(fmt_pkt " - Ether(dst='ff:ff:ff:ff:ff:ff', src='${src_mac}') / + Ether(dst='33:33:ff:ff:ff:ff', src='${src_mac}') / IPv6(src='${src_ip}', dst='ff02::1:ff00:2') / ICMPv6ND_NS(tgt='${dst_ip}') ") @@ -14171,8 +14185,8 @@ test_mldv2() { local inport=$1 outport=$2 src_mac=$3 src_ip=$4 packet=$(fmt_pkt " - Ether(dst='ff:ff:ff:ff:ff:ff', src='${src_mac}') / - IPv6(src='${src_ip}', dst='ff02::2') / + Ether(dst='33:33:00:00:00:01', src='${src_mac}') / + IPv6(src='${src_ip}', dst='ff02::1') / ICMPv6MLQuery2() ") as hv1 ovs-appctl netdev-dummy/receive vif${inport} $packet @@ -15451,14 +15465,17 @@ m4_define([MULTICHASSIS_PATH_MTU_DISCOVERY_TEST], second_mac=00:00:00:00:00:02 multi1_mac=00:00:00:00:00:f0 multi2_mac=00:00:00:00:00:f1 + external_mac=00:00:00:00:ee:ff first_ip=10.0.0.1 second_ip=10.0.0.2 multi1_ip=10.0.0.10 multi2_ip=10.0.0.20 + external_ip=10.0.0.30 first_ip6=abcd::1 second_ip6=abcd::2 multi1_ip6=abcd::f0 multi2_ip6=abcd::f1 + external_ip6=abcd::eeff check ovn-nbctl ls-add ls0 check ovn-nbctl lsp-add ls0 first @@ -15577,6 +15594,24 @@ m4_define([MULTICHASSIS_PATH_MTU_DISCOVERY_TEST], reset_env + AS_BOX([Multi with "unknown" to external doesn't produce wrong FDB]) + len=3000 + check ovn-nbctl --wait=hv lsp-set-addresses multi1 unknown + + packet=$(send_ip_packet multi1 1 $multi1_mac $external_mac $multi1_ip $external_ip $(payload $len) 1 ${expected_ip_mtu}) + echo $packet >> hv1/multi1.expected + + packet=$(send_ip6_packet multi1 1 $multi1_mac $external_mac $multi1_ip6 $external_ip6 $(payload $len) 1 ${expected_ip_mtu}) + echo $packet >> hv1/multi1.expected + + check_pkts + reset_env + + check_row_count fdb 0 mac="$external_mac" + ovn-sbctl --all destroy fdb + + check ovn-nbctl --wait=hv lsp-set-addresses multi1 "${multi1_mac} ${multi1_ip} ${multi1_ip6}" + AS_BOX([Packets of proper size are delivered from multichassis to regular ports]) len=1000 @@ -15676,9 +15711,6 @@ m4_define([MULTICHASSIS_PATH_MTU_DISCOVERY_TEST], packet=$(send_ip6_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip6 $multi2_ip6 $(payload $len) 1) echo $packet >> hv1/multi1.expected - check_pkts - reset_env - AS_BOX([MTU updates are honored in ICMP Path MTU calculation]) set_mtu() { @@ -26674,20 +26706,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. @@ -27428,7 +27450,14 @@ check ovs-vsctl add-port br-int vif3 -- set Interface vif3 external-ids:iface-id # Add a forwarding group on ls2 with lsp21 and lsp22 as child ports # virtual IP - 172.16.1.11, virtual MAC - 00:11:de:ad:be:ef check ovn-nbctl --wait=hv fwd-group-add fwd_grp1 ls2 172.16.1.11 00:11:de:ad:be:ef lsp21 lsp22 +check ovn-nbctl --wait=hv fwd-group-add fwd_grp2 ls2 172.16.2.11 00:22:de:ad:be:ef lsp21 lsp22 +# Check logical flow +AT_CAPTURE_FILE([sbflows]) +ovn-sbctl dump-flows > sbflows +AT_CHECK([grep ls_in_l2_lkup sbflows | grep fwd_group | wc -l], [0], [2 +]) +check ovn-nbctl --wait=hv fwd-group-del fwd_grp2 # Check logical flow AT_CAPTURE_FILE([sbflows]) ovn-sbctl dump-flows > sbflows @@ -32805,7 +32834,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep "${arp_proxy_ls1[[1]]}" | sed 's/table=../table=??/'], [0], [dnl - table=??(ls_in_arp_rsp ), priority=30 , match=(arp.op == 1 && dnl + table=??(ls_in_arp_rsp ), priority=30 , match=(reg0[[18]] == 0 && arp.op == 1 && dnl arp.tpa == {169.254.238.0/24,169.254.239.2/32}), dnl action=(eth.dst = eth.src; eth.src = 00:00:00:01:02:f1; arp.op = 2; dnl /* ARP reply */ arp.tha = arp.sha; arp.sha = 00:00:00:01:02:f1; dnl @@ -32818,7 +32847,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep "${arp_proxy_ls1[[3]]}" | sed 's/table=../table=??/'], [0], [dnl table=??(ls_in_arp_rsp ), priority=30 , dnl -match=(nd_ns && ip6.dst == { fd7b:6b4d:7b25:d22d::/64, ff02::1:ff00:0/64, dnl +match=(reg0[[18]] == 0 && nd_ns && ip6.dst == { fd7b:6b4d:7b25:d22d::/64, ff02::1:ff00:0/64, dnl fd7b:6b4d:7b25:d22f::1/128, ff02::1:ff00:1/128 } && dnl nd.target == { fd7b:6b4d:7b25:d22d::/64, fd7b:6b4d:7b25:d22f::1/128 }), dnl action=(nd_na_router { eth.src = 00:00:00:01:02:f1; ip6.src = nd.target; dnl @@ -32832,7 +32861,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep "${arp_proxy_ls2[[2]]}" | sed 's/table=../table=??/'], [0], [dnl table=??(ls_in_arp_rsp ), priority=30 , dnl -match=(arp.op == 1 && arp.tpa == {169.254.236.0/24,169.254.237.2/32}), dnl +match=(reg0[[18]] == 0 && arp.op == 1 && arp.tpa == {169.254.236.0/24,169.254.237.2/32}), dnl action=(eth.dst = eth.src; eth.src = 00:00:00:02:02:f1; arp.op = 2; dnl /* ARP reply */ arp.tha = arp.sha; arp.sha = 00:00:00:02:02:f1; dnl arp.tpa <-> arp.spa; outport = inport; flags.loopback = 1; output;) @@ -32844,7 +32873,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep "${arp_proxy_ls2[[4]]}" | sed 's/table=../table=??/'], [0], [dnl table=??(ls_in_arp_rsp ), priority=30 , dnl -match=(nd_ns && ip6.dst == { fd7b:6b4d:7b25:d22b::/64, ff02::1:ff00:0/64, dnl +match=(reg0[[18]] == 0 && nd_ns && ip6.dst == { fd7b:6b4d:7b25:d22b::/64, ff02::1:ff00:0/64, dnl fd7b:6b4d:7b25:d22c::1/128, ff02::1:ff00:1/128 } && dnl nd.target == { fd7b:6b4d:7b25:d22b::/64, fd7b:6b4d:7b25:d22c::1/128 }), dnl action=(nd_na_router { eth.src = 00:00:00:02:02:f1; ip6.src = nd.target; dnl @@ -35202,7 +35231,10 @@ check_default_flows() { # Check that every drop flow gets sampled. check_sample_drops() { - + hv=hv$1 + remote_hv=hv$((${1}%2 + 1)) + race_condition=$2 + ovs-vsctl destroy Flow_Sample_Collector_Set 123 check ovn-nbctl -- remove NB_Global . options debug_drop_collector_set \ -- remove NB_Global . options debug_drop_domain_id check ovn-nbctl --wait=hv sync @@ -35212,14 +35244,52 @@ check_sample_drops() { # Take match part of flows that contain "drop". drop_matches="$(grep 'drop' oflows_nosample | grep -oP 'table=\d*, priority=.* ')" + if [[ x$race_condition = x"true" ]]; then + sleep_controller $hv + # Get ofport used by the geneve interface + OVS_WAIT_UNTIL([ + ofport=$(as $hv ovs-vsctl --bare --columns ofport find Interface name=ovn-${remote_hv}-0) + test 1 -le $ofport + ]) + + # Add a vif while ovn-controller sleeps, and make it request the ofport used by the geneve interface. + # This is used to cause the geneve interface to change ofport. + ovs-vsctl -- add-port br-int vif3 -- set interface vif3\ + options:tx_pcap=${hv}/vif3-tx.pcap \ + options:rxq_pcap=${hv}/vif3-rx.pcap \ + ofport-request=$ofport + OVS_WAIT_UNTIL([ + vif_ofport=$(as $hv ovs-vsctl --bare --columns ofport find Interface name=vif3) + test 1 -le $vif_ofport + ]) + # For the geneve interface ofport change to happen... + ovs-vsctl -- add-port br-int vif4 -- set interface vif4\ + options:tx_pcap=${hv}/vif4-tx.pcap \ + options:rxq_pcap=${hv}/vif4-rx.pcap + OVS_WAIT_UNTIL([ + new_ofport=$(as $hv ovs-vsctl --bare --columns ofport find Interface name=ovn-${remote_hv}-0) + test $ofport -ne $new_ofport + ]) + fi + ovs-vsctl --id=@br get Bridge br-int -- \ --id=@i create IPFIX targets=\"192.168.1.1\" -- \ create Flow_Sample_Collector_Set bridge=@br id=123 ipfix=@i check ovn-nbctl -- set NB_Global . options:debug_drop_collector_set="123" \ -- set NB_Global . options:debug_drop_domain_id="1" - check ovn-nbctl --wait=hv sync + if [[ x$race_condition = x"true" ]]; then + # Wait sb as ovn-controller sleeps. + check ovn-nbctl --wait=sb sync + # Wake up ovn-controller. It should most of the times receive non-vif ofport change and sb changes at the same time. + wake_up_controller $hv + # Check twice ovn-controller is running to guarantee if run a full loop. + OVS_WAIT_UNTIL([test x$(as $hv ovn-appctl -t ovn-controller debug/status) = "xrunning"]) + OVS_WAIT_UNTIL([test x$(as $hv ovn-appctl -t ovn-controller debug/status) = "xrunning"]) + else + check ovn-nbctl --wait=hv sync + fi ovs-ofctl dump-flows --no-stats br-int > oflows_sample AT_CAPTURE_FILE([oflows_sample]) @@ -35227,6 +35297,8 @@ check_sample_drops() { save_IFS=$IFS IFS=$'\n' for flow in $drop_matches; do + # Restore IFS to avoid "printf %s\n: command not found" errors. + IFS=$save_IFS AT_CHECK([grep "${flow}actions=.*sample.*" oflows_sample], [0], [ignore], [ignore], [echo "Flow $flow has a drop and did not get sampled"]) done IFS=$save_IFS @@ -35239,9 +35311,9 @@ check_drops() { check_default_flows as hv1 - check_sample_drops + check_sample_drops 1 $1 as hv2 - check_sample_drops + check_sample_drops 2 $1 } # Logical network: @@ -35309,7 +35381,8 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \ wait_for_ports_up check ovn-nbctl --wait=hv sync -check_debug +check_drops +check_drops true # Add stateless ACL check ovn-nbctl --wait=sb \ @@ -35317,7 +35390,7 @@ check ovn-nbctl --wait=sb \ check ovn-nbctl --wait=sb \ -- acl-add ls2 from-lport 100 'ip4' allow-stateless -check_debug +check_drops check ovn-nbctl --wait=sb acl-del ls1 check ovn-nbctl --wait=sb acl-del ls2 @@ -35328,7 +35401,7 @@ check ovn-nbctl --wait=sb \ check ovn-nbctl --wait=sb \ -- acl-add ls2 from-lport 100 "udp" allow-related -check_debug +check_drops check ovn-nbctl --wait=sb acl-del ls1 check ovn-nbctl --wait=sb acl-del ls2 @@ -37663,9 +37736,9 @@ AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \ --ca-cert=$PKIDIR/testpki-cacert.pem \ --ssl-ciphers='HIGH:!aNULL:!MD5:@SECLEVEL=1' \ --ssl-protocols='TLSv1,TLSv1.1,TLSv1.2' \ - chassis-add ch vxlan 1.2.4.8], [1], [ignore], -[ovn-sbctl: transaction error: {"details":"insert operation not allowed when database server is in read only mode","error":"not allowed"} -]) + chassis-add ch vxlan 1.2.4.8 2>&1 | grep 'transaction error]', [0], [dnl +ovn-sbctl: transaction error: {"details":"insert operation not allowed when database server is in read only mode","error":"not allowed"} +], [ignore]) OVS_APP_EXIT_AND_WAIT([ovsdb-server]) AT_CLEANUP @@ -37840,3 +37913,171 @@ OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=1 OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +dnl This test checks that the megaflows translated by ovs-vswitchd +dnl don't match on IPv6 source and destination addresses for +dnl simple switching. +OVN_FOR_EACH_NORTHD([ +AT_SETUP([IPv6 switching - megaflow check for IPv6 src/dst matches]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +check ovn-nbctl ls-add sw0 + +check ovn-nbctl lsp-add sw0 vm0 +check ovn-nbctl lsp-set-addresses vm0 "f0:00:0f:01:02:03 10.0.0.3 1000::3" + +check ovn-nbctl lsp-add sw0 vm1 +check ovn-nbctl lsp-set-addresses vm1 "f0:00:0f:01:02:04 10.0.0.4 1000::4" + +check ovn-nbctl lr-add lr0 +check ovn-nbctl lrp-add lr0 lr0-sw0 fa:16:3e:00:00:01 10.0.0.1 1000::1/64 +check ovn-nbctl lsp-add sw0 sw0-lr0 +check ovn-nbctl lsp-set-type sw0-lr0 router +check ovn-nbctl lsp-set-addresses sw0-lr0 router +check ovn-nbctl --wait=hv lsp-set-options sw0-lr0 router-port=lr0-sw0 + +net_add n1 +sim_add hv +as hv +check 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=vm0 \ + options:tx_pcap=hv/vif1-tx.pcap \ + options:rxq_pcap=hv/vif1-rx.pcap \ + ofport-request=1 +check ovs-vsctl add-port br-int vif2 -- \ + set Interface vif2 external-ids:iface-id=vm1 \ + options:tx_pcap=hv/vif2-tx.pcap \ + options:rxq_pcap=hv/vif2-rx.pcap \ + ofport-request=2 + +check ovn-nbctl --wait=sb sync +wait_for_ports_up + +AS_BOX([No port security, to vm1]) +packet=$(fmt_pkt "Ether(dst='f0:00:0f:01:02:04', src='f0:00:0f:01:02:03')/ \ + IPv6(dst='1000::4', src='1000::3')/ \ + UDP(sport=53, dport=4369)") + +as hv +ovs-appctl ofproto/trace br-int in_port=1 $packet > vm0_ip6_ofproto_trace.txt +ovs-appctl netdev-dummy/receive vif1 $packet + +AT_CAPTURE_FILE([vm0_ip6_ofproto_trace.txt]) + +AT_CHECK([grep Megaflow vm0_ip6_ofproto_trace.txt | grep -e ipv6_src -e ipv6_dst -c], [1], [dnl +0 +]) + +dnl Make sure that the packet was received by vm1. This ensures that the +dnl packet was delivered as expected and the megaflow didn't have any matches +dnl on IPv6 src or dst. + +echo $packet >> expected-vif2 +OVN_CHECK_PACKETS([hv/vif2-tx.pcap], [expected-vif2]) + +AS_BOX([No port security, to vm0]) +packet=$(fmt_pkt "Ether(dst='f0:00:0f:01:02:03', src='f0:00:0f:01:02:04')/ \ + IPv6(dst='1000::3', src='1000::4')/ \ + UDP(sport=53, dport=4369)") + +as hv +ovs-appctl ofproto/trace br-int in_port=2 $packet > vm1_ip6_ofproto_trace.txt +ovs-appctl netdev-dummy/receive vif2 $packet + +AT_CAPTURE_FILE([vm1_ip6_ofproto_trace.txt]) + +AT_CHECK([grep Megaflow vm0_ip6_ofproto_trace.txt | grep -e ipv6_src -e ipv6_dst -c], [1], [dnl +0 +]) + +dnl Make sure that the packet was received by vm0. This ensures that the +dnl packet was delivered as expected and the megaflow didn't have any matches +dnl on IPv6 src or dst. +echo $packet >> expected-vif1 +OVN_CHECK_PACKETS([hv/vif1-tx.pcap], [expected-vif1]) + +AS_BOX([With port security, to vm1]) +dnl Add port security to vm0. The megaflow should now match on ipv6 src/dst. +check ovn-nbctl lsp-set-port-security vm0 "f0:00:0f:01:02:03 10.0.0.3 1000::3" +check ovn-nbctl --wait=hv sync + +packet=$(fmt_pkt "Ether(dst='f0:00:0f:01:02:04', src='f0:00:0f:01:02:03')/ \ + IPv6(dst='1000::4', src='1000::3')/ \ + UDP(sport=53, dport=4369)") + +as hv +ovs-appctl ofproto/trace br-int in_port=1 $packet > vm0_ip6_ofproto_trace.txt +ovs-appctl netdev-dummy/receive vif1 $packet + +AT_CAPTURE_FILE([vm0_ip6_ofproto_trace.txt]) + +AT_CHECK([grep Megaflow vm0_ip6_ofproto_trace.txt | grep -e ipv6_src -e ipv6_dst -c], [0], [dnl +1 +]) + +dnl Make sure that the packet was received by vm1. +echo $packet >> expected-vif2 +OVN_CHECK_PACKETS([hv/vif2-tx.pcap], [expected-vif2]) + +AS_BOX([Clear port security, to vm1]) +dnl Clear port security. +check ovn-nbctl lsp-set-port-security vm0 "" +check ovn-nbctl --wait=hv sync + +as hv +ovs-appctl ofproto/trace br-int in_port=1 $packet > vm0_ip6_ofproto_trace.txt +ovs-appctl netdev-dummy/receive vif1 $packet + +AT_CAPTURE_FILE([vm0_ip6_ofproto_trace.txt]) + +AT_CHECK([grep Megaflow vm0_ip6_ofproto_trace.txt | grep -e ipv6_src -e ipv6_dst -c], [1], [dnl +0 +]) + +dnl Make sure that the packet was received by vm1. +echo $packet >> expected-vif2 +OVN_CHECK_PACKETS([hv/vif2-tx.pcap], [expected-vif2]) + +AS_BOX([With proxy arp/nd, to vm1]) +dnl Configure proxy arp/nd on the router port. The megaflow should now match +dnl on ipv6 src/dst. +check ovn-nbctl --wait=hv lsp-set-options sw0-lr0 router-port=lr0-sw0 arp_proxy="2000::1/64" + +as hv +ovs-appctl ofproto/trace br-int in_port=1 $packet > vm0_ip6_ofproto_trace.txt +ovs-appctl netdev-dummy/receive vif1 $packet + +AT_CAPTURE_FILE([vm0_ip6_ofproto_trace.txt]) + +AT_CHECK([grep Megaflow vm0_ip6_ofproto_trace.txt | grep -e ipv6_src -e ipv6_dst -c], [0], [dnl +1 +]) + +dnl Make sure that the packet was received by vm1. +echo $packet >> expected-vif2 +OVN_CHECK_PACKETS([hv/vif2-tx.pcap], [expected-vif2]) + +AS_BOX([With proxy arp/nd, to vm0]) +packet=$(fmt_pkt "Ether(dst='f0:00:0f:01:02:03', src='f0:00:0f:01:02:04')/ \ + IPv6(dst='1000::3', src='1000::4')/ \ + UDP(sport=53, dport=4369)") + +as hv +ovs-appctl ofproto/trace br-int in_port=2 $packet > vm1_ip6_ofproto_trace.txt +ovs-appctl netdev-dummy/receive vif2 $packet + +AT_CAPTURE_FILE([vm1_ip6_ofproto_trace.txt]) + +AT_CHECK([grep Megaflow vm0_ip6_ofproto_trace.txt | grep -e ipv6_src -e ipv6_dst -c], [0], [dnl +1 +]) + +dnl Make sure that the packet was received by vm0. +echo $packet >> expected-vif1 +OVN_CHECK_PACKETS([hv/vif1-tx.pcap], [expected-vif1]) + +AT_CLEANUP +]) diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 463075ac0..28474ed66 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -10628,7 +10628,7 @@ check ovn-nbctl ls-add bar # Connect foo to R1 check ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24 check ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \ - type=router options:arp_proxy="0a:58:a9:fe:01:01 169.254.239.254 169.254.239.2 169.254.238.0/24 192.168.1.100" options:router-port=foo addresses='"router"' + type=router options:arp_proxy="0a:58:a9:fe:01:01 169.254.239.254 169.254.239.2 169.254.238.0/24 192.168.1.100 192.168.1.200" options:router-port=foo addresses='"router"' # Connect bar to R1 check ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24 @@ -10657,6 +10657,12 @@ ADD_VETH(foo3, foo3, br-int, "192.168.1.4/24", "f0:00:00:01:02:05", \ check ovn-nbctl lsp-add foo foo3 \ -- lsp-set-addresses foo3 "f0:00:00:01:02:05 192.168.1.4" +ADD_NAMESPACES(foo4) +ADD_VETH(foo4, foo4, br-int, "192.168.1.6/24", "f0:00:00:01:02:11", \ + "192.168.1.1") +check ovn-nbctl lsp-add foo foo4 \ +-- lsp-set-addresses foo4 "f0:00:00:01:02:11 192.168.1.6" + # Logical port 'ext1' in switch 'foo' ADD_NAMESPACES(ext1) ADD_VETH(ext1, ext1, br-ext, "192.168.1.5/24", "f0:00:00:01:02:06", \ @@ -10672,6 +10678,12 @@ ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:07", \ check ovn-nbctl lsp-add bar bar1 \ -- lsp-set-addresses bar1 "f0:00:00:01:02:07 192.168.2.2" +ADD_NAMESPACES(bar2) +ADD_VETH(bar2, bar2, br-int, "192.168.2.3/24", "f0:00:00:01:02:10", \ +"192.168.2.1") +check ovn-nbctl lsp-add bar bar2 \ +-- lsp-set-addresses bar2 "f0:00:00:01:10:10 192.168.2.3" + # wait for ovn-controller to catch up. check ovn-nbctl --wait=hv sync @@ -10723,6 +10735,14 @@ OVS_WAIT_UNTIL([ test "${total_pkts}" = "3" ]) +check ovn-nbctl lr-route-add R1 169.254.240.0/24 192.168.1.200 +NETNS_START_TCPDUMP([foo4], [-nn -c 4 -e -i foo4 arp[[24:4]]=0xc0a801c8], [foo4-arp]) + +NS_CHECK_EXEC([bar2], [ping -q -c 5 -i 0.3 -w 2 169.254.240.10],[ignore],[ignore]) +OVS_WAIT_UNTIL([ + total_pkts=$(cat foo4-arp.tcpdump| wc -l) + test "${total_pkts}" = "4" +]) OVS_APP_EXIT_AND_WAIT([ovn-controller]) @@ -11183,7 +11203,25 @@ check_ovn_installed check_ports_up check_ports_bound -OVS_APP_EXIT_AND_WAIT([ovn-controller]) +AS_BOX(["Leave some ovn-installed while closing ovn-controller"]) +# Block IDL from ovn-controller to OVSDB +stop_ovsdb_controller_updates $TCP_PORT +remove_iface_id vif2 +ensure_controller_run + +# OVSDB should now be seen as read-only by ovn-controller +remove_iface_id vif1 +check ovn-nbctl --wait=hv sync + +# Stop ovsdb before ovn-controller to ensure it's not updated +as +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d +/connection dropped.*/d"]) + +# Don't use OVS_APP_EXIT... to use --restart to avoid cleaning up the databases. +TMPPID=$(cat $OVS_RUNDIR/ovn-controller.pid) +check ovs-appctl -t ovn-controller exit --restart +OVS_WAIT_WHILE([kill -0 $TMPPID 2>/dev/null]) as ovn-sb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) @@ -11194,9 +11232,6 @@ OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as northd OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) -as -OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -/connection dropped.*/d"]) AT_CLEANUP ]) diff --git a/utilities/automake.mk b/utilities/automake.mk index 6a2b96e66..b7d2ebeef 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -41,6 +41,7 @@ EXTRA_DIST += \ utilities/checkpatch.py \ utilities/containers/Makefile \ utilities/containers/py-requirements.txt \ + utilities/containers/prepare.sh \ utilities/containers/fedora/Dockerfile \ utilities/containers/ubuntu/Dockerfile \ utilities/docker/Makefile \ diff --git a/utilities/containers/fedora/Dockerfile b/utilities/containers/fedora/Dockerfile index c11ea37b7..f5852378c 100755 --- a/utilities/containers/fedora/Dockerfile +++ b/utilities/containers/fedora/Dockerfile @@ -27,6 +27,7 @@ RUN dnf -y update \ libcap-ng-devel \ libtool \ net-tools \ + nftables \ nmap-ncat \ openssl \ openssl-devel \ @@ -44,23 +45,12 @@ RUN dnf -y update \ && \ dnf clean all -# Compile sparse from source -WORKDIR /workspace/sparse - -RUN git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git \ - /workspace/sparse \ - && \ - make -j4 PREFIX=/usr HAVE_LLVM= HAVE_SQLITE= install - WORKDIR /workspace COPY $CONTAINERS_PATH/py-requirements.txt /tmp/py-requirements.txt -# Update and install pip dependencies -RUN python3 -m pip install --upgrade pip \ - && \ - python3 -m pip install wheel \ - && \ - python3 -m pip install -r /tmp/py-requirements.txt +COPY $CONTAINERS_PATH/prepare.sh /tmp/prepare.sh + +RUN /tmp/prepare.sh CMD ["/usr/sbin/init"] diff --git a/utilities/containers/prepare.sh b/utilities/containers/prepare.sh new file mode 100755 index 000000000..d3e8c4253 --- /dev/null +++ b/utilities/containers/prepare.sh @@ -0,0 +1,22 @@ +#!/bin/bash -xe + +function compile_sparse() +{ + git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git \ + /workspace/sparse + + pushd sparse + make -j4 PREFIX=/usr HAVE_LLVM= HAVE_SQLITE= install + popd +} + +function install_python_dep() +{ + # The --user should be removed once pip can be upgraded on Ubuntu. + python3 -m pip install --user --upgrade pip + python3 -m pip install wheel + python3 -m pip install -r /tmp/py-requirements.txt +} + +compile_sparse +install_python_dep diff --git a/utilities/containers/ubuntu/Dockerfile b/utilities/containers/ubuntu/Dockerfile index 3c7fe7775..4e9599004 100755 --- a/utilities/containers/ubuntu/Dockerfile +++ b/utilities/containers/ubuntu/Dockerfile @@ -32,6 +32,7 @@ RUN apt update -y \ llvm-dev \ ncat \ net-tools \ + nftables \ python3-dev \ python3-pip \ selinux-policy-dev \ @@ -43,23 +44,12 @@ RUN apt update -y \ && \ apt clean -# Compile sparse from source -WORKDIR /workspace/sparse - -RUN git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git \ - /workspace/sparse \ - && \ - make -j4 PREFIX=/usr HAVE_LLVM= HAVE_SQLITE= install - WORKDIR /workspace COPY $CONTAINERS_PATH/py-requirements.txt /tmp/py-requirements.txt -# Update and install pip dependencies -RUN python3 -m pip install --upgrade pip \ - && \ - python3 -m pip install wheel \ - && \ - python3 -m pip install -r /tmp/py-requirements.txt +COPY $CONTAINERS_PATH/prepare.sh /tmp/prepare.sh + +RUN /tmp/prepare.sh CMD ["/sbin/init"]