From patchwork Fri Apr 1 08:32:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Vladislav Odintsov X-Patchwork-Id: 1612089 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=F6sbxoY1; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KVD235Jr8z9sG5 for ; Fri, 1 Apr 2022 19:32:43 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 71620418DC; Fri, 1 Apr 2022 08:32:41 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UU8oHpHJBtAf; Fri, 1 Apr 2022 08:32:39 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 08CE2418DB; Fri, 1 Apr 2022 08:32:38 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 94BE8C002C; Fri, 1 Apr 2022 08:32:37 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id DB015C0012 for ; Fri, 1 Apr 2022 08:32:35 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id C269E418DC for ; Fri, 1 Apr 2022 08:32:35 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iqt1Wvhn0BM8 for ; Fri, 1 Apr 2022 08:32:34 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-lj1-x236.google.com (mail-lj1-x236.google.com [IPv6:2a00:1450:4864:20::236]) by smtp4.osuosl.org (Postfix) with ESMTPS id DAE44418DB for ; Fri, 1 Apr 2022 08:32:33 +0000 (UTC) Received: by mail-lj1-x236.google.com with SMTP id q5so2904854ljb.11 for ; Fri, 01 Apr 2022 01:32:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ZkZTy6ZYH6P53HjVrnarrliXAndKws/4hykZXcP08ek=; b=F6sbxoY1J1bTbp4DXUsZWXPUfkNofqCIZtAH0xyAb1DvzY5YyrX6gLIP+fVMJt2jwk rY+PV5bZDwfWqd5MGJo3fKsnkMoG24pP5roWnKhyEqgcqLk9IwQGEpLw7hpC6pQ3B1+Q XF86Km6c4UOGM2KQ1uRFrUmukFKs8zqJwWuSwsvxFqAcBxKWgIWPFbD4Zk6Rlo3hK/t+ bDLK77t1+tuu7bSWa/kvkgrvH0HCf4gke8v0wf9Hx5cRTsVWU8D5xn5WhtPwUdUZ+PPl /+idCZktKri0l+47E9rkpSUDsjygX56XlEArba0obb+MIU6uN+MOd9bQ3e3v/Zcq+ZIG GONA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ZkZTy6ZYH6P53HjVrnarrliXAndKws/4hykZXcP08ek=; b=mioB4aHd4X+NCYeyypZ62+QGekfdcAIzxEZ9mlhzZPuvydb+BDbFvpx5nh/QFrjvlG N5gSs4DuWRtFUmVCwwAs9fay2Z/iINwkNntXl2fAZYXEGOliG4TlZHR1dMXXqRs1KhCl zTaRvbQ41BJStlBl3MMQPj9/P3sgfV8xc61i89xEGSkgJps2zKh+tIY3fq/G2a3UoAJ6 mEwQLt1teDzumejNNWyJDCM5ft4/E+fwYS3gITQBizlQVmG7vyeptqHmsPuiooLd+RFf klNwQx7utfbkBf64zcm230El99CQmAtJ2q/zNJxcd8VRjEyCT4mJgcEQFazYAYYZ4b9j 6hOw== X-Gm-Message-State: AOAM532B8GKaakhQfWguFckkPGehGWeHbNQIfJ+OUbUpUQ89+MFwyBIv dR7JdKyEuJa35CIRLYjNVQm27u6Uu6E= X-Google-Smtp-Source: ABdhPJwG17Wg6rvsGhxjWBDT2H42LRTXR31ewVDVYIPqOGd6GyX+d+MEzyRKGV9J7ubBqv2jJcs6TA== X-Received: by 2002:a2e:9990:0:b0:249:88f6:f637 with SMTP id w16-20020a2e9990000000b0024988f6f637mr12611587lji.14.1648801951160; Fri, 01 Apr 2022 01:32:31 -0700 (PDT) Received: from ip-10-70-112-12.vpc-1e810be1.internal (c2-217-73-63-80.elastic.cloud.croc.ru. [217.73.63.80]) by smtp.gmail.com with ESMTPSA id q10-20020a196e4a000000b0044ac90ec3fcsm172168lfk.79.2022.04.01.01.32.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Apr 2022 01:32:30 -0700 (PDT) From: Vladislav Odintsov To: dev@openvswitch.org Date: Fri, 1 Apr 2022 11:32:29 +0300 Message-Id: <20220401083229.1583750-1-odivlad@gmail.com> X-Mailer: git-send-email 2.26.3 MIME-Version: 1.0 Cc: Vladislav Odintsov Subject: [ovs-dev] [PATCH ovn] controller, northd, vtep: support routed networks with HW VTEP X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" When HW VTEP is used with OVN logical networks routed by Logical Routers, only directly-attached network can communicate with external VLAN (via vtep LSP). There is no connectivity between VLAN network which is located behind VTEP LSP and lswitch1 behind LR. Visual description: ┌──────┐ ┌─────► │ VM │ │ └───┬──┘ │ ┌──────┴───────┐ │ │ lswitch1 │ │ │192.168.0.0/24│ │ └──────┬───────┘ │ ┌─┴──┐ │ │ LR │ │ └─┬──┘ │ ┌──────┴───────┐ │ │ lswitch2 │ │ │192.168.1.0/24│ ◄──┐ │ └──────┬───────┘ │ │ ┌───┴────┐ │ │FAIL │vtep LSP│ OK│ │ └───┬────┘ │ │ ┌──┴────┐ │ └────────┤VLAN 10├───────┘ └───────┘ This patch adds support to have connectivity between such routed networks. User must set LRP gateway chassis (or ha chassis group) in the lswitch2's associated LRP, which will enable answering ARP requests for LR IP from VLAN (lswitch2) side. Traffic from VLAN to overlay will go from HW VTEP switch through gateway chassis to hypervisor and return traffic will go directly from hypervisor to HW VTEP switch and then got forwarded to VLAN. Now chassis, on which chassis redirect LRP is claimed, will answer ARP requests coming from HW VTEP switch. For this reason the hairpin traffic from VTEP switch is allowed: 1. the blocking OF rule in table `OFTABLE_REMOTE_OUTPUT` which matched on reg10=0x2/0x2 is changed to match on reg10=0x2/0x3. We check if traffic is from VTEP (ramp) switch and also we check if loopback flag was not set and only in this case such traffic is not allowed. 2. OF rule in table `OFTABLE_REMOTE_OUTPUT`, which directs traffic to HW VTEP (ramp) switch is modified to flush IN_PORT in order to allow sending traffic to OF port from which this traffic came (hairpin). New flows are added to ls_in_ip_hairpin table to support ARP traffic hairpin for VTEP switches: 1. if traffic has come from VTEP (ramp) switch AND l3dgw ports of associated LSPs reside on current chassis (is_chassis_resident()), such traffic is passed to next table for further ARP responder processing. Priority of this flow is 2000. 2. if traffic has come from VTEP (ramp) switch, send it to L2_LKUP table to skip ARP responder processing. We serve ARP requests from VTEP lports only on gateway chassis. Priority of this flow is 1000. Signed-off-by: Vladislav Odintsov --- controller-vtep/vtep.c | 31 ++++++++++++++++++++--- controller/physical.c | 18 ++++++++++---- northd/northd.c | 50 +++++++++++++++++++++++++++++++++---- northd/ovn-northd.8.xml | 55 +++++++++++++++++++++++++++++------------ tests/ovn-northd.at | 9 ++++--- tests/ovn.at | 37 +++++++++++++++++++++------ 6 files changed, 159 insertions(+), 41 deletions(-) diff --git a/controller-vtep/vtep.c b/controller-vtep/vtep.c index ecca00b54..c3d09425c 100644 --- a/controller-vtep/vtep.c +++ b/controller-vtep/vtep.c @@ -311,6 +311,9 @@ vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts, hash_uint64((uint64_t) vtep_ls->tunnel_key[0])); } + const char *dp, *peer; + const struct sbrec_port_binding *lrp_pb, *peer_pb; + SHASH_FOR_EACH (node, non_vtep_pbs) { const struct sbrec_port_binding *port_binding_rec = node->data; const struct sbrec_chassis *chassis_rec; @@ -324,7 +327,25 @@ vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts, continue; } - tnl_key = port_binding_rec->datapath->tunnel_key; + if (!strcmp(port_binding_rec->type, "chassisredirect")) { + dp = smap_get(&port_binding_rec->options, "distributed-port"); + lrp_pb = shash_find_data(non_vtep_pbs, dp); + if (!lrp_pb) { + continue; + } + + peer = smap_get(&lrp_pb->options, "peer"); + if (!peer) { + continue; + } + + peer_pb = shash_find_data(non_vtep_pbs, peer); + tnl_key = peer_pb->datapath->tunnel_key; + } + else { + tnl_key = port_binding_rec->datapath->tunnel_key; + } + HMAP_FOR_EACH_WITH_HASH (ls_node, hmap_node, hash_uint64((uint64_t) tnl_key), &ls_map) { @@ -454,7 +475,7 @@ vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts, static bool vtep_lswitch_cleanup(struct ovsdb_idl *vtep_idl) { - const struct vteprec_logical_switch *vtep_ls; + const struct vteprec_logical_switch *vtep_ls; bool done = true; VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, vtep_idl) { @@ -572,9 +593,11 @@ vtep_run(struct controller_vtep_ctx *ctx) /* Collects and classifies 'Port_Binding's. */ SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->ovnsb_idl) { struct shash *target = - !strcmp(port_binding_rec->type, "vtep") ? &vtep_pbs : &non_vtep_pbs; + !strcmp(port_binding_rec->type, "vtep") ? &vtep_pbs + : &non_vtep_pbs; - if (!port_binding_rec->chassis) { + if (!port_binding_rec->chassis && + strcmp(port_binding_rec->type, "patch")) { continue; } shash_add(target, port_binding_rec->logical_port, port_binding_rec); diff --git a/controller/physical.c b/controller/physical.c index 02fcd5ea8..2a70f4fe0 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -299,9 +299,16 @@ put_remote_port_redirect_overlay(const struct if (!rem_tun) { return; } + + bool is_vtep_port = !strcmp(binding->type, "vtep"); + /* rewrite MFF_IN_PORT to bypass OpenFlow loopback check for ARP/ND + * responder in L3 networks. */ + if (is_vtep_port) { + put_load(ofp_to_u16(OFPP_NONE), MFF_IN_PORT, 0, 16, ofpacts_p); + } + put_encapsulation(mff_ovn_geneve, tun, binding->datapath, port_key, - !strcmp(binding->type, "vtep"), - ofpacts_p); + is_vtep_port, ofpacts_p); /* Output to tunnel. */ ofpact_put_OUTPUT(ofpacts_p)->port = rem_tun->ofport; } else { @@ -1841,12 +1848,13 @@ physical_run(struct physical_ctx *p_ctx, * Handles packets received from a VXLAN tunnel which get resubmitted to * OFTABLE_LOG_INGRESS_PIPELINE due to lack of needed metadata in VXLAN, * explicitly skip sending back out any tunnels and resubmit to table 38 - * for local delivery. + * for local delivery, except packets which have MLF_ALLOW_LOOPBACK bit + * set. */ struct match match; match_init_catchall(&match); - match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, - MLF_RCV_FROM_RAMP, MLF_RCV_FROM_RAMP); + match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, MLF_RCV_FROM_RAMP, + MLF_RCV_FROM_RAMP | MLF_ALLOW_LOOPBACK); /* Resubmit to table 38. */ ofpbuf_clear(&ofpacts); diff --git a/northd/northd.c b/northd/northd.c index a2cf8d6fc..0a055b519 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -199,6 +199,7 @@ enum ovn_stage { #define REGBIT_LKUP_FDB "reg0[11]" #define REGBIT_HAIRPIN_REPLY "reg0[12]" #define REGBIT_ACL_LABEL "reg0[13]" +#define REGBIT_FROM_RAMP "reg0[14]" #define REG_ORIG_DIP_IPV4 "reg1" #define REG_ORIG_DIP_IPV6 "xxreg1" @@ -5510,8 +5511,9 @@ build_lswitch_input_port_sec_op( } if (!strcmp(op->nbsp->type, "vtep")) { + ds_put_format(actions, REGBIT_FROM_RAMP" = 1; "); ds_put_format(actions, "next(pipeline=ingress, table=%d);", - ovn_stage_get_table(S_SWITCH_IN_L2_LKUP)); + ovn_stage_get_table(S_SWITCH_IN_HAIRPIN)); } else { ds_put_cstr(actions, "next;"); } @@ -6960,6 +6962,45 @@ build_lb_hairpin(struct ovn_datapath *od, struct hmap *lflows) } } +static void +build_vtep_hairpin(struct ovn_datapath *od, struct hmap *lflows) +{ + /* Ingress Pre-ARP flows for VTEP hairpining traffic. Priority 1000: + * Packets that received from non-VTEP ports should continue processing. */ + + char *action = xasprintf("next(pipeline=ingress, table=%d);", + ovn_stage_get_table(S_SWITCH_IN_L2_LKUP)); + /* send all traffic from VTEP directly to L2LKP table. */ + ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 1000, + REGBIT_FROM_RAMP" == 1", action); + free(action); + + struct ds match = DS_EMPTY_INITIALIZER; + int n_ports = od->n_router_ports; + bool dp_has_l3dgw_ports = false; + for (int i = 0; i < n_ports; i++) { + if (is_l3dgw_port(od->router_ports[i]->peer)) { + ds_put_format(&match, "%sis_chassis_resident(%s)%s", + i == 0 ? REGBIT_FROM_RAMP" == 1 && (" : "", + od->router_ports[i]->peer->cr_port->json_key, + i < n_ports - 1 ? " || " : ")"); + dp_has_l3dgw_ports = true; + } + } + + /* Ingress pre-arp flow for traffic from VTEP (ramp) switch. + * Priority 2000: Packets, that were received from VTEP (ramp) switch and + * router ports of current datapath are l3dgw ports and they reside on + * current chassis, should be passed to next table for ARP/ND hairpin + * processing. + */ + if (dp_has_l3dgw_ports) { + ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 2000, ds_cstr(&match), + "next;"); + } + ds_destroy(&match); +} + /* Build logical flows for the forwarding groups */ static void build_fwd_group_lflows(struct ovn_datapath *od, struct hmap *lflows) @@ -7652,6 +7693,7 @@ build_lswitch_lflows_pre_acl_and_acl(struct ovn_datapath *od, build_qos(od, lflows); build_stateful(od, lflows); build_lb_hairpin(od, lflows); + build_vtep_hairpin(od, lflows); } } @@ -7680,8 +7722,7 @@ build_lswitch_lflows_admission_control(struct ovn_datapath *od, } /* Ingress table 18: ARP/ND responder, skip requests coming from localnet - * and vtep ports. (priority 100); see ovn-northd.8.xml for the - * rationale. */ + * ports. (priority 100); see ovn-northd.8.xml for the rationale. */ static void build_lswitch_arp_nd_responder_skip_local(struct ovn_port *op, @@ -7689,8 +7730,7 @@ build_lswitch_arp_nd_responder_skip_local(struct ovn_port *op, struct ds *match) { if (op->nbsp) { - if ((!strcmp(op->nbsp->type, "localnet")) || - (!strcmp(op->nbsp->type, "vtep"))) { + if (!strcmp(op->nbsp->type, "localnet")) { ds_clear(match); ds_put_format(match, "inport == %s", op->json_key); ovn_lflow_add_with_lport_and_hint(lflows, op->od, diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 4784bff04..08864acfe 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -1094,6 +1094,29 @@

Ingress Table 17: Hairpin

    +
  • + A priority-2000 flow that passes traffic to next table for hairpin ARP + processing with + next; action, which matches on: +
      +
    • + reg0[14] register bit, that is set in + ls_in_port_sec_l2 table for traffic received from HW VTEP (ramp) + switch AND +
    • +
    • + all Distrubited Gateway ports, which are associated with current LS + router type LSPs if is_chassis_resident() + for them is true. +
    • +
    +
  • +
  • + A priority-1000 flow that matches on reg0[14] register + bit that is set in ls_in_port_sec_l2 table for traffic received from HW + VTEP (ramp) switch. This traffic is passed to ingress table + ls_in_l2_lkup. +
  • A priority-1 flow that hairpins traffic matched by non-default flows in the Pre-Hairpin table. Hairpinning is done at L2, Ethernet @@ -1150,27 +1173,27 @@

    - Note that ARP requests received from localnet or - vtep logical inports can either go directly to VMs, in - which case the VM responds or can hit an ARP responder for a logical - router port if the packet is used to resolve a logical router port - next hop address. In either case, logical switch ARP responder rules - will not be hit. It contains these logical flows: + Note that ARP requests received from localnet logical + inports can either go directly to VMs, in which case the VM responds or + can hit an ARP responder for a logical router port if the packet is used + to resolve a logical router port next hop address. In either case, + logical switch ARP responder rules will not be hit. It contains these + logical flows:

    • Priority-100 flows to skip the ARP responder if inport is of type - localnet or vtep and advances directly - to the next table. ARP requests sent to localnet or - vtep ports can be received by multiple hypervisors. - Now, because the same mac binding rules are downloaded to all - hypervisors, each of the multiple hypervisors will respond. This - will confuse L2 learning on the source of the ARP requests. ARP - requests received on an inport of type router are not - expected to hit any logical switch ARP responder flows. However, - no skip flows are installed for these packets, as there would be - some additional flow cost for this and the value appears limited. + localnet advances directly to the next table. ARP + requests sent to localnet ports can be received by + multiple hypervisors. Now, because the same mac binding rules are + downloaded to all hypervisors, each of the multiple hypervisors will + respond. This will confuse L2 learning on the source of the ARP + requests. ARP requests received on an inport of type + router are not expected to hit any logical switch ARP + responder flows. However, no skip flows are installed for these + packets, as there would be some additional flow cost for this and the + value appears limited.
    • diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 17d4f31b3..eab84886a 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -2592,9 +2592,10 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl table=??(ls_in_nat_hairpin ), priority=90 , match=(ip && reg0[[12]] == 1), action=(ct_snat;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) table=??(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) + table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) ]) check ovn-nbctl -- ls-lb-del sw0 lb0 @@ -2608,8 +2609,9 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl table=??(ls_in_nat_hairpin ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) ]) check ovn-nbctl -- add load_balancer_group $lbg load_balancer $lb0 @@ -2627,9 +2629,10 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl table=??(ls_in_nat_hairpin ), priority=90 , match=(ip && reg0[[12]] == 1), action=(ct_snat;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) table=??(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) + table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) ]) AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index 166b5f72e..0e24f7abb 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -4023,10 +4023,20 @@ ovn-nbctl lsp-set-addresses lp-vtep unknown ovn-nbctl lsp-add lsw0 lpr ovn-nbctl lr-add lr ovn-nbctl lrp-add lr lrp1 f0:00:00:00:00:f1 192.168.1.1/24 -ovn-nbctl set Logical_Switch_Port lpr type=router \ - options:router-port=lrp1 \ - addresses='"f0:00:00:00:00:f1 192.168.1.1"' - +ovn-nbctl set Logical_Switch_Port lpr \ + type=router \ + options:router-port=lrp1 \ + addresses=router +ovn-nbctl lrp-set-gateway-chassis lrp1 hv1 + +ovn-nbctl lsp-add lsw0 lpr2 +ovn-nbctl lr-add lr2 +ovn-nbctl lrp-add lr lrp2 f0:00:00:00:00:f2 192.168.1.254/24 +ovn-nbctl set Logical_Switch_Port lpr2 \ + type=router \ + options:router-port=lrp2 \ + addresses=router +ovn-nbctl lrp-set-gateway-chassis lrp2 hv1 net_add n1 # Network to connect hv1, hv2, and vtep net_add n2 # Network to connect vtep and hv3 @@ -4147,17 +4157,28 @@ for s in 1 2 3; do test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown #3 done -# ARP request should not be responded to by logical switch router -# type arp responder on HV1 and HV2 and should reach directly to -# vif1 and vif2 +# ARP request from VTEP to LRP should be responded by ARP responder. sha=f00000000003 spa=`ip_to_hex 192 168 1 2` tpa=`ip_to_hex 192 168 1 1` request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} as hv3 ovs-appctl netdev-dummy/receive vif3 $request -echo $request >> 1.expected echo $request >> 2.expected +lrpmac=f000000000f1 +response=${sha}${lrpmac}08060001080006040002${lrpmac}${tpa}${sha}${spa} +# since lrp1 has gateway chassis set on hv1, hv1 will suppress arp request and +# answer with arp reply by OVS directly to vtep lport. all other lports, +# except lport from which this request was initiated, will receive arp request. +# we expect arp reply packet on hv3 +echo $response >> 3.expected + +AT_CHECK([ovn-sbctl lflow-list lsw0 | grep 'reg0[\[14\]]' | sort | sed 's/table=../table=??/g'], [0], [dnl + table=??(ls_in_port_sec_l2 ), priority=50 , match=(inport == "lp-vtep"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=??);) + table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) + table=??(ls_in_hairpin ), priority=2000 , match=(reg0[[14]] == 1 && (is_chassis_resident("cr-lrp1") || is_chassis_resident("cr-lrp2"))), action=(next;) +]) + # dump information with counters echo "------ OVN dump ------" ovn-nbctl show