On Mon, Apr 22, 2024 at 11:14 AM Ales Musil <amu...@redhat.com> wrote:
> On Fri, Apr 19, 2024 at 6:38 PM Numan Siddique <num...@ovn.org> wrote: > > > > > > > On Fri, Apr 19, 2024 at 7:09 AM Ales Musil <amu...@redhat.com> wrote: > > > >> The current packet injection loses ct_state in the process. When > >> the ct_state is lost we might commit to DNAT zone and perform > >> zero SNAT after the packet injection. This causes the first session > >> to be wrong as the reply packets are not unDNATted. > >> > >> Instead of re-injecting the packet back into the pipeline when > >> we get the MAC binding, use paused controller action. The paused > >> controller action stores ct_state, which is important for the behavior > >> of the resumed packet. > >> > >> At the same time bump the OvS submodule latest branch-3.3. This is > >> mainly for [0], which fixes metering for paused controller actions. > >> > >> In order to make sure that the paused action works during upgrade add > >> the output implicitly. Once the upgrade is done northd will create > option > >> to inform controllers that the implicit action is no longer needed. > >> > >> [0] c560f6ca3257 ("ofproto-dpif-xlate: Fix continuations with associated > >> metering.") > >> > >> Reported-at: https://issues.redhat.com/browse/FDP-439 > >> Signed-off-by: Ales Musil <amu...@redhat.com> > >> --- > >> v5: Rebase on top of current main. > >> v4: Fix copy paste error in the global_handler. > >> v3: Rebase on top of current main. > >> Add flag to ensure that the paused action works during upgrade. > >> v2: Fix the Jira link and add ack from Mark. > >> > > > > Thanks. I applied this patch to the main. > > It doesn't apply cleanly to branch-24.03. Please submit a backport patch > > for branches - 24.03 and 23.09. > > > > Forgot to reply earlier, the backports are up on ML. > Thanks. Applied. Numan > > > Numan > > > > > > --- > >> controller/lflow.c | 1 + > >> controller/lflow.h | 1 + > >> controller/mac-learn.c | 30 ++++++++---- > >> controller/mac-learn.h | 9 ++-- > >> controller/ovn-controller.c | 21 ++++++++ > >> controller/pinctrl.c | 64 +++++++++---------------- > >> include/ovn/actions.h | 3 ++ > >> lib/actions.c | 47 +++++++++++++++++- > >> northd/en-global-config.c | 4 ++ > >> northd/northd.c | 6 +-- > >> tests/multinode.at | 8 ++++ > >> tests/ovn-northd.at | 3 ++ > >> tests/ovn.at | 8 ++-- > >> tests/system-ovn.at | 95 +++++++++++++++++++++++++++++++++++++ > >> tests/test-ovn.c | 1 + > >> 15 files changed, 239 insertions(+), 62 deletions(-) > >> > >> diff --git a/controller/lflow.c b/controller/lflow.c > >> index 895d17d19..760ec0b41 100644 > >> --- a/controller/lflow.c > >> +++ b/controller/lflow.c > >> @@ -874,6 +874,7 @@ add_matches_to_flow_table(const struct > >> sbrec_logical_flow *lflow, > >> .collector_ids = l_ctx_in->collector_ids, > >> .lflow_uuid = lflow->header_.uuid, > >> .dp_key = ldp->datapath->tunnel_key, > >> + .explicit_arp_ns_output = l_ctx_in->explicit_arp_ns_output, > >> > >> .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS, > >> .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE, > >> diff --git a/controller/lflow.h b/controller/lflow.h > >> index 9b7ffa19c..295d004f4 100644 > >> --- a/controller/lflow.h > >> +++ b/controller/lflow.h > >> @@ -130,6 +130,7 @@ struct lflow_ctx_in { > >> bool lb_hairpin_use_ct_mark; > >> bool localnet_learn_fdb; > >> bool localnet_learn_fdb_changed; > >> + bool explicit_arp_ns_output; > >> }; > >> > >> struct lflow_ctx_out { > >> diff --git a/controller/mac-learn.c b/controller/mac-learn.c > >> index 071f01b4f..0c3b60c23 100644 > >> --- a/controller/mac-learn.c > >> +++ b/controller/mac-learn.c > >> @@ -199,15 +199,24 @@ ovn_fdb_add(struct hmap *fdbs, uint32_t dp_key, > >> struct eth_addr mac, > >> /* packet buffering functions */ > >> > >> struct packet_data * > >> -ovn_packet_data_create(struct ofpbuf ofpacts, > >> - const struct dp_packet *original_packet) > >> +ovn_packet_data_create(const struct ofputil_packet_in *pin, > >> + const struct ofpbuf *continuation) > >> { > >> struct packet_data *pd = xmalloc(sizeof *pd); > >> > >> - pd->ofpacts = ofpacts; > >> - /* clone the packet to send it later with correct L2 address */ > >> - pd->p = dp_packet_clone_data(dp_packet_data(original_packet), > >> - dp_packet_size(original_packet)); > >> + pd->pin = (struct ofputil_packet_in) { > >> + .packet = xmemdup(pin->packet, pin->packet_len), > >> + .packet_len = pin->packet_len, > >> + .flow_metadata = pin->flow_metadata, > >> + .reason = pin->reason, > >> + .table_id = pin->table_id, > >> + .cookie = pin->cookie, > >> + /* Userdata are empty on purpose, > >> + * it is not needed for the continuation. */ > >> + .userdata = NULL, > >> + .userdata_len = 0, > >> + }; > >> + pd->continuation = ofpbuf_clone(continuation); > >> > >> return pd; > >> } > >> @@ -216,8 +225,8 @@ ovn_packet_data_create(struct ofpbuf ofpacts, > >> void > >> ovn_packet_data_destroy(struct packet_data *pd) > >> { > >> - dp_packet_delete(pd->p); > >> - ofpbuf_uninit(&pd->ofpacts); > >> + free(pd->pin.packet); > >> + ofpbuf_delete(pd->continuation); > >> free(pd); > >> } > >> > >> @@ -307,7 +316,10 @@ ovn_buffered_packets_ctx_run(struct > >> buffered_packets_ctx *ctx, > >> > >> struct packet_data *pd; > >> LIST_FOR_EACH_POP (pd, node, &bp->queue) { > >> - struct eth_header *eth = dp_packet_data(pd->p); > >> + struct dp_packet packet; > >> + dp_packet_use_const(&packet, pd->pin.packet, > >> pd->pin.packet_len); > >> + > >> + struct eth_header *eth = dp_packet_data(&packet); > >> eth->eth_dst = mac; > >> > >> ovs_list_push_back(&ctx->ready_packets_data, &pd->node); > >> diff --git a/controller/mac-learn.h b/controller/mac-learn.h > >> index e0fd6a8d1..20a015e1a 100644 > >> --- a/controller/mac-learn.h > >> +++ b/controller/mac-learn.h > >> @@ -24,6 +24,7 @@ > >> #include "openvswitch/hmap.h" > >> #include "openvswitch/list.h" > >> #include "openvswitch/ofpbuf.h" > >> +#include "openvswitch/ofp-packet.h" > >> > >> struct ovsdb_idl_index; > >> > >> @@ -91,8 +92,8 @@ struct fdb_entry *ovn_fdb_add(struct hmap *fdbs, > >> struct packet_data { > >> struct ovs_list node; > >> > >> - struct ofpbuf ofpacts; > >> - struct dp_packet *p; > >> + struct ofpbuf *continuation; > >> + struct ofputil_packet_in pin; > >> }; > >> > >> struct buffered_packets { > >> @@ -120,8 +121,8 @@ struct buffered_packets_ctx { > >> }; > >> > >> struct packet_data * > >> -ovn_packet_data_create(struct ofpbuf ofpacts, > >> - const struct dp_packet *original_packet); > >> +ovn_packet_data_create(const struct ofputil_packet_in *pin, > >> + const struct ofpbuf *continuation); > >> void ovn_packet_data_destroy(struct packet_data *pd); > >> struct buffered_packets * > >> ovn_buffered_packets_add(struct buffered_packets_ctx *ctx, uint64_t > >> dp_key, > >> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > >> index b84f6dfd4..23269af83 100644 > >> --- a/controller/ovn-controller.c > >> +++ b/controller/ovn-controller.c > >> @@ -3668,6 +3668,7 @@ non_vif_data_ovs_iface_handler(struct engine_node > >> *node, void *data OVS_UNUSED) > >> > >> struct ed_type_northd_options { > >> bool lb_hairpin_use_ct_mark; > >> + bool explicit_arp_ns_output; > >> }; > >> > >> > >> @@ -3698,6 +3699,13 @@ en_northd_options_run(struct engine_node *node, > >> void *data) > >> ? smap_get_bool(&sb_global->options, "lb_hairpin_use_ct_mark", > >> DEFAULT_SB_GLOBAL_LB_HAIRPIN_USE_CT_MARK) > >> : DEFAULT_SB_GLOBAL_LB_HAIRPIN_USE_CT_MARK; > >> + > >> + n_opts->explicit_arp_ns_output = > >> + sb_global > >> + ? smap_get_bool(&sb_global->options, > >> "arp_ns_explicit_output", > >> + false) > >> + : false; > >> + > >> engine_set_node_state(node, EN_UPDATED); > >> } > >> > >> @@ -3720,6 +3728,18 @@ en_northd_options_sb_sb_global_handler(struct > >> engine_node *node, void *data) > >> n_opts->lb_hairpin_use_ct_mark = lb_hairpin_use_ct_mark; > >> engine_set_node_state(node, EN_UPDATED); > >> } > >> + > >> + bool explicit_arp_ns_output = > >> + sb_global > >> + ? smap_get_bool(&sb_global->options, > >> "arp_ns_explicit_output", > >> + false) > >> + : false; > >> + > >> + if (explicit_arp_ns_output != n_opts->explicit_arp_ns_output) { > >> + n_opts->explicit_arp_ns_output = explicit_arp_ns_output; > >> + engine_set_node_state(node, EN_UPDATED); > >> + } > >> + > >> return true; > >> } > >> > >> @@ -3949,6 +3969,7 @@ init_lflow_ctx(struct engine_node *node, > >> l_ctx_in->localnet_learn_fdb_changed = > >> rt_data->localnet_learn_fdb_changed; > >> l_ctx_in->chassis_tunnels = &non_vif_data->chassis_tunnels; > >> l_ctx_in->lb_hairpin_use_ct_mark = n_opts->lb_hairpin_use_ct_mark; > >> + l_ctx_in->explicit_arp_ns_output = n_opts->explicit_arp_ns_output; > >> l_ctx_in->nd_ra_opts = &fo->nd_ra_opts; > >> l_ctx_in->dhcp_opts = &dhcp_opts->v4_opts; > >> l_ctx_in->dhcpv6_opts = &dhcp_opts->v6_opts; > >> diff --git a/controller/pinctrl.c b/controller/pinctrl.c > >> index 327ac0335..aa73facbf 100644 > >> --- a/controller/pinctrl.c > >> +++ b/controller/pinctrl.c > >> @@ -258,9 +258,9 @@ static void pinctrl_handle_put_nd_ra_opts( > >> struct ofpbuf *continuation); > >> static void pinctrl_handle_nd_ns(struct rconn *swconn, > >> const struct flow *ip_flow, > >> - struct dp_packet *pkt_in, > >> - const struct match *md, > >> - struct ofpbuf *userdata); > >> + const struct ofputil_packet_in *pin, > >> + struct ofpbuf *userdata, > >> + const struct ofpbuf *continuation); > >> static void pinctrl_handle_put_icmp_frag_mtu(struct rconn *swconn, > >> const struct flow > *in_flow, > >> struct dp_packet *pkt_in, > >> @@ -1534,11 +1534,13 @@ destroy_buffered_packets_ctx(void) > >> > >> /* Called with in the pinctrl_handler thread context. */ > >> static void > >> -pinctrl_handle_buffered_packets(struct dp_packet *pkt_in, > >> - const struct match *md, bool is_arp) > >> +pinctrl_handle_buffered_packets(const struct ofputil_packet_in *pin, > >> + const struct ofpbuf *continuation, > >> + bool is_arp) > >> OVS_REQUIRES(pinctrl_mutex) > >> { > >> struct in6_addr ip; > >> + const struct match *md = &pin->flow_metadata; > >> uint64_t dp_key = ntohll(md->flow.metadata); > >> uint64_t oport_key = md->flow.regs[MFF_LOG_OUTPORT - MFF_REG0]; > >> > >> @@ -1556,20 +1558,7 @@ OVS_REQUIRES(pinctrl_mutex) > >> return; > >> } > >> > >> - struct ofpbuf ofpacts; > >> - ofpbuf_init(&ofpacts, 4096); > >> - reload_metadata(&ofpacts, md); > >> - /* reload pkt_mark field */ > >> - const struct mf_field *pkt_mark_field = mf_from_id(MFF_PKT_MARK); > >> - union mf_value pkt_mark_value; > >> - mf_get_value(pkt_mark_field, &md->flow, &pkt_mark_value); > >> - ofpact_put_set_field(&ofpacts, pkt_mark_field, &pkt_mark_value, > >> NULL); > >> - > >> - struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); > >> - resubmit->in_port = OFPP_CONTROLLER; > >> - resubmit->table_id = OFTABLE_OUTPUT_INIT; > >> - > >> - struct packet_data *pd = ovn_packet_data_create(ofpacts, pkt_in); > >> + struct packet_data *pd = ovn_packet_data_create(pin, continuation); > >> ovn_buffered_packets_packet_data_enqueue(bp, pd); > >> > >> /* There is a chance that the MAC binding was already created. */ > >> @@ -1579,8 +1568,8 @@ OVS_REQUIRES(pinctrl_mutex) > >> /* Called with in the pinctrl_handler thread context. */ > >> static void > >> pinctrl_handle_arp(struct rconn *swconn, const struct flow *ip_flow, > >> - struct dp_packet *pkt_in, > >> - const struct match *md, struct ofpbuf *userdata) > >> + const struct ofputil_packet_in *pin, > >> + struct ofpbuf *userdata, const struct ofpbuf > >> *continuation) > >> { > >> /* This action only works for IP packets, and the switch should > only > >> send > >> * us IP packets this way, but check here just to be sure. */ > >> @@ -1592,7 +1581,7 @@ pinctrl_handle_arp(struct rconn *swconn, const > >> struct flow *ip_flow, > >> } > >> > >> ovs_mutex_lock(&pinctrl_mutex); > >> - pinctrl_handle_buffered_packets(pkt_in, md, true); > >> + pinctrl_handle_buffered_packets(pin, continuation, true); > >> ovs_mutex_unlock(&pinctrl_mutex); > >> > >> /* Compose an ARP packet. */ > >> @@ -1617,7 +1606,8 @@ pinctrl_handle_arp(struct rconn *swconn, const > >> struct flow *ip_flow, > >> ip_flow->vlans[0].tci); > >> } > >> > >> - set_actions_and_enqueue_msg(swconn, &packet, md, userdata); > >> + set_actions_and_enqueue_msg(swconn, &packet, > >> + &pin->flow_metadata, userdata); > >> dp_packet_uninit(&packet); > >> } > >> > >> @@ -3294,8 +3284,7 @@ process_packet_in(struct rconn *swconn, const > >> struct ofp_header *msg) > >> > >> switch (ntohl(ah->opcode)) { > >> case ACTION_OPCODE_ARP: > >> - pinctrl_handle_arp(swconn, &headers, &packet, > &pin.flow_metadata, > >> - &userdata); > >> + pinctrl_handle_arp(swconn, &headers, &pin, &userdata, > >> &continuation); > >> break; > >> case ACTION_OPCODE_IGMP: > >> pinctrl_ip_mcast_handle(swconn, &headers, &packet, > >> &pin.flow_metadata, > >> @@ -3361,8 +3350,7 @@ process_packet_in(struct rconn *swconn, const > >> struct ofp_header *msg) > >> break; > >> > >> case ACTION_OPCODE_ND_NS: > >> - pinctrl_handle_nd_ns(swconn, &headers, &packet, > >> &pin.flow_metadata, > >> - &userdata); > >> + pinctrl_handle_nd_ns(swconn, &headers, &pin, &userdata, > >> &continuation); > >> break; > >> > >> case ACTION_OPCODE_ICMP: > >> @@ -4375,16 +4363,8 @@ send_mac_binding_buffered_pkts(struct rconn > >> *swconn) > >> > >> struct packet_data *pd; > >> LIST_FOR_EACH_POP (pd, node, > >> &buffered_packets_ctx.ready_packets_data) { > >> - struct ofputil_packet_out po = { > >> - .packet = dp_packet_data(pd->p), > >> - .packet_len = dp_packet_size(pd->p), > >> - .buffer_id = UINT32_MAX, > >> - .ofpacts = pd->ofpacts.data, > >> - .ofpacts_len = pd->ofpacts.size, > >> - }; > >> - match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER); > >> - queue_msg(swconn, ofputil_encode_packet_out(&po, proto)); > >> - > >> + queue_msg(swconn, ofputil_encode_resume(&pd->pin, > >> pd->continuation, > >> + proto)); > >> ovn_packet_data_destroy(pd); > >> } > >> > >> @@ -6318,8 +6298,9 @@ pinctrl_handle_nd_na(struct rconn *swconn, const > >> struct flow *ip_flow, > >> /* Called with in the pinctrl_handler thread context. */ > >> static void > >> pinctrl_handle_nd_ns(struct rconn *swconn, const struct flow *ip_flow, > >> - struct dp_packet *pkt_in, > >> - const struct match *md, struct ofpbuf *userdata) > >> + const struct ofputil_packet_in *pin, > >> + struct ofpbuf *userdata, > >> + const struct ofpbuf *continuation) > >> { > >> /* This action only works for IPv6 packets. */ > >> if (get_dl_type(ip_flow) != htons(ETH_TYPE_IPV6)) { > >> @@ -6329,7 +6310,7 @@ pinctrl_handle_nd_ns(struct rconn *swconn, const > >> struct flow *ip_flow, > >> } > >> > >> ovs_mutex_lock(&pinctrl_mutex); > >> - pinctrl_handle_buffered_packets(pkt_in, md, false); > >> + pinctrl_handle_buffered_packets(pin, continuation, false); > >> ovs_mutex_unlock(&pinctrl_mutex); > >> > >> uint64_t packet_stub[128 / 8]; > >> @@ -6342,7 +6323,8 @@ pinctrl_handle_nd_ns(struct rconn *swconn, const > >> struct flow *ip_flow, > >> &ip_flow->ipv6_dst); > >> > >> /* Reload previous packet metadata and set actions from userdata. > */ > >> - set_actions_and_enqueue_msg(swconn, &packet, md, userdata); > >> + set_actions_and_enqueue_msg(swconn, &packet, > >> + &pin->flow_metadata, userdata); > >> dp_packet_uninit(&packet); > >> } > >> > >> diff --git a/include/ovn/actions.h b/include/ovn/actions.h > >> index 8e794450c..f697dff39 100644 > >> --- a/include/ovn/actions.h > >> +++ b/include/ovn/actions.h > >> @@ -854,6 +854,9 @@ struct ovnact_encode_params { > >> /* The datapath key. */ > >> uint32_t dp_key; > >> > >> + /* Indication if we should add explicit output after arp/nd_ns > >> action. */ > >> + bool explicit_arp_ns_output; > >> + > >> /* OVN maps each logical flow table (ltable), one-to-one, onto a > >> physical > >> * OpenFlow flow table (ptable). A number of parameters describe > >> this > >> * mapping and data related to flow tables: > >> diff --git a/lib/actions.c b/lib/actions.c > >> index 39bb5bc8a..361d55009 100644 > >> --- a/lib/actions.c > >> +++ b/lib/actions.c > >> @@ -1836,6 +1836,44 @@ format_REJECT(const struct ovnact_nest *nest, > >> struct ds *s) > >> format_nested_action(nest, "reject", s); > >> } > >> > >> +static bool > >> +is_paused_nested_action(enum action_opcode opcode) > >> +{ > >> + switch (opcode) { > >> + case ACTION_OPCODE_ARP: > >> + case ACTION_OPCODE_ND_NS: > >> + return true; > >> + case ACTION_OPCODE_IGMP: > >> + case ACTION_OPCODE_PUT_ARP: > >> + case ACTION_OPCODE_PUT_DHCP_OPTS: > >> + case ACTION_OPCODE_ND_NA: > >> + case ACTION_OPCODE_ND_NA_ROUTER: > >> + case ACTION_OPCODE_PUT_ND: > >> + case ACTION_OPCODE_PUT_FDB: > >> + case ACTION_OPCODE_PUT_DHCPV6_OPTS: > >> + case ACTION_OPCODE_DNS_LOOKUP: > >> + case ACTION_OPCODE_LOG: > >> + case ACTION_OPCODE_PUT_ND_RA_OPTS: > >> + case ACTION_OPCODE_ICMP: > >> + case ACTION_OPCODE_ICMP4_ERROR: > >> + case ACTION_OPCODE_ICMP6_ERROR: > >> + case ACTION_OPCODE_TCP_RESET: > >> + case ACTION_OPCODE_SCTP_ABORT: > >> + case ACTION_OPCODE_REJECT: > >> + case ACTION_OPCODE_PUT_ICMP4_FRAG_MTU: > >> + case ACTION_OPCODE_PUT_ICMP6_FRAG_MTU: > >> + case ACTION_OPCODE_EVENT: > >> + case ACTION_OPCODE_BIND_VPORT: > >> + case ACTION_OPCODE_DHCP6_SERVER: > >> + case ACTION_OPCODE_HANDLE_SVC_CHECK: > >> + case ACTION_OPCODE_BFD_MSG: > >> + case ACTION_OPCODE_ACTIVATION_STRATEGY_RARP: > >> + case ACTION_OPCODE_MG_SPLIT_BUF: > >> + default: > >> + return false; > >> + } > >> +} > >> + > >> static void > >> encode_nested_actions(const struct ovnact_nest *on, > >> const struct ovnact_encode_params *ep, > >> @@ -1851,7 +1889,8 @@ encode_nested_actions(const struct ovnact_nest > *on, > >> * converted to OpenFlow, as its userdata. ovn-controller will > >> convert the > >> * packet to ARP or NA and then send the packet and actions back to > >> the > >> * switch inside an OFPT_PACKET_OUT message. */ > >> - size_t oc_offset = encode_start_controller_op(opcode, false, > >> + bool pause = is_paused_nested_action(opcode); > >> + size_t oc_offset = encode_start_controller_op(opcode, pause, > >> ep->ctrl_meter_id, > >> ofpacts); > >> ofpacts_put_openflow_actions(inner_ofpacts.data, > inner_ofpacts.size, > >> ofpacts, OFP15_VERSION); > >> @@ -1867,6 +1906,9 @@ encode_ARP(const struct ovnact_nest *on, > >> struct ofpbuf *ofpacts) > >> { > >> encode_nested_actions(on, ep, ACTION_OPCODE_ARP, ofpacts); > >> + if (!ep->explicit_arp_ns_output) { > >> + emit_resubmit(ofpacts, ep->output_ptable); > >> + } > >> } > >> > >> static void > >> @@ -1955,6 +1997,9 @@ encode_ND_NS(const struct ovnact_nest *on, > >> struct ofpbuf *ofpacts) > >> { > >> encode_nested_actions(on, ep, ACTION_OPCODE_ND_NS, ofpacts); > >> + if (!ep->explicit_arp_ns_output) { > >> + emit_resubmit(ofpacts, ep->output_ptable); > >> + } > >> } > >> > >> static void > >> diff --git a/northd/en-global-config.c b/northd/en-global-config.c > >> index 34e393b33..9462b3b7b 100644 > >> --- a/northd/en-global-config.c > >> +++ b/northd/en-global-config.c > >> @@ -553,6 +553,10 @@ update_sb_config_options_to_sbrec(struct > >> ed_type_global_config *config_data, > >> smap_replace(options, "sbctl_probe_interval", sip); > >> } > >> > >> + /* Adds indication that northd is handling explicit output after > >> + * arp/nd_ns action. */ > >> + smap_add(options, "arp_ns_explicit_output", "true"); > >> + > >> if (!smap_equal(&sb->options, options)) { > >> sbrec_sb_global_set_options(sb, options); > >> } > >> diff --git a/northd/northd.c b/northd/northd.c > >> index 37f443e70..331d9c267 100644 > >> --- a/northd/northd.c > >> +++ b/northd/northd.c > >> @@ -13422,7 +13422,7 @@ build_arp_request_flows_for_lrouter( > >> "ip6.dst = %s; " > >> "nd.target = %s; " > >> "output; " > >> - "};", ETH_ADDR_ARGS(eth_dst), sn_addr_s, > >> + "}; output;", ETH_ADDR_ARGS(eth_dst), sn_addr_s, > >> route->nexthop); > >> > >> ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_ARP_REQUEST, > >> 200, > >> @@ -13442,7 +13442,7 @@ build_arp_request_flows_for_lrouter( > >> "arp.tpa = " REG_NEXT_HOP_IPV4 "; " > >> "arp.op = 1; " /* ARP request */ > >> "output; " > >> - "};", > >> + "}; output;", > >> copp_meter_get(COPP_ARP_RESOLVE, od->nbr->copp, > >> meter_groups), > >> lflow_ref); > >> @@ -13451,7 +13451,7 @@ build_arp_request_flows_for_lrouter( > >> "nd_ns { " > >> "nd.target = " REG_NEXT_HOP_IPV6 "; " > >> "output; " > >> - "};", > >> + "}; output;", > >> copp_meter_get(COPP_ND_NS_RESOLVE, od->nbr->copp, > >> meter_groups), > >> lflow_ref); > >> diff --git a/tests/multinode.at b/tests/multinode.at > >> index 0187382be..b959a2550 100644 > >> --- a/tests/multinode.at > >> +++ b/tests/multinode.at > >> @@ -70,6 +70,14 @@ M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c > >> 3 -i 0.3 -w 2 20.0.0.3 | F > >> 3 packets transmitted, 3 received, 0% packet loss, time 0ms > >> ]) > >> > >> +check multinode_nbctl lsp-set-addresses sw1-port1 unknown > >> +m_wait_for_ports_up sw1-port1 > >> + > >> +M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c 3 -i 0.3 -w 2 > >> 20.0.0.3 | FORMAT_PING], \ > >> +[0], [dnl > >> +3 packets transmitted, 3 received, 0% packet loss, time 0ms > >> +]) > >> + > >> AT_CLEANUP > >> > >> AT_SETUP([ovn multinode pmtu - distributed router - geneve]) > >> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > >> index be006fb32..dcc29ffa8 100644 > >> --- a/tests/ovn-northd.at > >> +++ b/tests/ovn-northd.at > >> @@ -6973,6 +6973,9 @@ ct_dnat /* assuming no un-dnat entry, so no change > >> */ { > >> arp.op = 1; > >> output("rtr-ls"); > >> }; > >> + ct_dnat /* assuming no un-dnat entry, so no change */ { > >> + output("rtr-ls"); > >> + }; > >> }; > >> }; > >> ]) > >> diff --git a/tests/ovn.at b/tests/ovn.at > >> index c8cc1d37f..dc6aafd53 100644 > >> --- a/tests/ovn.at > >> +++ b/tests/ovn.at > >> @@ -1521,11 +1521,11 @@ clone { ip4.dst = 255.255.255.255; output; }; > >> next; > >> > >> # arp > >> arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output; > >> - encodes as > >> > controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.OFTABLE_SAVE_INPORT_HEX.00.00.00),resubmit(,OFTABLE_SAVE_INPORT) > >> + encodes as > >> > controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.OFTABLE_SAVE_INPORT_HEX.00.00.00,pause),resubmit(,OFTABLE_SAVE_INPORT) > >> has prereqs ip4 > >> arp { }; > >> formats as arp { drop; }; > >> - encodes as controller(userdata=00.00.00.00.00.00.00.00) > >> + encodes as controller(userdata=00.00.00.00.00.00.00.00,pause) > >> has prereqs ip4 > >> > >> # get_arp > >> @@ -1655,12 +1655,12 @@ reg1[[0]] = put_dhcp_opts(offerip=1.2.3.4, > >> domain_search_list=1.2.3.4); > >> > >> # nd_ns > >> nd_ns { nd.target = xxreg0; output; }; > >> - encodes as > >> controller(userdata=00.00.00.09.00.00.00.00.00.1c.00.18.00. > >> 80.00.00.00.00.00.00.00.01.de > >> > .10.80.00.3e.10.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.OFTABLE_SAVE_INPORT_HEX.00.00.00) > >> + encodes as > >> controller(userdata=00.00.00.09.00.00.00.00.00.1c.00.18.00. > >> 80.00.00.00.00.00.00.00.01.de > >> > .10.80.00.3e.10.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.OFTABLE_SAVE_INPORT_HEX.00.00.00,pause) > >> has prereqs ip6 > >> > >> nd_ns { }; > >> formats as nd_ns { drop; }; > >> - encodes as controller(userdata=00.00.00.09.00.00.00.00) > >> + encodes as controller(userdata=00.00.00.09.00.00.00.00,pause) > >> has prereqs ip6 > >> > >> # nd_na > >> diff --git a/tests/system-ovn.at b/tests/system-ovn.at > >> index 516fb4d99..5848f3901 100644 > >> --- a/tests/system-ovn.at > >> +++ b/tests/system-ovn.at > >> @@ -12417,3 +12417,98 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query > >> port patch-.*/d > >> /connection dropped.*/d"]) > >> AT_CLEANUP > >> ]) > >> + > >> +OVN_FOR_EACH_NORTHD([ > >> +AT_SETUP([LB with first packet buffered]) > >> +AT_KEYWORDS([ovnlb]) > >> + > >> +CHECK_CONNTRACK() > >> +CHECK_CONNTRACK_NAT() > >> + > >> +ovn_start > >> +OVS_TRAFFIC_VSWITCHD_START() > >> +ADD_BR([br-int]) > >> +ADD_BR([br-ext]) > >> + > >> +check ovs-ofctl add-flow br-ext action=normal > >> +# Set external-ids in br-int needed for ovn-controller > >> +check ovs-vsctl \ > >> + -- set Open_vSwitch . external-ids:system-id=hv1 \ > >> + -- set Open_vSwitch . > >> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ > >> + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ > >> + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ > >> + -- set bridge br-int fail-mode=secure > >> other-config:disable-in-band=true \ > >> + -- set Open_vSwitch . > >> external-ids:ovn-bridge-mappings=phynet:br-ext > >> + > >> +# Start ovn-controller > >> +start_daemon ovn-controller > >> + > >> +check ovn-nbctl lr-add lr > >> +check ovn-nbctl ls-add internal > >> +check ovn-nbctl ls-add public > >> + > >> +check ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.100.1/24 > >> 1000::1/64 > >> +check ovn-nbctl lsp-add public pub-lr -- set Logical_Switch_Port > pub-lr > >> \ > >> + type=router options:router-port=lr-pub > >> addresses=\"00:00:01:01:02:03\" > >> + > >> +check ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 > >> 192.168.200.1/24 2000::1/64 > >> +check ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port > >> internal-lr \ > >> + type=router options:router-port=lr-internal > >> addresses=\"00:00:01:01:02:04\" > >> + > >> +check ovn-nbctl lsp-add internal server -- lsp-set-addresses server > >> "unknown" > >> + > >> +ovn-nbctl lsp-add public ln_port \ > >> + -- lsp-set-addresses ln_port unknown \ > >> + -- lsp-set-type ln_port localnet \ > >> + -- lsp-set-options ln_port network_name=phynet > >> + > >> +check ovn-nbctl set logical_router lr options:chassis=hv1 > >> + > >> +check ovn-nbctl lb-add lb1 192.168.100.20 192.168.200.10 > >> +check ovn-nbctl lb-add lb2 1000::20 2000::10 > >> +check ovn-nbctl lr-lb-add lr lb1 > >> +check ovn-nbctl lr-lb-add lr lb2 > >> +check ovn-nbctl --wait=hv sync > >> + > >> +ADD_NAMESPACES(client) > >> +ADD_VETH(client, client, br-ext, "1000::10/64", "f0:00:00:01:02:03", \ > >> + "1000::1", "nodad", "192.168.100.10/24", "192.168.100.1") > >> + > >> +ADD_NAMESPACES(server) > >> +ADD_VETH(server, server, br-int, "2000::10/64", "f0:00:0f:01:02:03", \ > >> + "2000::1", "nodad", "192.168.200.10/24", "192.168.200.1") > >> + > >> +NETNS_DAEMONIZE([server], [nc -l -u 192.168.200.10 4242 > /dev/null], > >> [serverv4.pid]) > >> +NETNS_DAEMONIZE([server], [nc -l -u 2000::10 4243 > /dev/null], > >> [serverv6.pid]) > >> + > >> +NETNS_START_TCPDUMP([client], [-l -U -i client -vnne udp], [client]) > >> +NETNS_START_TCPDUMP([server], [-l -U -i server -vnne udp], [server]) > >> + > >> +check ovs-appctl dpctl/flush-conntrack > >> + > >> +NS_CHECK_EXEC([client], [nc -z -u 192.168.100.20 4242], [ignore], > >> [ignore], [ignore]) > >> +OVS_WAIT_UNTIL([grep -q "192.168.200.10" server.tcpdump]) > >> + > >> +NS_CHECK_EXEC([client], [nc -z -u 1000::20 4243]) > >> +OVS_WAIT_UNTIL([grep -q "2000::10" server.tcpdump]) > >> + > >> +zone_id=$(ovn-appctl -t ovn-controller ct-zone-list | grep lr_dnat | > cut > >> -d ' ' -f2) > >> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep -c "zone=$zone_id"], > >> [0], [2 > >> +]) > >> + > >> +OVS_APP_EXIT_AND_WAIT([ovn-controller]) > >> + > >> +as ovn-sb > >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) > >> + > >> +as ovn-nb > >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) > >> + > >> +as northd > >> +OVS_APP_EXIT_AND_WAIT([ovn-northd]) > >> + > >> +as > >> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d > >> +/connection dropped.*/d"]) > >> +AT_CLEANUP > >> +]) > >> diff --git a/tests/test-ovn.c b/tests/test-ovn.c > >> index 5326c6e69..2ea68f212 100644 > >> --- a/tests/test-ovn.c > >> +++ b/tests/test-ovn.c > >> @@ -1359,6 +1359,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx > >> OVS_UNUSED) > >> .group_table = &group_table, > >> .meter_table = &meter_table, > >> .collector_ids = &collector_ids, > >> + .explicit_arp_ns_output = true, > >> > >> .pipeline = OVNACT_P_INGRESS, > >> .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE, > >> -- > >> 2.44.0 > >> > >> _______________________________________________ > >> dev mailing list > >> d...@openvswitch.org > >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev > >> > >> > 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 > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev