From patchwork Thu Jul 8 23:15:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1502790 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=DrshFV1M; dkim-atps=neutral Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (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 ozlabs.org (Postfix) with ESMTPS id 4GLXFt2L2fz9sXM for ; Fri, 9 Jul 2021 09:15:30 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 9F1E640595; Thu, 8 Jul 2021 23:15:27 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id MHVxKNq_Vbak; Thu, 8 Jul 2021 23:15:26 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id AEDDF40590; Thu, 8 Jul 2021 23:15:25 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E052DC0010; Thu, 8 Jul 2021 23:15:24 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 87541C000E for ; Thu, 8 Jul 2021 23:15:23 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 474ED83C0D for ; Thu, 8 Jul 2021 23:15:23 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp1.osuosl.org (amavisd-new); dkim=pass (1024-bit key) header.d=redhat.com Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id afPrfxYNhcna for ; Thu, 8 Jul 2021 23:15:22 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id 62AF883AE5 for ; Thu, 8 Jul 2021 23:15:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1625786121; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1j6jErCWja2MwWxWQ+h8DbBWxX9kZ1Ek/ekcqVSPkgc=; b=DrshFV1Mw+hzoC/sECqM1cYWYfhGeqPfo3becdnggG911I7RPMSohVjiVVyS4sgupDsp0l Q/5+/Uq3u3M8FokDwMhRiBa/vwXol227hciThC6T85UWGRNdOpjGHhdVD2r8PiLYlaR4iK a98I6ciTN3BzXzY/QR/i2KAzARDsVrk= Received: from mail-ed1-f71.google.com (mail-ed1-f71.google.com [209.85.208.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-485-8MKq_ixRP4m28LloYeHJxg-1; Thu, 08 Jul 2021 19:15:20 -0400 X-MC-Unique: 8MKq_ixRP4m28LloYeHJxg-1 Received: by mail-ed1-f71.google.com with SMTP id z5-20020a05640235c5b0290393974bcf7eso4139728edc.2 for ; Thu, 08 Jul 2021 16:15:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1j6jErCWja2MwWxWQ+h8DbBWxX9kZ1Ek/ekcqVSPkgc=; b=XxxJ8P33UtdTFv5bAS6DbcY9Zhyj4ZIiqRC1c5eMzJrRgSBxKx0bgWYW5eP9VfXz9h XIlrv3Nn2osYvMzwpEQnD6KMzQysA1hq9MtbIxqL8fLqjX+JmPyFQlR5uk9IAMmpuUus 4AP85Pxtp7xyoUMv5zWiduoZ3ywbCoUkKbFovH/G6L0nwr9NBOt1lIjnlV8dXSlPMvHl rATlOCT/cPaLg4FrVGpEFG3FpHOSbVZkxO388f0q531sM7U2hAvQmDQcVRRwDx6TT6ug z8k1oyXf9jYAPncmBddrAMR9XF0vM53qKDiB4gT6DC3jtd9dfwrlE1xhhDRqVBpc2bjz erRw== X-Gm-Message-State: AOAM530QQ0EA4qmQsCi3m7go3xuJyrLQFeeXingvKM0PP5ZaSeSQF75L a4+byBG4RGEtKvxl2i/A5Fy6sOeBGEPT705x/e8F0vW5ZrguT0fIYh5OHK98iMc63FZo8uG+/Iz P3OHGvzLedDU3fNucoML3IrwlnjdvsCK+xt+3fB6SHRvV89xgFF1jGqp37xN867lRRmJHnHt90o c= X-Received: by 2002:a05:6402:5249:: with SMTP id t9mr20872840edd.181.1625786118864; Thu, 08 Jul 2021 16:15:18 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwSVmiiWlTTNqnvll2zeg544zwNJUkh9F8FTOnaOL0GQM0E75Jc3m6abmKveFYoaz9WKSRUmw== X-Received: by 2002:a05:6402:5249:: with SMTP id t9mr20872824edd.181.1625786118691; Thu, 08 Jul 2021 16:15:18 -0700 (PDT) Received: from lore-desk.redhat.com (net-93-71-3-244.cust.vodafonedsl.it. [93.71.3.244]) by smtp.gmail.com with ESMTPSA id c15sm1993328edu.19.2021.07.08.16.15.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Jul 2021 16:15:18 -0700 (PDT) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Fri, 9 Jul 2021 01:15:09 +0200 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH v5 ovn 1/3] northd: introduce build_check_pkt_len_flows_for_lrp routine 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" Introduce build_check_pkt_len_flows_for_lrp routine to configure check_pkt_larger logical flow for a given logical port. This is a preliminary patch to enable check_pkt_larger support for gw router use case. Acked-by: Mark Michelson Signed-off-by: Lorenzo Bianconi --- northd/ovn-northd.c | 181 +++++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 86 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index eb25e31b1..c86ab927c 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -10575,6 +10575,99 @@ build_arp_resolve_flows_for_lrouter_port( } +static void +build_check_pkt_len_flows_for_lrp(struct ovn_port *op, + struct hmap *lflows, struct hmap *ports, + struct ds *match, struct ds *actions) +{ + int gw_mtu = 0; + + if (op->nbrp) { + gw_mtu = smap_get_int(&op->nbrp->options, "gateway_mtu", 0); + } + /* Add the flows only if gateway_mtu is configured. */ + if (gw_mtu <= 0) { + return; + } + + ds_clear(match); + ds_put_format(match, "outport == %s", op->json_key); + + ds_clear(actions); + ds_put_format(actions, + REGBIT_PKT_LARGER" = check_pkt_larger(%d);" + " next;", gw_mtu + VLAN_ETH_HEADER_LEN); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_CHK_PKT_LEN, 50, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_); + + for (size_t i = 0; i < op->od->nbr->n_ports; i++) { + struct ovn_port *rp = ovn_port_find(ports, + op->od->nbr->ports[i]->name); + if (!rp || rp == op) { + continue; + } + + if (rp->lrp_networks.ipv4_addrs) { + ds_clear(match); + ds_put_format(match, "inport == %s && outport == %s" + " && ip4 && "REGBIT_PKT_LARGER, + rp->json_key, op->json_key); + + ds_clear(actions); + /* Set icmp4.frag_mtu to gw_mtu */ + ds_put_format(actions, + "icmp4_error {" + REGBIT_EGRESS_LOOPBACK" = 1; " + "eth.dst = %s; " + "ip4.dst = ip4.src; " + "ip4.src = %s; " + "ip.ttl = 255; " + "icmp4.type = 3; /* Destination Unreachable. */ " + "icmp4.code = 4; /* Frag Needed and DF was Set. */ " + "icmp4.frag_mtu = %d; " + "next(pipeline=ingress, table=%d); };", + rp->lrp_networks.ea_s, + rp->lrp_networks.ipv4_addrs[0].addr_s, + gw_mtu, + ovn_stage_get_table(S_ROUTER_IN_ADMISSION)); + ovn_lflow_add_with_hint(lflows, op->od, + S_ROUTER_IN_LARGER_PKTS, 50, + ds_cstr(match), ds_cstr(actions), + &rp->nbrp->header_); + } + + if (rp->lrp_networks.ipv6_addrs) { + ds_clear(match); + ds_put_format(match, "inport == %s && outport == %s" + " && ip6 && "REGBIT_PKT_LARGER, + rp->json_key, op->json_key); + + ds_clear(actions); + /* Set icmp6.frag_mtu to gw_mtu */ + ds_put_format(actions, + "icmp6_error {" + REGBIT_EGRESS_LOOPBACK" = 1; " + "eth.dst = %s; " + "ip6.dst = ip6.src; " + "ip6.src = %s; " + "ip.ttl = 255; " + "icmp6.type = 2; /* Packet Too Big. */ " + "icmp6.code = 0; " + "icmp6.frag_mtu = %d; " + "next(pipeline=ingress, table=%d); };", + rp->lrp_networks.ea_s, + rp->lrp_networks.ipv6_addrs[0].addr_s, + gw_mtu, + ovn_stage_get_table(S_ROUTER_IN_ADMISSION)); + ovn_lflow_add_with_hint(lflows, op->od, + S_ROUTER_IN_LARGER_PKTS, 50, + ds_cstr(match), ds_cstr(actions), + &rp->nbrp->header_); + } + } +} + /* Local router ingress table CHK_PKT_LEN: Check packet length. * * Any IPv4 packet with outport set to the distributed gateway @@ -10603,92 +10696,8 @@ build_check_pkt_len_flows_for_lrouter( "next;"); if (od->l3dgw_port && od->l3redirect_port) { - int gw_mtu = 0; - if (od->l3dgw_port->nbrp) { - gw_mtu = smap_get_int(&od->l3dgw_port->nbrp->options, - "gateway_mtu", 0); - } - /* Add the flows only if gateway_mtu is configured. */ - if (gw_mtu <= 0) { - return; - } - - ds_clear(match); - ds_put_format(match, "outport == %s", od->l3dgw_port->json_key); - - ds_clear(actions); - ds_put_format(actions, - REGBIT_PKT_LARGER" = check_pkt_larger(%d);" - " next;", gw_mtu + VLAN_ETH_HEADER_LEN); - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_CHK_PKT_LEN, 50, - ds_cstr(match), ds_cstr(actions), - &od->l3dgw_port->nbrp->header_); - - for (size_t i = 0; i < od->nbr->n_ports; i++) { - struct ovn_port *rp = ovn_port_find(ports, - od->nbr->ports[i]->name); - if (!rp || rp == od->l3dgw_port) { - continue; - } - - if (rp->lrp_networks.ipv4_addrs) { - ds_clear(match); - ds_put_format(match, "inport == %s && outport == %s" - " && ip4 && "REGBIT_PKT_LARGER, - rp->json_key, od->l3dgw_port->json_key); - - ds_clear(actions); - /* Set icmp4.frag_mtu to gw_mtu */ - ds_put_format(actions, - "icmp4_error {" - REGBIT_EGRESS_LOOPBACK" = 1; " - "eth.dst = %s; " - "ip4.dst = ip4.src; " - "ip4.src = %s; " - "ip.ttl = 255; " - "icmp4.type = 3; /* Destination Unreachable. */ " - "icmp4.code = 4; /* Frag Needed and DF was Set. */ " - "icmp4.frag_mtu = %d; " - "next(pipeline=ingress, table=%d); };", - rp->lrp_networks.ea_s, - rp->lrp_networks.ipv4_addrs[0].addr_s, - gw_mtu, - ovn_stage_get_table(S_ROUTER_IN_ADMISSION)); - ovn_lflow_add_with_hint(lflows, od, - S_ROUTER_IN_LARGER_PKTS, 50, - ds_cstr(match), ds_cstr(actions), - &rp->nbrp->header_); - } - - if (rp->lrp_networks.ipv6_addrs) { - ds_clear(match); - ds_put_format(match, "inport == %s && outport == %s" - " && ip6 && "REGBIT_PKT_LARGER, - rp->json_key, od->l3dgw_port->json_key); - - ds_clear(actions); - /* Set icmp6.frag_mtu to gw_mtu */ - ds_put_format(actions, - "icmp6_error {" - REGBIT_EGRESS_LOOPBACK" = 1; " - "eth.dst = %s; " - "ip6.dst = ip6.src; " - "ip6.src = %s; " - "ip.ttl = 255; " - "icmp6.type = 2; /* Packet Too Big. */ " - "icmp6.code = 0; " - "icmp6.frag_mtu = %d; " - "next(pipeline=ingress, table=%d); };", - rp->lrp_networks.ea_s, - rp->lrp_networks.ipv6_addrs[0].addr_s, - gw_mtu, - ovn_stage_get_table(S_ROUTER_IN_ADMISSION)); - ovn_lflow_add_with_hint(lflows, od, - S_ROUTER_IN_LARGER_PKTS, 50, - ds_cstr(match), ds_cstr(actions), - &rp->nbrp->header_); - } - } + build_check_pkt_len_flows_for_lrp(od->l3dgw_port, lflows, + ports, match, actions); } } } From patchwork Thu Jul 8 23:15:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1502792 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=BBWbs2Ls; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (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 ozlabs.org (Postfix) with ESMTPS id 4GLXGD1cYPz9sXM for ; Fri, 9 Jul 2021 09:15:48 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 2C1C683D0C; Thu, 8 Jul 2021 23:15:46 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9m29YWMl304r; Thu, 8 Jul 2021 23:15:41 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 06B4B83D06; Thu, 8 Jul 2021 23:15:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id CEFE0C001C; Thu, 8 Jul 2021 23:15:38 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 15996C0027 for ; Thu, 8 Jul 2021 23:15:37 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id E4D2D4057B for ; Thu, 8 Jul 2021 23:15:33 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp2.osuosl.org (amavisd-new); dkim=pass (1024-bit key) header.d=redhat.com Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nudq05_TaleC for ; Thu, 8 Jul 2021 23:15:30 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp2.osuosl.org (Postfix) with ESMTPS id E21AD401E1 for ; Thu, 8 Jul 2021 23:15:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1625786128; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uhmazAd5LXTwA+FZaU94IYYD3CfjD/I9KFQ7aXxH+xI=; b=BBWbs2LsrMqqhMaKQ41rqSwpLFgq2+QEy4jb+uDSk5SegzRgIgAZVpeZg0Nt3Nljl4Edob c5BCkrFYnqc92tB9ua/0P8VOgRe6rDwG8Y2uKrlgt8Re+FfV4ivAHQGVbD/RjDilpuyUUL FB0FTGvWVDD+0fum/5Yng1UjxEAR+3M= Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-142-xQAs9WNBNfWKa2_gd-A88Q-1; Thu, 08 Jul 2021 19:15:21 -0400 X-MC-Unique: xQAs9WNBNfWKa2_gd-A88Q-1 Received: by mail-ej1-f69.google.com with SMTP id q14-20020a1709066aceb029049fa6bee56fso2414541ejs.21 for ; Thu, 08 Jul 2021 16:15:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=uhmazAd5LXTwA+FZaU94IYYD3CfjD/I9KFQ7aXxH+xI=; b=N4/z9YK4SmdqK3ZIGT19nS/8pr8eTQrOquh9+RIe5v9fZ8hKpIXztEFWQu9Pem5UsP uhpziOcKAWfuYPQNu0ImpKt0V5XUs2OVMlC41cL8dpYTQiizIW+gdgZpxhA4VqpUfCCD +pa6cyY8blojBoz65UZCT5HjXYgvsADiOzMpzwIw4keJdSQGuzigU4GR3jp8P+lRzapa 4h56X3CiacVk/NYR2jxORb+zJnK/zxCBZal7S2hgFCDBKNgRN7DFP+BkZBV3IEd3rWC6 DbzWRq825lswSDK1r02EtsgX8MqMBoJPWu2vCsfz9Ki5hQPQ2J+Bpe7dIBKgZChk3rxB mGjA== X-Gm-Message-State: AOAM531Rj3DfElSUvQtA3+2B9qQ5Va/SOa0ORXQjBbmtDrG8qiSm9x1L 8/nkou4oNZauXC+vw8FtnLWTCE4W14ZCuAiX1sc/+OMp7K2t2EyEedlR/9Zfqli1ylvFvqQjYj1 CU4WQLn0gEgI5loD2DtiRGzOY/s62+NrE3JmlnCoIjlMZckVibvP0hc3G0h0y8KLvt1lky282pL M= X-Received: by 2002:a17:906:3693:: with SMTP id a19mr24993157ejc.237.1625786120257; Thu, 08 Jul 2021 16:15:20 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyCRweH9MjHBXYyUqb2uWbStrIGApmmCnmt1FQgamANf2iYHaA0ER8pLc93nsqVG6PyCPMV6Q== X-Received: by 2002:a17:906:3693:: with SMTP id a19mr24993117ejc.237.1625786119841; Thu, 08 Jul 2021 16:15:19 -0700 (PDT) Received: from lore-desk.redhat.com (net-93-71-3-244.cust.vodafonedsl.it. [93.71.3.244]) by smtp.gmail.com with ESMTPSA id c15sm1993328edu.19.2021.07.08.16.15.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Jul 2021 16:15:19 -0700 (PDT) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Fri, 9 Jul 2021 01:15:10 +0200 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH v5 ovn 2/3] northd: enable check_pkt_larger for gw router 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" As it is already done for distributed gw router scenario, introduce check_pkt_larger logical flows for gw router use case. Co-authored-by: Numan Siddique Signed-off-by: Numan Siddique Signed-off-by: Lorenzo Bianconi --- northd/ovn-northd.8.xml | 24 ++++---- northd/ovn-northd.c | 31 +++++++--- northd/ovn_northd.dl | 82 +++++++++++++++++++++++++++ tests/ovn-northd.at | 121 ++++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 47 ++++++++++++++++ 5 files changed, 284 insertions(+), 21 deletions(-) diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index b5c961e89..f38d46234 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -3608,13 +3608,13 @@ outport = P

Ingress Table 15: Check packet length

- For distributed logical routers with distributed gateway port configured - with options:gateway_mtu to a valid integer value, this - table adds a priority-50 logical flow with the match - ip4 && outport == GW_PORT where - GW_PORT is the distributed gateway router port and applies the - action check_pkt_larger and advances the packet to the - next table. + For distributed logical routers or gateway routers with gateway + port configured with options:gateway_mtu to a valid + integer value, this table adds a priority-50 logical flow with + the match ip4 && outport == GW_PORT + where GW_PORT is the gateway router port and applies + the action check_pkt_larger and advances the packet + to the next table.

@@ -3638,14 +3638,14 @@ REGBIT_PKT_LARGER = check_pkt_larger(L); next;
     

Ingress Table 16: Handle larger packets

- For distributed logical routers with distributed gateway port configured - with options:gateway_mtu to a valid integer value, this - table adds the following priority-50 logical flow for each + For distributed logical routers or gateway routers with gateway port + configured with options:gateway_mtu to a valid integer + value, this table adds the following priority-50 logical flow for each logical router port with the match inport == LRP && outport == GW_PORT && REGBIT_PKT_LARGER, where LRP is the logical - router port and GW_PORT is the distributed gateway router - port and applies the following action for ipv4 and ipv6 respectively: + router port and GW_PORT is the gateway router port and applies + the following action for ipv4 and ipv6 respectively:

diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index c86ab927c..4aa9e242c 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -10687,17 +10687,30 @@ build_check_pkt_len_flows_for_lrouter(
         struct hmap *ports,
         struct ds *match, struct ds *actions)
 {
-    if (od->nbr) {
+    if (!od->nbr) {
+        return;
+    }
 
-        /* Packets are allowed by default. */
-        ovn_lflow_add(lflows, od, S_ROUTER_IN_CHK_PKT_LEN, 0, "1",
-                      "next;");
-        ovn_lflow_add(lflows, od, S_ROUTER_IN_LARGER_PKTS, 0, "1",
-                      "next;");
+    /* Packets are allowed by default. */
+    ovn_lflow_add(lflows, od, S_ROUTER_IN_CHK_PKT_LEN, 0, "1",
+                  "next;");
+    ovn_lflow_add(lflows, od, S_ROUTER_IN_LARGER_PKTS, 0, "1",
+                  "next;");
 
-        if (od->l3dgw_port && od->l3redirect_port) {
-            build_check_pkt_len_flows_for_lrp(od->l3dgw_port, lflows,
-                                              ports, match, actions);
+    if (od->l3dgw_port && od->l3redirect_port) {
+        /* gw router port */
+        build_check_pkt_len_flows_for_lrp(od->l3dgw_port, lflows,
+                                          ports, match, actions);
+    } else if (smap_get(&od->nbr->options, "chassis")) {
+        for (size_t i = 0; i < od->nbr->n_ports; i++) {
+            /* gw router */
+            struct ovn_port *rp = ovn_port_find(ports,
+                                                od->nbr->ports[i]->name);
+            if (!rp) {
+                continue;
+            }
+            build_check_pkt_len_flows_for_lrp(rp, lflows, ports, match,
+                                              actions);
         }
     }
 }
diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl
index e27c944a0..b59f8ea4c 100644
--- a/northd/ovn_northd.dl
+++ b/northd/ovn_northd.dl
@@ -7150,6 +7150,7 @@ for (&Router(._uuid = lr_uuid))
 
 /* Local router ingress table CHK_PKT_LEN: Check packet length.
  *
+ * For distributed routers with gateway ports.
  * Any IPv4 packet with outport set to the distributed gateway
  * router port, check the packet length and store the result in the
  * 'REGBIT_PKT_LARGER' register bit.
@@ -7160,6 +7161,18 @@ for (&Router(._uuid = lr_uuid))
  * router port and the 'REGBIT_PKT_LARGER' register bit is set,
  * generate ICMPv4 packet with type 3 (Destination Unreachable) and
  * code 4 (Fragmentation needed).
+ *
+ * For Gateway routers.
+ * Any IPv4 packet with outport set to the router port which has
+ * the option 'gateway_mtu' set, check the packet length and store
+ * the result in the 'REGBIT_PKT_LARGER' register bit.
+ *
+ * Local router ingress table LARGER_PKTS: Handle larger packets.
+ *
+ * Any IPv4 packet with outport set to the router port which has
+ * the option 'gateway_mtu' set and the 'REGBIT_PKT_LARGER' register bit
+ * is set, generate ICMPv4 packet with type 3 (Destination Unreachable) and
+ * code 4 (Fragmentation needed).
  * */
 Flow(.logical_datapath = lr_uuid,
      .stage            = s_ROUTER_IN_CHK_PKT_LEN(),
@@ -7244,6 +7257,75 @@ Flow(.logical_datapath = lr_uuid,
     rp.lrp != l3dgw_port,
     Some{var first_ipv6} = rp.networks.ipv6_addrs.nth(0).
 
+/* Gateway routers. */
+Flow(.logical_datapath = lr_uuid,
+     .stage            = s_ROUTER_IN_CHK_PKT_LEN(),
+     .priority         = 50,
+     .__match          = "outport == ${gw_mtu_rp.json_name}",
+     .actions          = "${rEGBIT_PKT_LARGER()} = check_pkt_larger(${mtu}); "
+                         "next;",
+     .external_ids     = stage_hint(gw_mtu_rp.lrp._uuid)) :-
+    r in &Router(._uuid = lr_uuid),
+    r.is_gateway,
+    gw_mtu_rp in &RouterPort(.router = r),
+    var gw_mtu = gw_mtu_rp.lrp.options.get_int_def("gateway_mtu", 0),
+    gw_mtu > 0,
+    var mtu = gw_mtu + vLAN_ETH_HEADER_LEN().
+Flow(.logical_datapath = lr_uuid,
+     .stage            = s_ROUTER_IN_LARGER_PKTS(),
+     .priority         = 50,
+     .__match          = "inport == ${rp.json_name} && outport == ${gw_mtu_rp.json_name} && "
+                         "ip4 && ${rEGBIT_PKT_LARGER()}",
+     .actions          = "icmp4_error {"
+                         "${rEGBIT_EGRESS_LOOPBACK()} = 1; "
+                         "eth.dst = ${rp.networks.ea}; "
+                         "ip4.dst = ip4.src; "
+                         "ip4.src = ${first_ipv4.addr}; "
+                         "ip.ttl = 255; "
+                         "icmp4.type = 3; /* Destination Unreachable. */ "
+                         "icmp4.code = 4; /* Frag Needed and DF was Set. */ "
+                         /* Set icmp4.frag_mtu to gw_mtu */
+                         "icmp4.frag_mtu = ${gw_mtu}; "
+                         "next(pipeline=ingress, table=0); "
+                         "};",
+     .external_ids     = stage_hint(rp.lrp._uuid)) :-
+    r in &Router(._uuid = lr_uuid),
+    r.is_gateway,
+    gw_mtu_rp in &RouterPort(.router = r),
+    var gw_mtu = gw_mtu_rp.lrp.options.get_int_def("gateway_mtu", 0),
+    gw_mtu > 0,
+    var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(),
+    rp in &RouterPort(.router = r),
+    rp.lrp != gw_mtu_rp.lrp,
+    Some{var first_ipv4} = rp.networks.ipv4_addrs.nth(0).
+Flow(.logical_datapath = lr_uuid,
+     .stage            = s_ROUTER_IN_LARGER_PKTS(),
+     .priority         = 50,
+     .__match          = "inport == ${rp.json_name} && outport == ${gw_mtu_rp.json_name} && "
+                         "ip6 && ${rEGBIT_PKT_LARGER()}",
+     .actions          = "icmp6_error {"
+                         "${rEGBIT_EGRESS_LOOPBACK()} = 1; "
+                         "eth.dst = ${rp.networks.ea}; "
+                         "ip6.dst = ip6.src; "
+                         "ip6.src = ${first_ipv6.addr}; "
+                         "ip.ttl = 255; "
+                         "icmp6.type = 2; /* Packet Too Big. */ "
+                         "icmp6.code = 0; "
+                         /* Set icmp6.frag_mtu to gw_mtu */
+                         "icmp6.frag_mtu = ${gw_mtu}; "
+                         "next(pipeline=ingress, table=0); "
+                         "};",
+     .external_ids     = stage_hint(rp.lrp._uuid)) :-
+    r in &Router(._uuid = lr_uuid),
+    r.is_gateway,
+    gw_mtu_rp in &RouterPort(.router = r),
+    var gw_mtu = gw_mtu_rp.lrp.options.get_int_def("gateway_mtu", 0),
+    gw_mtu > 0,
+    var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(),
+    rp in &RouterPort(.router = r),
+    rp.lrp != gw_mtu_rp.lrp,
+    Some{var first_ipv6} = rp.networks.ipv6_addrs.nth(0).
+
 /* Logical router ingress table GW_REDIRECT: Gateway redirect.
  *
  * For traffic with outport equal to the l3dgw_port
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 02640d163..8e67bad83 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -3787,3 +3787,124 @@ AT_CHECK([grep -w "ls_in_dhcp_options" sw0flows | sort], [0], [dnl
 
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn -- gateway mtu check pkt larger flows])
+ovn_start
+
+check ovn-sbctl chassis-add ch1 geneve 127.0.0.1
+
+check ovn-nbctl ls-add sw0
+check ovn-nbctl ls-add sw1
+
+# Create a logical router and attach both logical switches
+check ovn-nbctl lr-add lr0
+check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
+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 00:00:00:00:ff:01
+check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
+
+check ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24
+check ovn-nbctl lsp-add sw1 sw1-lr0
+check ovn-nbctl lsp-set-type sw1-lr0 router
+check ovn-nbctl lsp-set-addresses sw1-lr0 00:00:00:00:ff:02
+check ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
+
+check ovn-nbctl ls-add public
+check ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
+check ovn-nbctl lsp-add public public-lr0
+check ovn-nbctl lsp-set-type public-lr0 router
+check ovn-nbctl lsp-set-addresses public-lr0 router
+check ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
+
+check ovn-nbctl --wait=sb lrp-set-gateway-chassis lr0-public ch1
+
+ovn-sbctl dump-flows lr0 > lr0flows
+AT_CAPTURE_FILE([sw0flows])
+
+AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [dnl
+  table=15(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
+  table=16(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
+])
+
+check ovn-nbctl --wait=sb set logical_router_port lr0-public options:gateway_mtu=1500
+
+ovn-sbctl dump-flows lr0 > lr0flows
+AT_CAPTURE_FILE([sw0flows])
+
+AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [dnl
+  table=15(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
+  table=15(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); next;)
+  table=16(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+])
+
+# Clear the gateway-chassis for lr0-public
+check ovn-nbctl --wait=sb clear logical_router_port lr0-public gateway_chassis
+
+ovn-sbctl dump-flows lr0 > lr0flows
+AT_CAPTURE_FILE([sw0flows])
+
+AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [dnl
+  table=15(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
+  table=16(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
+])
+
+# Make lr0 as a gateway router.
+check ovn-nbctl --wait=sb set logical_router lr0 options:chassis=ch1
+
+ovn-sbctl dump-flows lr0 > lr0flows
+AT_CAPTURE_FILE([sw0flows])
+
+AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [dnl
+  table=15(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
+  table=15(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); next;)
+  table=16(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+])
+
+# Set gateway_mtu option on lr0-sw0
+check ovn-nbctl --wait=sb set logical_router_port lr0-sw0 options:gateway_mtu=1400
+
+ovn-sbctl dump-flows lr0 > lr0flows
+AT_CAPTURE_FILE([sw0flows])
+
+AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [dnl
+  table=15(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
+  table=15(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); next;)
+  table=15(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1418); next;)
+  table=16(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+])
+
+# Clear gateway_mtu option on lr0-public
+check ovn-nbctl --wait=sb clear logical_router_port lr0-public options
+ovn-sbctl dump-flows lr0 > lr0flows
+AT_CAPTURE_FILE([sw0flows])
+
+AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [dnl
+  table=15(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
+  table=15(lr_in_chk_pkt_len  ), priority=50   , match=(outport == "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1418); next;)
+  table=16(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+  table=16(lr_in_larger_pkts  ), priority=50   , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };)
+])
+
+AT_CLEANUP
+])
diff --git a/tests/ovn.at b/tests/ovn.at
index 41d78da6c..c818150a5 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -16534,6 +16534,53 @@ for mtu in 100 500 118; do
     test_ip6_packet_larger $mtu
 done
 
+ovn-nbctl lsp-del sw0-lr0
+
+ovn-nbctl lr-del lr0
+ovn-nbctl create Logical_Router name=lr1 options:chassis="hv1"
+ovn-nbctl lrp-add lr1 lr1-sw0 00:00:00:00:ff:01 10.0.0.1/24 1000::1/64
+ovn-nbctl lsp-add sw0 sw0-lr1
+ovn-nbctl lsp-set-type sw0-lr1 router
+ovn-nbctl lsp-set-addresses sw0-lr1 router
+ovn-nbctl lsp-set-options sw0-lr1 router-port=lr1-sw0
+
+ovn-nbctl lrp-add lr1 lr1-public 00:00:20:20:12:13 172.168.0.100/24 2000::1/64
+ovn-nbctl lsp-del public-lr0
+ovn-nbctl lsp-add public public-lr1
+ovn-nbctl lsp-set-type public-lr1 router
+ovn-nbctl lsp-set-addresses public-lr1 router
+ovn-nbctl lsp-set-options public-lr1 router-port=lr1-public
+
+ovn-nbctl lr-nat-add lr1 snat 172.168.0.100 10.0.0.0/24
+ovn-nbctl lr-nat-add lr1 snat 2000::1 1000::/64
+
+dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep _uuid | \
+awk '{print $3}')
+ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \
+logical_port=lr1-public mac="00\:00\:00\:12\:af\:11"
+
+# Try different gateway mtus and send a 142-byte packet (corresponding
+# to a 124-byte MTU).  If the MTU is less than 124, ovn-controller
+# should send icmp host not reachable with pmtu set to $mtu.
+for mtu in 100 500 118; do
+    AS_BOX([testing gw mtu $mtu])
+    check ovn-nbctl --wait=hv set logical_router_port lr1-public options:gateway_mtu=$mtu
+    ovn-sbctl dump-flows > sbflows-gw-$mtu
+    AT_CAPTURE_FILE([sbflows-gw-$mtu])
+
+    OVS_WAIT_FOR_OUTPUT([
+        as hv1 ovs-ofctl dump-flows br-int > br-int-gw-flows-$mtu
+        AT_CAPTURE_FILE([br-int-gw-flows-$mtu])
+        grep "check_pkt_larger($(expr $mtu + 18))" br-int-gw-flows-$mtu | wc -l], [0], [1
+])
+
+    AS_BOX([testing gw mtu $mtu - IPv4])
+    test_ip_packet_larger $mtu
+
+    AS_BOX([testing gw mtu $mtu - IPv6])
+    test_ip6_packet_larger $mtu
+done
+
 OVN_CLEANUP([hv1])
 AT_CLEANUP
 ])

From patchwork Thu Jul  8 23:15:11 2021
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-Patchwork-Submitter: Lorenzo Bianconi 
X-Patchwork-Id: 1502791
Return-Path: 
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
 spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org
 (client-ip=140.211.166.133; helo=smtp2.osuosl.org;
 envelope-from=ovs-dev-bounces@openvswitch.org; receiver=)
Authentication-Results: ozlabs.org;
	dkim=fail reason="signature verification failed" (1024-bit key;
 unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256
 header.s=mimecast20190719 header.b=KkvpE0/O;
	dkim-atps=neutral
Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])
	(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 ozlabs.org (Postfix) with ESMTPS id 4GLXG51BYJz9sXM
	for ; Fri,  9 Jul 2021 09:15:40 +1000 (AEST)
Received: from localhost (localhost [127.0.0.1])
	by smtp2.osuosl.org (Postfix) with ESMTP id 95E69405FE;
	Thu,  8 Jul 2021 23:15:38 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
Received: from smtp2.osuosl.org ([127.0.0.1])
	by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id 5Bi2XTxvkg7A; Thu,  8 Jul 2021 23:15:36 +0000 (UTC)
Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])
	by smtp2.osuosl.org (Postfix) with ESMTPS id 0246840589;
	Thu,  8 Jul 2021 23:15:34 +0000 (UTC)
Received: from lf-lists.osuosl.org (localhost [127.0.0.1])
	by lists.linuxfoundation.org (Postfix) with ESMTP id CC63BC0010;
	Thu,  8 Jul 2021 23:15:34 +0000 (UTC)
X-Original-To: dev@openvswitch.org
Delivered-To: ovs-dev@lists.linuxfoundation.org
Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])
 by lists.linuxfoundation.org (Postfix) with ESMTP id 1F7A4C001C
 for ; Thu,  8 Jul 2021 23:15:33 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
 by smtp3.osuosl.org (Postfix) with ESMTP id B74A060B54
 for ; Thu,  8 Jul 2021 23:15:29 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
Authentication-Results: smtp3.osuosl.org (amavisd-new);
 dkim=pass (1024-bit key) header.d=redhat.com
Received: from smtp3.osuosl.org ([127.0.0.1])
 by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
 with ESMTP id qSkFYiGO4yoV for ;
 Thu,  8 Jul 2021 23:15:26 +0000 (UTC)
X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0
Received: from us-smtp-delivery-124.mimecast.com
 (us-smtp-delivery-124.mimecast.com [216.205.24.124])
 by smtp3.osuosl.org (Postfix) with ESMTPS id 87F4760B48
 for ; Thu,  8 Jul 2021 23:15:26 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;
 s=mimecast20190719; t=1625786125;
 h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
 to:to:cc:cc:mime-version:mime-version:content-type:content-type:
 content-transfer-encoding:content-transfer-encoding:
 in-reply-to:in-reply-to:references:references;
 bh=g8Iy8relzHx/cJwuB1GN3SEoU9KIg9N+x+gL+4HoAY4=;
 b=KkvpE0/OH4omlHoZ6tf2/TNQ1DglxBFAqKGMprgIKtdWb0tI2xoiHi2aaoe0fSJjacmR3H
 MnAwuzrgxZENF6A+tjpEsK67PugFFf0fCxr5wSmosRkMQhVA3N13OnM4jEyesIexUpjvOF
 wIn4DKuh0sTFC0omDDR27QnSiQUO9HU=
Received: from mail-ed1-f71.google.com (mail-ed1-f71.google.com
 [209.85.208.71]) (Using TLS) by relay.mimecast.com with ESMTP id
 us-mta-555-XWtOu-2CPtKnqW1Nc5zrVw-1; Thu, 08 Jul 2021 19:15:24 -0400
X-MC-Unique: XWtOu-2CPtKnqW1Nc5zrVw-1
Received: by mail-ed1-f71.google.com with SMTP id
 s6-20020a0564020146b029039578926b8cso4114159edu.20
 for ; Thu, 08 Jul 2021 16:15:23 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20161025;
 h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
 :references:mime-version:content-transfer-encoding;
 bh=g8Iy8relzHx/cJwuB1GN3SEoU9KIg9N+x+gL+4HoAY4=;
 b=JUpW+aR0M4aig12a3Po2HDBS/xKcH8nzB76ugA7Bw9xvUTAlVwDyDeOXpOCnEionWp
 FXi7s2s0VM63yAcXSxDWqq0CSPX2y303JkTssEIdmGSn457QoNBNyXWc65P/vv0ZDPoB
 /vbuRiNRvV8L71Y5Pl5cA5U4OD1SjtlICIHsYE6FhwZuO1O5D8+C0LsSgqrXLO70vdIl
 0Y5O0PLP/kcB0B1x18Q0/9RdJv4uf2agc0MOZBJNNfK5OTggd68yRUHfmuHx8yV3xUjU
 A3B1iFW2JdZzklEop9oTW8tG/ZmAXkdg0W7VN0sx/BvNiwD0tL0qN/lonTGzMJ7Q7121
 tX7g==
X-Gm-Message-State: AOAM531O/ZUjG7WxpKwKoNMJaW6QlqkNyN/izYbWXHJ9o0y1YYDOG7Z6
 dY8nPhaP26Zqgk+HCzEI6Nb/m50uXG3RdlBbkaK5blJcImF4jkbg2IvZ9QZJLz0AmDSAHI3sw/c
 4kKpR8Fetg3ZXl5dTNsUrDoqwMnLczQbrf2IyFb6cZhsJy/4yuI4OeLu9RnSnka3opVTkvLQw9Z
 w=
X-Received: by 2002:a17:906:31c6:: with SMTP id
 f6mr32355753ejf.386.1625786122137;
 Thu, 08 Jul 2021 16:15:22 -0700 (PDT)
X-Google-Smtp-Source: 
 ABdhPJxVtHm5s+DalfckJ1PIHkyi6ONq98jpDlpNv+XSOZ9vyKZE3lrVVB4ezsFveMX6MFdYDQPcuQ==
X-Received: by 2002:a17:906:31c6:: with SMTP id
 f6mr32355686ejf.386.1625786121394;
 Thu, 08 Jul 2021 16:15:21 -0700 (PDT)
Received: from lore-desk.redhat.com (net-93-71-3-244.cust.vodafonedsl.it.
 [93.71.3.244])
 by smtp.gmail.com with ESMTPSA id c15sm1993328edu.19.2021.07.08.16.15.20
 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
 Thu, 08 Jul 2021 16:15:20 -0700 (PDT)
From: Lorenzo Bianconi 
To: dev@openvswitch.org
Date: Fri,  9 Jul 2021 01:15:11 +0200
Message-Id: 
 
X-Mailer: git-send-email 2.31.1
In-Reply-To: 
References: 
MIME-Version: 1.0
Authentication-Results: relay.mimecast.com;
 auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com
X-Mimecast-Spam-Score: 0
X-Mimecast-Originator: redhat.com
Subject: [ovs-dev] [PATCH v5 ovn 3/3] northd: add check_pkt_larger lflows
	for ingress traffic
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" 

Introduce check_pkt_larger action for ingress traffic
entering the cluster from a distributed gw router port
or from a gw router. This patch enables pMTU discovery
for ingress traffic.

Signed-off-by: Lorenzo Bianconi 
---
 northd/ovn-northd.8.xml |  60 +++++++++++++--
 northd/ovn-northd.c     | 166 ++++++++++++++++++++++++----------------
 northd/ovn_northd.dl    | 153 ++++++++++++++++++++++++++++++++----
 tests/ovn-northd.at     |  40 +++++-----
 tests/ovn.at            | 135 +++++++++++++++++++++++++++++++-
 5 files changed, 445 insertions(+), 109 deletions(-)

diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index f38d46234..36cd2ac28 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -1932,6 +1932,15 @@ output;
           eth.dst == E is only programmed on
           the gateway port instance on the gateway chassis.
         

+ +

+ For a distributed logical router or for gateway router where + the port is configured with options:gateway_mtu + the action of the above flow is modified adding + check_pkt_larger in order to mark the packet + setting REGBIT_PKT_LARGER if the size is greater + than the MTU +

  • @@ -2156,6 +2165,46 @@ next;

      +
    • +

      + For distributed logical routers or gateway routers with gateway port + configured with options:gateway_mtu to a valid integer + value, a priority-150 flow with the match inport == + LRP && REGBIT_PKT_LARGER && + REGBIT_EGRESS_LOOPBACK == 0, where LRP is the + logical router port and applies the following action for ipv4 + and ipv6 respectively: +

      + +
      +icmp4 {
      +    icmp4.type = 3; /* Destination Unreachable. */
      +    icmp4.code = 4;  /* Frag Needed and DF was Set. */
      +    icmp4.frag_mtu = M;
      +    eth.dst = E;
      +    ip4.dst = ip4.src;
      +    ip4.src = I;
      +    ip.ttl = 255;
      +    REGBIT_EGRESS_LOOPBACK = 1;
      +    REGBIT_PKT_LARGER 0;
      +    next(pipeline=ingress, table=0);
      +};
      +
      +icmp6 {
      +    icmp6.type = 2;
      +    icmp6.code = 0;
      +    icmp6.frag_mtu = M;
      +    eth.dst = E;
      +    ip6.dst = ip6.src;
      +    ip6.src = I;
      +    ip.ttl = 255;
      +    REGBIT_EGRESS_LOOPBACK = 1;
      +    REGBIT_PKT_LARGER 0;
      +    next(pipeline=ingress, table=0);
      +};
      +    
      +
    • +
    • For each NAT entry of a distributed logical router (with @@ -3640,12 +3689,11 @@ REGBIT_PKT_LARGER = check_pkt_larger(L); next;

      For distributed logical routers or gateway routers with gateway port configured with options:gateway_mtu to a valid integer - value, this table adds the following priority-50 logical flow for each + value, this table adds the following priority-150 logical flow for each logical router port with the match inport == LRP - && outport == GW_PORT && - REGBIT_PKT_LARGER, where LRP is the logical - router port and GW_PORT is the gateway router port and applies - the following action for ipv4 and ipv6 respectively: + && REGBIT_PKT_LARGER && !REGBIT_EGRESS_LOOPBACK, + where LRP is the logical router port and applies the following + action for ipv4 and ipv6 respectively:

      @@ -3658,6 +3706,7 @@ icmp4 {
           ip4.src = I;
           ip.ttl = 255;
           REGBIT_EGRESS_LOOPBACK = 1;
      +    REGBIT_PKT_LARGER = 0;
           next(pipeline=ingress, table=0);
       };
       
      @@ -3670,6 +3719,7 @@ icmp6 {
           ip6.src = I;
           ip.ttl = 255;
           REGBIT_EGRESS_LOOPBACK = 1;
      +    REGBIT_PKT_LARGER = 0;
           next(pipeline=ingress, table=0);
       };
           
      diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 4aa9e242c..35a82176f 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -9654,6 +9654,10 @@ build_adm_ctrl_flows_for_lrouter( } } +static void +build_check_pkt_len_action_string(struct ovn_port *op, int *pmtu, + struct ds *actions); + /* Logical router ingress Table 0: L2 Admission Control * This table drops packets that the router shouldn’t see at all based * on their Ethernet headers. @@ -9681,6 +9685,8 @@ build_adm_ctrl_flows_for_lrouter_port( * the pipeline. */ ds_clear(actions); + + build_check_pkt_len_action_string(op, NULL, actions); ds_put_format(actions, REG_INPORT_ETH_ADDR " = %s; next;", op->lrp_networks.ea_s); @@ -10575,32 +10581,110 @@ build_arp_resolve_flows_for_lrouter_port( } +static void +build_icmperr_pkt_big_flows(struct ovn_port *op, int mtu, struct hmap *lflows, + struct ds *match, struct ds *actions, + enum ovn_stage stage) +{ + if (op->lrp_networks.ipv4_addrs) { + ds_clear(match); + ds_put_format(match, + "inport == %s && ip4 && "REGBIT_PKT_LARGER + " && "REGBIT_EGRESS_LOOPBACK" == 0", op->json_key); + + ds_clear(actions); + /* Set icmp4.frag_mtu to gw_mtu */ + ds_put_format(actions, + "icmp4_error {" + REGBIT_EGRESS_LOOPBACK" = 1; " + REGBIT_PKT_LARGER" = 0; " + "eth.dst = %s; " + "ip4.dst = ip4.src; " + "ip4.src = %s; " + "ip.ttl = 255; " + "icmp4.type = 3; /* Destination Unreachable. */ " + "icmp4.code = 4; /* Frag Needed and DF was Set. */ " + "icmp4.frag_mtu = %d; " + "next(pipeline=ingress, table=%d); };", + op->lrp_networks.ea_s, + op->lrp_networks.ipv4_addrs[0].addr_s, + mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION)); + ovn_lflow_add_with_hint(lflows, op->od, stage, 150, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_); + } + + if (op->lrp_networks.ipv6_addrs) { + ds_clear(match); + ds_put_format(match, "inport == %s && ip6 && "REGBIT_PKT_LARGER + " && "REGBIT_EGRESS_LOOPBACK" == 0", op->json_key); + + ds_clear(actions); + /* Set icmp6.frag_mtu to gw_mtu */ + ds_put_format(actions, + "icmp6_error {" + REGBIT_EGRESS_LOOPBACK" = 1; " + REGBIT_PKT_LARGER" = 0; " + "eth.dst = %s; " + "ip6.dst = ip6.src; " + "ip6.src = %s; " + "ip.ttl = 255; " + "icmp6.type = 2; /* Packet Too Big. */ " + "icmp6.code = 0; " + "icmp6.frag_mtu = %d; " + "next(pipeline=ingress, table=%d); };", + op->lrp_networks.ea_s, + op->lrp_networks.ipv6_addrs[0].addr_s, + mtu, ovn_stage_get_table(S_ROUTER_IN_ADMISSION)); + ovn_lflow_add_with_hint(lflows, op->od, stage, 150, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_); + } +} + +static void +build_check_pkt_len_action_string(struct ovn_port *op, int *pmtu, + struct ds *actions) +{ + int gw_mtu = smap_get_int(&op->nbrp->options, "gateway_mtu", 0); + + if (gw_mtu > 0) { + /* Add the flows only if gateway_mtu is configured. */ + ds_put_format(actions, + REGBIT_PKT_LARGER" = check_pkt_larger(%d); ", + gw_mtu + VLAN_ETH_HEADER_LEN); + } + if (pmtu) { + *pmtu = gw_mtu; + } +} + static void build_check_pkt_len_flows_for_lrp(struct ovn_port *op, struct hmap *lflows, struct hmap *ports, struct ds *match, struct ds *actions) { - int gw_mtu = 0; + int gw_mtu; - if (op->nbrp) { - gw_mtu = smap_get_int(&op->nbrp->options, "gateway_mtu", 0); - } - /* Add the flows only if gateway_mtu is configured. */ + ds_clear(actions); + build_check_pkt_len_action_string(op, &gw_mtu, actions); if (gw_mtu <= 0) { return; } + ds_put_format(actions, "next;"); + ds_clear(match); ds_put_format(match, "outport == %s", op->json_key); - ds_clear(actions); - ds_put_format(actions, - REGBIT_PKT_LARGER" = check_pkt_larger(%d);" - " next;", gw_mtu + VLAN_ETH_HEADER_LEN); ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_CHK_PKT_LEN, 50, ds_cstr(match), ds_cstr(actions), &op->nbrp->header_); + /* ingress traffic */ + build_icmperr_pkt_big_flows(op, gw_mtu, lflows, match, actions, + S_ROUTER_IN_IP_INPUT); + for (size_t i = 0; i < op->od->nbr->n_ports; i++) { struct ovn_port *rp = ovn_port_find(ports, op->od->nbr->ports[i]->name); @@ -10608,63 +10692,9 @@ build_check_pkt_len_flows_for_lrp(struct ovn_port *op, continue; } - if (rp->lrp_networks.ipv4_addrs) { - ds_clear(match); - ds_put_format(match, "inport == %s && outport == %s" - " && ip4 && "REGBIT_PKT_LARGER, - rp->json_key, op->json_key); - - ds_clear(actions); - /* Set icmp4.frag_mtu to gw_mtu */ - ds_put_format(actions, - "icmp4_error {" - REGBIT_EGRESS_LOOPBACK" = 1; " - "eth.dst = %s; " - "ip4.dst = ip4.src; " - "ip4.src = %s; " - "ip.ttl = 255; " - "icmp4.type = 3; /* Destination Unreachable. */ " - "icmp4.code = 4; /* Frag Needed and DF was Set. */ " - "icmp4.frag_mtu = %d; " - "next(pipeline=ingress, table=%d); };", - rp->lrp_networks.ea_s, - rp->lrp_networks.ipv4_addrs[0].addr_s, - gw_mtu, - ovn_stage_get_table(S_ROUTER_IN_ADMISSION)); - ovn_lflow_add_with_hint(lflows, op->od, - S_ROUTER_IN_LARGER_PKTS, 50, - ds_cstr(match), ds_cstr(actions), - &rp->nbrp->header_); - } - - if (rp->lrp_networks.ipv6_addrs) { - ds_clear(match); - ds_put_format(match, "inport == %s && outport == %s" - " && ip6 && "REGBIT_PKT_LARGER, - rp->json_key, op->json_key); - - ds_clear(actions); - /* Set icmp6.frag_mtu to gw_mtu */ - ds_put_format(actions, - "icmp6_error {" - REGBIT_EGRESS_LOOPBACK" = 1; " - "eth.dst = %s; " - "ip6.dst = ip6.src; " - "ip6.src = %s; " - "ip.ttl = 255; " - "icmp6.type = 2; /* Packet Too Big. */ " - "icmp6.code = 0; " - "icmp6.frag_mtu = %d; " - "next(pipeline=ingress, table=%d); };", - rp->lrp_networks.ea_s, - rp->lrp_networks.ipv6_addrs[0].addr_s, - gw_mtu, - ovn_stage_get_table(S_ROUTER_IN_ADMISSION)); - ovn_lflow_add_with_hint(lflows, op->od, - S_ROUTER_IN_LARGER_PKTS, 50, - ds_cstr(match), ds_cstr(actions), - &rp->nbrp->header_); - } + /* egress traffic */ + build_icmperr_pkt_big_flows(rp, gw_mtu, lflows, match, actions, + S_ROUTER_IN_LARGER_PKTS); } } @@ -11724,8 +11754,10 @@ build_lrouter_ingress_flow(struct hmap *lflows, struct ovn_datapath *od, * down in the pipeline. */ ds_clear(actions); + + build_check_pkt_len_action_string(od->l3dgw_port, NULL, actions); ds_put_format(actions, REG_INPORT_ETH_ADDR " = %s; next;", - od->l3dgw_port->lrp_networks.ea_s); + od->l3dgw_port->lrp_networks.ea_s); ds_clear(match); ds_put_format(match, diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index b59f8ea4c..840aee50b 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -4512,7 +4512,12 @@ for (&RouterPort(.lrp = lrp, * This will save us from having to match on inport further down in * the pipeline. */ - var actions = "${rEG_INPORT_ETH_ADDR()} = ${lrp_networks.ea}; next;" in { + var gw_mtu = lrp.options.get_int_def("gateway_mtu", 0) in + var mtu = gw_mtu + vLAN_ETH_HEADER_LEN() in + var actions = "${rEG_INPORT_ETH_ADDR()} = ${lrp_networks.ea}; " ++ + if (gw_mtu > 0) { + "${rEGBIT_PKT_LARGER()} = check_pkt_larger(${mtu}); next;" + } else { "next;" } in { Flow(.logical_datapath = router._uuid, .stage = s_ROUTER_IN_ADMISSION(), .priority = 50, @@ -7204,11 +7209,12 @@ Flow(.logical_datapath = lr_uuid, var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(). Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LARGER_PKTS(), - .priority = 50, - .__match = "inport == ${rp.json_name} && outport == ${l3dgw_port_json_name} && " - "ip4 && ${rEGBIT_PKT_LARGER()}", + .priority = 150, + .__match = "inport == ${rp.json_name} && ip4 && " + "${rEGBIT_PKT_LARGER()} && ${rEGBIT_EGRESS_LOOPBACK()} == 0", .actions = "icmp4_error {" "${rEGBIT_EGRESS_LOOPBACK()} = 1; " + "${rEGBIT_PKT_LARGER()} = 0; " "eth.dst = ${rp.networks.ea}; " "ip4.dst = ip4.src; " "ip4.src = ${first_ipv4.addr}; " @@ -7229,13 +7235,44 @@ Flow(.logical_datapath = lr_uuid, rp in &RouterPort(.router = r), rp.lrp != l3dgw_port, Some{var first_ipv4} = rp.networks.ipv4_addrs.nth(0). + +Flow(.logical_datapath = lr_uuid, + .stage = s_ROUTER_IN_IP_INPUT(), + .priority = 150, + .__match = "inport == ${rp.json_name} && ip4 && " + "${rEGBIT_PKT_LARGER()} && ${rEGBIT_EGRESS_LOOPBACK()} == 0", + .actions = "icmp4_error {" + "${rEGBIT_EGRESS_LOOPBACK()} = 1; " + "${rEGBIT_PKT_LARGER()} = 0; " + "eth.dst = ${rp.networks.ea}; " + "ip4.dst = ip4.src; " + "ip4.src = ${first_ipv4.addr}; " + "ip.ttl = 255; " + "icmp4.type = 3; /* Destination Unreachable. */ " + "icmp4.code = 4; /* Frag Needed and DF was Set. */ " + /* Set icmp4.frag_mtu to gw_mtu */ + "icmp4.frag_mtu = ${gw_mtu}; " + "next(pipeline=ingress, table=0); " + "};", + .external_ids = stage_hint(rp.lrp._uuid)) :- + r in &Router(._uuid = lr_uuid), + Some{var l3dgw_port} = r.l3dgw_port, + var l3dgw_port_json_name = json_string_escape(l3dgw_port.name), + r.redirect_port_name != "", + var gw_mtu = l3dgw_port.options.get_int_def("gateway_mtu", 0), + gw_mtu > 0, + rp in &RouterPort(.router = r), + rp.lrp == l3dgw_port, + Some{var first_ipv4} = rp.networks.ipv4_addrs.nth(0). + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LARGER_PKTS(), - .priority = 50, - .__match = "inport == ${rp.json_name} && outport == ${l3dgw_port_json_name} && " - "ip6 && ${rEGBIT_PKT_LARGER()}", + .priority = 150, + .__match = "inport == ${rp.json_name} && ip6 && " + "${rEGBIT_PKT_LARGER()} && ${rEGBIT_EGRESS_LOOPBACK()} == 0", .actions = "icmp6_error {" "${rEGBIT_EGRESS_LOOPBACK()} = 1; " + "${rEGBIT_PKT_LARGER()} = 0; " "eth.dst = ${rp.networks.ea}; " "ip6.dst = ip6.src; " "ip6.src = ${first_ipv6.addr}; " @@ -7257,6 +7294,35 @@ Flow(.logical_datapath = lr_uuid, rp.lrp != l3dgw_port, Some{var first_ipv6} = rp.networks.ipv6_addrs.nth(0). +Flow(.logical_datapath = lr_uuid, + .stage = s_ROUTER_IN_IP_INPUT(), + .priority = 150, + .__match = "inport == ${rp.json_name} && ip6 && " + "${rEGBIT_PKT_LARGER()} && ${rEGBIT_EGRESS_LOOPBACK()} == 0", + .actions = "icmp6_error {" + "${rEGBIT_EGRESS_LOOPBACK()} = 1; " + "${rEGBIT_PKT_LARGER()} = 0; " + "eth.dst = ${rp.networks.ea}; " + "ip6.dst = ip6.src; " + "ip6.src = ${first_ipv6.addr}; " + "ip.ttl = 255; " + "icmp6.type = 2; /* Packet Too Big. */ " + "icmp6.code = 0; " + /* Set icmp6.frag_mtu to gw_mtu */ + "icmp6.frag_mtu = ${gw_mtu}; " + "next(pipeline=ingress, table=0); " + "};", + .external_ids = stage_hint(rp.lrp._uuid)) :- + r in &Router(._uuid = lr_uuid), + Some{var l3dgw_port} = r.l3dgw_port, + var l3dgw_port_json_name = json_string_escape(l3dgw_port.name), + r.redirect_port_name != "", + var gw_mtu = l3dgw_port.options.get_int_def("gateway_mtu", 0), + gw_mtu > 0, + rp in &RouterPort(.router = r), + rp.lrp == l3dgw_port, + Some{var first_ipv6} = rp.networks.ipv6_addrs.nth(0). + /* Gateway routers. */ Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_CHK_PKT_LEN(), @@ -7273,11 +7339,12 @@ Flow(.logical_datapath = lr_uuid, var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(). Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LARGER_PKTS(), - .priority = 50, - .__match = "inport == ${rp.json_name} && outport == ${gw_mtu_rp.json_name} && " - "ip4 && ${rEGBIT_PKT_LARGER()}", + .priority = 150, + .__match = "inport == ${rp.json_name} && ip4 && " + "${rEGBIT_PKT_LARGER()} && ${rEGBIT_EGRESS_LOOPBACK()} == 0", .actions = "icmp4_error {" "${rEGBIT_EGRESS_LOOPBACK()} = 1; " + "${rEGBIT_PKT_LARGER()} = 0; " "eth.dst = ${rp.networks.ea}; " "ip4.dst = ip4.src; " "ip4.src = ${first_ipv4.addr}; " @@ -7298,13 +7365,44 @@ Flow(.logical_datapath = lr_uuid, rp in &RouterPort(.router = r), rp.lrp != gw_mtu_rp.lrp, Some{var first_ipv4} = rp.networks.ipv4_addrs.nth(0). + +Flow(.logical_datapath = lr_uuid, + .stage = s_ROUTER_IN_IP_INPUT(), + .priority = 150, + .__match = "inport == ${rp.json_name} && ip4 && " + "${rEGBIT_PKT_LARGER()} && ${rEGBIT_EGRESS_LOOPBACK()} == 0", + .actions = "icmp4_error {" + "${rEGBIT_EGRESS_LOOPBACK()} = 1; " + "${rEGBIT_PKT_LARGER()} = 0; " + "eth.dst = ${rp.networks.ea}; " + "ip4.dst = ip4.src; " + "ip4.src = ${first_ipv4.addr}; " + "ip.ttl = 255; " + "icmp4.type = 3; /* Destination Unreachable. */ " + "icmp4.code = 4; /* Frag Needed and DF was Set. */ " + /* Set icmp4.frag_mtu to gw_mtu */ + "icmp4.frag_mtu = ${gw_mtu}; " + "next(pipeline=ingress, table=0); " + "};", + .external_ids = stage_hint(rp.lrp._uuid)) :- + r in &Router(._uuid = lr_uuid), + r.is_gateway, + gw_mtu_rp in &RouterPort(.router = r), + var gw_mtu = gw_mtu_rp.lrp.options.get_int_def("gateway_mtu", 0), + gw_mtu > 0, + var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(), + rp in &RouterPort(.router = r), + rp.lrp == gw_mtu_rp.lrp, + Some{var first_ipv4} = rp.networks.ipv4_addrs.nth(0). + Flow(.logical_datapath = lr_uuid, .stage = s_ROUTER_IN_LARGER_PKTS(), - .priority = 50, - .__match = "inport == ${rp.json_name} && outport == ${gw_mtu_rp.json_name} && " - "ip6 && ${rEGBIT_PKT_LARGER()}", + .priority = 150, + .__match = "inport == ${rp.json_name} && ip6 && " + "${rEGBIT_PKT_LARGER()} && ${rEGBIT_EGRESS_LOOPBACK()} == 0", .actions = "icmp6_error {" "${rEGBIT_EGRESS_LOOPBACK()} = 1; " + "${rEGBIT_PKT_LARGER()} = 0; " "eth.dst = ${rp.networks.ea}; " "ip6.dst = ip6.src; " "ip6.src = ${first_ipv6.addr}; " @@ -7326,6 +7424,35 @@ Flow(.logical_datapath = lr_uuid, rp.lrp != gw_mtu_rp.lrp, Some{var first_ipv6} = rp.networks.ipv6_addrs.nth(0). +Flow(.logical_datapath = lr_uuid, + .stage = s_ROUTER_IN_IP_INPUT(), + .priority = 150, + .__match = "inport == ${rp.json_name} && ip6 && " + "${rEGBIT_PKT_LARGER()} && ${rEGBIT_EGRESS_LOOPBACK()} == 0", + .actions = "icmp6_error {" + "${rEGBIT_EGRESS_LOOPBACK()} = 1; " + "${rEGBIT_PKT_LARGER()} = 0; " + "eth.dst = ${rp.networks.ea}; " + "ip6.dst = ip6.src; " + "ip6.src = ${first_ipv6.addr}; " + "ip.ttl = 255; " + "icmp6.type = 2; /* Packet Too Big. */ " + "icmp6.code = 0; " + /* Set icmp6.frag_mtu to gw_mtu */ + "icmp6.frag_mtu = ${gw_mtu}; " + "next(pipeline=ingress, table=0); " + "};", + .external_ids = stage_hint(rp.lrp._uuid)) :- + r in &Router(._uuid = lr_uuid), + r.is_gateway, + gw_mtu_rp in &RouterPort(.router = r), + var gw_mtu = gw_mtu_rp.lrp.options.get_int_def("gateway_mtu", 0), + gw_mtu > 0, + var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(), + rp in &RouterPort(.router = r), + rp.lrp == gw_mtu_rp.lrp, + Some{var first_ipv6} = rp.networks.ipv6_addrs.nth(0). + /* Logical router ingress table GW_REDIRECT: Gateway redirect. * * For traffic with outport equal to the l3dgw_port diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 8e67bad83..755c280b3 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -3837,10 +3837,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [d table=15(lr_in_chk_pkt_len ), priority=0 , match=(1), action=(next;) table=15(lr_in_chk_pkt_len ), priority=50 , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); next;) table=16(lr_in_larger_pkts ), priority=0 , match=(1), action=(next;) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) ]) # Clear the gateway-chassis for lr0-public @@ -3864,10 +3864,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [d table=15(lr_in_chk_pkt_len ), priority=0 , match=(1), action=(next;) table=15(lr_in_chk_pkt_len ), priority=50 , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); next;) table=16(lr_in_larger_pkts ), priority=0 , match=(1), action=(next;) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) ]) # Set gateway_mtu option on lr0-sw0 @@ -3881,14 +3881,14 @@ AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [d table=15(lr_in_chk_pkt_len ), priority=50 , match=(outport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); next;) table=15(lr_in_chk_pkt_len ), priority=50 , match=(outport == "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1418); next;) table=16(lr_in_larger_pkts ), priority=0 , match=(1), action=(next;) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw0" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-public" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw0" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip4.dst = ip4.src; ip4.src = 10.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw0" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:01; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff01; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1500; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1500; next(pipeline=ingress, table=0); };) ]) # Clear gateway_mtu option on lr0-public @@ -3900,10 +3900,10 @@ AT_CHECK([grep -e "chk_pkt_len" -e "lr_in_larger_pkts" lr0flows | sort], [0], [d table=15(lr_in_chk_pkt_len ), priority=0 , match=(1), action=(next;) table=15(lr_in_chk_pkt_len ), priority=50 , match=(outport == "lr0-sw0"), action=(reg9[[1]] = check_pkt_larger(1418); next;) table=16(lr_in_larger_pkts ), priority=0 , match=(1), action=(next;) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-public" && outport == "lr0-sw0" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip4 && reg9[[1]]), action=(icmp4_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };) - table=16(lr_in_larger_pkts ), priority=50 , match=(inport == "lr0-sw1" && outport == "lr0-sw0" && ip6 && reg9[[1]]), action=(icmp6_error {reg9[[0]] = 1; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-public" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip4.dst = ip4.src; ip4.src = 172.168.0.100; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-public" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:20:20:12:13; ip6.dst = ip6.src; ip6.src = fe80::200:20ff:fe20:1213; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip4 && reg9[[1]] && reg9[[0]] == 0), action=(icmp4_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip4.dst = ip4.src; ip4.src = 20.0.0.1; ip.ttl = 255; icmp4.type = 3; /* Destination Unreachable. */ icmp4.code = 4; /* Frag Needed and DF was Set. */ icmp4.frag_mtu = 1400; next(pipeline=ingress, table=0); };) + table=16(lr_in_larger_pkts ), priority=150 , match=(inport == "lr0-sw1" && ip6 && reg9[[1]] && reg9[[0]] == 0), action=(icmp6_error {reg9[[0]] = 1; reg9[[1]] = 0; eth.dst = 00:00:00:00:ff:02; ip6.dst = ip6.src; ip6.src = fe80::200:ff:fe00:ff02; ip.ttl = 255; icmp6.type = 2; /* Packet Too Big. */ icmp6.code = 0; icmp6.frag_mtu = 1400; next(pipeline=ingress, table=0); };) ]) AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index c818150a5..117c20de2 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -16438,6 +16438,52 @@ test_ip_packet_larger() { fi } +test_ip_packet_larger_ext() { + local mtu=$1 + + # Send ip packet from sw0-port1 to outside + src_mac="00000012af11" # external mac + dst_mac="000020201213" # lr0-public mac + src_ip=`ip_to_hex 172 168 0 4` + dst_ip=`ip_to_hex 172 168 0 100` + # Set the packet length to 118. + pkt_len=0076 + packet=${dst_mac}${src_mac}08004500${pkt_len}00000000400120cf + orig_packet_l3=${src_ip}${dst_ip}0900000000000000 + orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 + orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 + orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 + orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 + orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 + packet=${packet}${orig_packet_l3} + + gw_ip_garp=ffffffffffff00002020121308060001080006040001000020201213aca80064000000000000aca80064 + ext_ip_garp=ffffffffffff00000012af110806000108000604000100000012af11aca80004000000000000aca80004 + + src_ip=`ip_to_hex 172 168 0 100` + dst_ip=`ip_to_hex 172 168 0 4` + # pkt len should be 146 (28 (icmp packet) + 118 (orig ip + payload)) + reply_pkt_len=0092 + ip_csum=f397 + icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe0122b2 + icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000$(printf "%04x" $mtu) + icmp_reply=${icmp_reply}4500${pkt_len}00000000400120cf + icmp_reply=${icmp_reply}${orig_packet_l3} + echo $icmp_reply > br-phys_n1.expected + + echo $gw_ip_garp >> br-phys_n1.expected + + as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1 + as hv1 reset_pcap_file hv1-vif1 hv1/vif1 + + check as hv1 ovs-appctl netdev-dummy/receive br-phys_n1 $ext_ip_garp + sleep 1 + # Send packet from sw0-port1 to outside + check as hv1 ovs-appctl netdev-dummy/receive br-phys_n1 $packet + + OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap], [br-phys_n1.expected]) +} + test_ip6_packet_larger() { local mtu=$1 @@ -16453,7 +16499,7 @@ test_ip6_packet_larger() { local payload=${payload}0000000000000000000000000000000000000000 local payload=${payload}0000000000000000000000000000000000000000 - local ip6_hdr=6000000000583aff${ipv6_src}${ipv6_dst} + local ip6_hdr=6000000000583afe${ipv6_src}${ipv6_dst} local packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000ec7662f00001${payload} as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1 @@ -16470,7 +16516,7 @@ test_ip6_packet_larger() { mtu_needed=$(expr ${packet_bytes} - 18) if test $mtu -lt $mtu_needed; then # First construct the inner IPv6 packet. - inner_ip6=6000000000583afe${ipv6_src}${ipv6_dst} + inner_ip6=6000000000583afd${ipv6_src}${ipv6_dst} inner_icmp6=8000000062f00001 inner_icmp6_and_payload=$(icmp6_csum_inplace ${inner_icmp6}${payload} ${inner_ip6}) inner_packet=${inner_ip6}${inner_icmp6_and_payload} @@ -16492,6 +16538,53 @@ test_ip6_packet_larger() { fi } +test_ip6_packet_larger_ext() { + local mtu=$1 + + local eth_src=00000012af11 + local eth_dst=000020201213 + + local ipv6_src=20000000000000000000000000000004 + local ipv6_dst=20000000000000000000000000000001 + + local payload=0000000000000000000000000000000000000000 + local payload=${payload}0000000000000000000000000000000000000000 + local payload=${payload}0000000000000000000000000000000000000000 + local payload=${payload}0000000000000000000000000000000000000000 + + local ip6_hdr=6000000000583afe${ipv6_src}${ipv6_dst} + local packet=${eth_dst}${eth_src}86dd${ip6_hdr}9000cc7662f00001${payload} + + local ns=ffffffffffff00002020121308060001080006040001000020201213aca80064000000000000aca80064 + echo $ns > br-phys_n1.expected + + as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1 + as hv1 reset_pcap_file hv1-vif1 hv1/vif1 + + local na_ip6_hdr=6000000000203aff${ipv6_src}${ipv6_dst} + local na=${eth_dst}${eth_src}86dd${na_ip6_hdr}8800d78440000000${ipv6_src}0201${eth_src} + check as hv1 ovs-appctl netdev-dummy/receive br-phys_n1 $na + sleep 1 + check as hv1 ovs-appctl netdev-dummy/receive br-phys_n1 $packet + AT_CAPTURE_FILE([trace-$mtu]) + + # First construct the inner IPv6 packet. + inner_ip6=6000000000583afe${ipv6_src}${ipv6_dst} + inner_icmp6=9000000062f00001 + inner_icmp6_and_payload=$(icmp6_csum_inplace ${inner_icmp6}${payload} ${inner_ip6}) + inner_packet=${inner_ip6}${inner_icmp6_and_payload} + + # Then the outer. + outer_ip6=6000000000883afe${ipv6_dst}${ipv6_src} + outer_icmp6_and_payload=$(icmp6_csum_inplace 020000000000$(printf "%04x" $mtu)${inner_packet} $outer_ip6) + outer_packet=${outer_ip6}${outer_icmp6_and_payload} + + icmp6_reply=${eth_src}${eth_dst}86dd${outer_packet} + echo $icmp6_reply >> br-phys_n1.expected + + OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap], [br-phys_n1.expected]) +} + wait_for_ports_up ovn-nbctl --wait=hv sync @@ -16524,7 +16617,7 @@ for mtu in 100 500 118; do OVS_WAIT_FOR_OUTPUT([ as hv1 ovs-ofctl dump-flows br-int > br-int-flows-$mtu AT_CAPTURE_FILE([br-int-flows-$mtu]) - grep "check_pkt_larger($(expr $mtu + 18))" br-int-flows-$mtu | wc -l], [0], [1 + grep "check_pkt_larger($(expr $mtu + 18))" br-int-flows-$mtu | wc -l], [0], [3 ]) AS_BOX([testing mtu $mtu - IPv4]) @@ -16534,6 +16627,23 @@ for mtu in 100 500 118; do test_ip6_packet_larger $mtu done +AS_BOX([testing mtu $mtu]) +check ovn-nbctl --wait=hv set logical_router_port lr0-public options:gateway_mtu=100 +ovn-sbctl dump-flows > ext-sbflows-100 +AT_CAPTURE_FILE([ext-sbflows-$mtu]) + +OVS_WAIT_FOR_OUTPUT([ + as hv1 ovs-ofctl dump-flows br-int > ext-br-int-flows-100 + AT_CAPTURE_FILE([ext-br-int-flows-100]) + grep "check_pkt_larger(118)" ext-br-int-flows-100 | wc -l], [0], [3 +]) + +AS_BOX([testing ext mtu 100 - IPv4]) +test_ip_packet_larger_ext 100 + +AS_BOX([testing mtu 100 - IPv6]) +test_ip6_packet_larger_ext 100 + ovn-nbctl lsp-del sw0-lr0 ovn-nbctl lr-del lr0 @@ -16571,7 +16681,7 @@ for mtu in 100 500 118; do OVS_WAIT_FOR_OUTPUT([ as hv1 ovs-ofctl dump-flows br-int > br-int-gw-flows-$mtu AT_CAPTURE_FILE([br-int-gw-flows-$mtu]) - grep "check_pkt_larger($(expr $mtu + 18))" br-int-gw-flows-$mtu | wc -l], [0], [1 + grep "check_pkt_larger($(expr $mtu + 18))" br-int-gw-flows-$mtu | wc -l], [0], [3 ]) AS_BOX([testing gw mtu $mtu - IPv4]) @@ -16581,6 +16691,23 @@ for mtu in 100 500 118; do test_ip6_packet_larger $mtu done +AS_BOX([testing gw mtu $mtu]) +check ovn-nbctl --wait=hv set logical_router_port lr1-public options:gateway_mtu=100 +ovn-sbctl dump-flows > ext-gw-sbflows-100 +AT_CAPTURE_FILE([ext-gw-sbflows-$mtu]) + +OVS_WAIT_FOR_OUTPUT([ + as hv1 ovs-ofctl dump-flows br-int > ext-br-int-gw-flows-100 + AT_CAPTURE_FILE([ext-br-int-gw-flows-100]) + grep "check_pkt_larger(118)" ext-br-int-gw-flows-100 | wc -l], [0], [3 +]) + +AS_BOX([testing gw ext mtu 100 - IPv4]) +test_ip_packet_larger_ext 100 + +AS_BOX([testing gw mtu 100 - IPv6]) +test_ip6_packet_larger_ext 100 + OVN_CLEANUP([hv1]) AT_CLEANUP ])