From patchwork Wed Apr 24 09:56:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naveen Yerramneni X-Patchwork-Id: 1927080 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=k7w1+jl4; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=L5R8tfpC; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VPZBn3Lcjz1yZr for ; Wed, 24 Apr 2024 19:56:33 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 74B1A407D8; Wed, 24 Apr 2024 09:56:31 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id y4_mbdY7Eq4Y; Wed, 24 Apr 2024 09:56:30 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 6429340801 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=k7w1+jl4; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=L5R8tfpC Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 6429340801; Wed, 24 Apr 2024 09:56:28 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 505CAC008E; Wed, 24 Apr 2024 09:56:28 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 10252C0037 for ; Wed, 24 Apr 2024 09:56:27 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id E2FA3407EE for ; Wed, 24 Apr 2024 09:56:26 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id P7eYp9jy6qcc for ; Wed, 24 Apr 2024 09:56:25 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=148.163.155.12; helo=mx0b-002c1b01.pphosted.com; envelope-from=naveen.yerramneni@nutanix.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp4.osuosl.org 8FC7B40791 Authentication-Results: smtp4.osuosl.org; dmarc=pass (p=none dis=none) header.from=nutanix.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 8FC7B40791 Received: from mx0b-002c1b01.pphosted.com (mx0b-002c1b01.pphosted.com [148.163.155.12]) by smtp4.osuosl.org (Postfix) with ESMTPS id 8FC7B40791 for ; Wed, 24 Apr 2024 09:56:24 +0000 (UTC) Received: from pps.filterd (m0127844.ppops.net [127.0.0.1]) by mx0b-002c1b01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 43O0S6s4031089; Wed, 24 Apr 2024 02:56:23 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :content-transfer-encoding:content-type:mime-version; s= proofpoint20171006; bh=sBViVx2bM24leWhFqMjDsU4T9+ym7g0f3Fb3vZqC3 EE=; b=k7w1+jl4+Q/vdYx+Ff/JwmVPcIAKW5N3zTQScDP6vk8rzC9oW+LRRuXrV QgElmJZb6JeE/927hKxSB9F908CJ2P4H6HatKkaMGHcGvEWyRR6dkhlp1pv/4vri HIqDsZ/62GMK22KvWVZ59lzqHWNahUTicCn+R3kiEimMWjs8uKFGIdWMXtUIPg0N RvH4OEqZZTUQzsqyix6rlQjUACM7K8Nre2/I84pk/aXYOKudJUnnIRpFMiU6KIgU p60ZdoeKvK0CjVYjihx2t5RJuOXpQOVU5ls7ywxUr6wMJVAV2EHTQ4EZ2LwwiGMY DxAPS3SiyzvyRA9Khk5ylU6RsaSnA== Received: from nam02-dm3-obe.outbound.protection.outlook.com (mail-dm3nam02lp2041.outbound.protection.outlook.com [104.47.56.41]) by mx0b-002c1b01.pphosted.com (PPS) with ESMTPS id 3xmd7yfstw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 24 Apr 2024 02:56:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=HrEtQ6y7NUuiLewRu+Cm6PiNYp/5zPhYJdJpGqi9HiWgeWG53V9nppfB1JIkn/vCPfW/7TFc1bGar0JpImXSMMUeTONE78HE7wmGFDrb1PIkpvaD2CM45nbtCh9gmF5+7ldAVGTBiUOiV+gBS5tIkV7dEaqR+c5H5UJaL82EZnBqw9Yp6oFYtjSzaUxRzjysAJZ8w/6NoqwegOFlLRO3LMfHYj2jJnTAsRInFid1WAIaD188Bnju0iM/7gsOeJDnUYCl0kTeDkJG2cNciT4Gg2ZAXCkt/ChOzSfPPe5CZz5fGec3CoUmpQqn6DDn6x/Tn1QX0CycFDn/tJPkASu7Rg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=sBViVx2bM24leWhFqMjDsU4T9+ym7g0f3Fb3vZqC3EE=; b=IFo9vFkE9n9p0Ut17c88UCHCC6XHF8qSQrlQltzvp4YU57jmP/klERqtQW1++lFS4ordGuDHbbClmmvZbLCd10cTLG/Yp9JEFtWUq4lOqYBhF1nCBjq+OAezfvcMhFb8ttkU2nY62axUvXjpi4D5QPFvo2wFIZ5dO27UJDU900l+hNX6ap0l2sn6OtbMdRmLu3zH5pDgGw3SDgsBATizPhnutAGBx8f151pOln87aK960fxVdhK0fE9U4pZfqUNuct6GuyQNG39s53L054r5chyPYAr5dgH/QO5WtMexuW8/MeHZ5Qfnv5pVakf+cHlUb74FmbGSyCf1M4FHoIT8cg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nutanix.com; dmarc=pass action=none header.from=nutanix.com; dkim=pass header.d=nutanix.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=sBViVx2bM24leWhFqMjDsU4T9+ym7g0f3Fb3vZqC3EE=; b=L5R8tfpCDk9rrsg5b65I3nAw9JA8BlJZzPaPOSSa2zWdQjxz5PkdQNziJ5cXAxDfz1HvzNhXaDegvLIfDdu39vC5sl0xjP6a2031sJIas2lTV7i3RbV6T5w1oxu9QjjXC/Go/jLjnZulwBAkIUtdpozRuFkH05Xau9ifFwdKBhYZv02FX50P59fGLwpgqDeFjIYlhEBvxgfy+aIFazfrYNYPtOgEREaKUZ6R8yGfsp++oBk9bIth6sc3MAx7zKIoB24yDvYbCLcvfTNBg2N3eOPrNxoBKBePGduoGRUlHzlEz0lmKCQ4cqu2uoZKZiFmkxOL/MuRvm+sK3UsUq2BZA== Received: from SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) by SJ0PR02MB7453.namprd02.prod.outlook.com (2603:10b6:a03:29b::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7519.23; Wed, 24 Apr 2024 09:56:21 +0000 Received: from SJ0PR02MB7808.namprd02.prod.outlook.com ([fe80::d95e:4ad8:aa24:7c4]) by SJ0PR02MB7808.namprd02.prod.outlook.com ([fe80::d95e:4ad8:aa24:7c4%3]) with mapi id 15.20.7519.021; Wed, 24 Apr 2024 09:56:21 +0000 From: Naveen Yerramneni To: dev@openvswitch.org Date: Wed, 24 Apr 2024 09:56:05 +0000 Message-Id: <20240424095607.129155-2-naveen.yerramneni@nutanix.com> X-Mailer: git-send-email 2.36.6 In-Reply-To: <20240424095607.129155-1-naveen.yerramneni@nutanix.com> References: <20240424095607.129155-1-naveen.yerramneni@nutanix.com> X-ClientProxiedBy: PH8PR21CA0001.namprd21.prod.outlook.com (2603:10b6:510:2ce::25) To SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR02MB7808:EE_|SJ0PR02MB7453:EE_ X-MS-Office365-Filtering-Correlation-Id: 6a4f14d4-d7f8-4d70-17a7-08dc6444cb62 x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230031|366007|52116005|376005|1800799015|38350700005; X-Microsoft-Antispam-Message-Info: cg9Js0taV4YCoBP7hNK0rrXQ3OGY2krSxUyVspVEMLCzBWSi0K+pwFOa0X6ept3mZO8W3aEKJhKuxiJtmDcyMq65Ox0URVrvm9N9egjDNL8GdGYWyRVrFITSOjrVes9WZJQWXx+3o9qyEAGYyNV1dYKr180ljirxK4zRrcLhiRX6YhI7NogrnE6LM2GbvCkER4TUl/t+CAAhmq3IBpi5EwWLK7HxAczXZafY5r/HKgj4bZmWk6FnQZZIOPRFc2Y+dCBGRpuXLUjGP36+F1sp/8oLt72arP/hQKqPTrKBAcwEJaKmsPdfPcJtystjHOYV+20bvqWq1Q0pnDL03qpI7UwkV0rF8bsK3sb/gmPRoBHNsr/npYFplGrt60GVRslzza/GZeyHMS5ZzPfzC5MFPTRXRcCTxk8R54EpwE5ERhPh/0dPGH9deRMZ/eV9MJzd0uxJ1fbdXVSFJdDlUETHabIGWU7bM1HPnP4+/j5EacKh640jiV1Ia/A76rO5i272g4aaJoERYoqQGaq82apziGtOHc9x0QOWVcos1PC9IX/OVU4EHLuFBDjkTntFAN0vScRQNFg6qAWJLSuR2lCmCgbcV+oswkxOKFXJur/RtY3EcHrvIL7Snu2d9S1BjJjYDaX4Hj2eG321/2yDTg7VQfl/FHbE8eK2h2+7FTiWzuMYGeitte9StFL7wWTa71xzrjCOBis8PC/26/3Q8Z8OYTWHCpPjrCCZRWofy4t/sx4dgE4jmGLPXmXvDoD+ftrDJt7vTKQ7uGTYgqGT1MjCujvV0cO4oQThknLj2QJZrlq3lqxmPYofgHr9J+tD4t3weBNprUKtp4eXsvV33fDBV4QpWk+ZO8b5hGws+tTraahTsulMqMM9zxvb/v6d98m7dTIFddPOj9iedBSMBWCZWw9/nvXMUiYkiO+T1HithegtfRQShTO+pvp5mXsiC37TMtNaT14hyirE/4GmMm/3jNI+4QG/rULc6xPv93f2BFTOQB4J7LKm2p5xr0LpANXWvkVe4KKP+/OtF4YBuci24GCttgiyFJFzsrrzOZmhqQIgrhlelBzy0E5j+BRRONKlCQwgDcHe92Uot5IvgADGPq5dMKplnji8kvOndiXvvfez5lh4mKLD+l0MI4rWk3ZGCdUON21fCUemBMXqNsWDV564TNZhq/PDi8zSjo/Pk9nHVF3QOeRtxAFRHftfoFMe+/eVvHU9xISV8N2xDkStgRzJc0sfqztU5Hwbk/ez7uozi7S0QnZSoKbA8+njL2MTiyLS7nweGgG352Gm732+EKCKV4uiowAYfonXqj9roBNjnr4iYqZwAC8R3beymoE5a6bVo6A9Gf7jff8zhrNrLQ== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SJ0PR02MB7808.namprd02.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(366007)(52116005)(376005)(1800799015)(38350700005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 7Ufud4ZGLRxE0yXeIMjDyK3I8ll/07ei+ToSrT+oAVkEGudqh5tMJzYlO3gfuAHSqXSSEinsF1HkAB3lCqj58/Exe7eZ4+eaOjekvjCuyY+Ern+3Dpjdm1dWXXgoX+pzKvNU+H14mfKeiftPjWTgNjIgUyS5PtN6fsb4UxqmdtD6uF2cssKHU6lXXAQVFA53Ti2+qvP4KnzQZgGdc0Jpqftyhtd8vAXaJWKAtYPxpYn2w/SV+KPK2RfAH0ZYDHKMn1VMItZKTTx0UFDBqnSt4VOIlmzrMuXuGInJAyxbQ8oiVyMXSLy66nPKPIHoesQcG3RLi1BUomdgbrYo769aaz36e527rQGV3nvZ+poQDkpzO6uCKwiVsqVxF4RWOZ9dUvxLQhG9Qzs8MV5Oj6V88bsIldyzNKymi9opzeXSPfi14vqS1aVINmqt7X1yEiANQhPJCIDCgnSPUScvKuW5I2cDSbfoTHEpJbsq4+WNeQASv7wJW0Cnu/9Ic2ffcsnePkWH6htdqY9AP2dTSSOaDffh4o3HeZ069s/UYEPbjZIv63qrGioNNKNgX6oqa831u55F2Z5bvIKHUTrZHIsZYgdyrcR2V7S1Xk1FdH8m+orzFVqhsIrC2j+FKdhanyAiXglOBr//CuiBYWhooPXLOmOqr7RzKlmo9aDTntEiXRL/Ph+wC3FvGiKq/2ENUV3oQQY4vdv2aw1WqgittqR60zInQtjkQHiJ2U9XsbP+wexuteAIVdwqPa8I4hv3RHuvn2MWJioB2z8bYdA2hTarbQu2Hm8zNHH22/5p22jN9cCRKVeWuo6S/2IU3KzRIr/mcHiZo8J8GuvQ7eGivqTcNrAxuYbN5w3w/hy9herMVBgxLthruGNPvM1OHZQfd4Wp2RuYT2BZUT2by/LJFx5YL0h+xM0YnbqxoF/SU2pjC/6nj+XQO4pi3rrTCDgUyJI0fMQ1lUZ4auU02+I2OpLfqnQpRKCicXOYW/tEuzo/3HgVd7pezzAdhtz0na5l9VtQngZcTeHWXqRvJUsZTJp1CDFLOGXI8Ocu4yrANAlhMgEeeb98O8paFXB5dq8x6R1S8uDZHb0ZkX4DiK5hL+ueNlnbYVwsm4rPgmu7eAUPY5erpk85yJZANJrDa1mv2Iodyg+9n9o0riYKkV4yoNeGnNsJ2TUymh1tJ03L2xMDtkEApwJqjdEoOGBMX9x3fCjdzbGQIav0Ng4UI6gXGvI05lPpqZ5sYniEQSfp3Ayw3RmubH7oJds0+j8FdE5BcHXVYEgeV+TcBhnovyb8cjaPXeQ2+rv2gDPKZ8uOAXSrNuCg0vnUgdUYfxWvwars2BXrYgfSW2DTmDMKp0jyb1VQN33c0jJVyikQs4jkWKxjYDin3f04ZjmDa6a9TsYEo1bv3/bQG0e8ql8wnvRhtGoJtPC/2Mt9w09tiTJCv1qqxGW6m53rJ0KmE0ePE6Nt/GykJvRK++KbnrTQHqKoRLpjOIOs9myypPlk356RHc1vTFIdmzc/ziRPL+ScRwht8+X33n7CYUhtWpeMR4ezxA6YqsjvVYVL3JtO/FLuFaVxl3Pfr6EtYHF6ZNBVux9aUCK74yUaTPGkjV/wyZJkrUgclpfgSM1UMmK9IIeFz8/QH44= X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6a4f14d4-d7f8-4d70-17a7-08dc6444cb62 X-MS-Exchange-CrossTenant-AuthSource: SJ0PR02MB7808.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Apr 2024 09:56:21.3666 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 1JlPAVWNVSIWUskqhdl/aaMISBqfDWUD+De/n1t9YyxfmtEDdARG9RKXuw+bFeJXgdzNKGDBtiSOr0EPXO+DsE9pe4BOu5hwBOQY4HUbsX8= X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR02MB7453 X-Proofpoint-GUID: jG6g0z9M8Ruv6x9iJrM6gajp4fr6sqwS X-Proofpoint-ORIG-GUID: jG6g0z9M8Ruv6x9iJrM6gajp4fr6sqwS X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.650,FMLib:17.11.176.26 definitions=2024-04-24_07,2024-04-23_02,2023-05-22_02 X-Proofpoint-Spam-Reason: safe Cc: huzaifa.c@nutanix.com Subject: [ovs-dev] [PATCH OVN v6 1/3] actions: DHCP Relay Agent support for overlay IPv4 subnets. 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" NEW OVN ACTIONS --------------- 1. dhcp_relay_req_chk(, ) - This action executes on the source node on which the DHCP request originated. - This action relays the DHCP request coming from client to the server. Relay-ip is used to update GIADDR in the DHCP header. 2. dhcp_relay_resp_chk(, ) - This action executes on the first node (RC node) which processes the DHCP response from the server. - This action updates the destination MAC and destination IP so that the response can be forwarded to the appropriate node from which request was originated. - Relay-ip, server-ip are used to validate GIADDR and SERVER ID in the DHCP payload. Signed-off-by: Naveen Yerramneni --- include/ovn/actions.h | 27 ++++++++++ lib/actions.c | 116 ++++++++++++++++++++++++++++++++++++++++++ ovn-sb.xml | 62 ++++++++++++++++++++++ tests/ovn.at | 34 +++++++++++++ utilities/ovn-trace.c | 67 ++++++++++++++++++++++++ 5 files changed, 306 insertions(+) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index f697dff39..ab2f3856c 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -96,6 +96,8 @@ struct collector_set_ids; OVNACT(LOOKUP_ND_IP, ovnact_lookup_mac_bind_ip) \ OVNACT(PUT_DHCPV4_OPTS, ovnact_put_opts) \ OVNACT(PUT_DHCPV6_OPTS, ovnact_put_opts) \ + OVNACT(DHCPV4_RELAY_REQ_CHK, ovnact_dhcp_relay) \ + OVNACT(DHCPV4_RELAY_RESP_CHK, ovnact_dhcp_relay) \ OVNACT(SET_QUEUE, ovnact_set_queue) \ OVNACT(DNS_LOOKUP, ovnact_result) \ OVNACT(LOG, ovnact_log) \ @@ -389,6 +391,15 @@ struct ovnact_put_opts { size_t n_options; }; +/* OVNACT_DHCP_RELAY. */ +struct ovnact_dhcp_relay { + struct ovnact ovnact; + int family; + struct expr_field dst; /* 1-bit destination field. */ + ovs_be32 relay_ipv4; + ovs_be32 server_ipv4; +}; + /* Valid arguments to SET_QUEUE action. * * QDISC_MIN_QUEUE_ID is the default queue, so user-defined queues should @@ -765,6 +776,22 @@ enum action_opcode { /* multicast group split buffer action. */ ACTION_OPCODE_MG_SPLIT_BUF, + + /* "dhcp_relay_req_chk(relay_ip, server_ip)". + * + * Arguments follow the action_header, in this format: + * - The 32-bit DHCP relay IP. + * - The 32-bit DHCP server IP. + */ + ACTION_OPCODE_DHCP_RELAY_REQ_CHK, + + /* "dhcp_relay_resp_chk(relay_ip, server_ip)". + * + * Arguments follow the action_header, in this format: + * - The 32-bit DHCP relay IP. + * - The 32-bit DHCP server IP. + */ + ACTION_OPCODE_DHCP_RELAY_RESP_CHK, }; /* Header. */ diff --git a/lib/actions.c b/lib/actions.c index 361d55009..6cd60366a 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -1869,6 +1869,8 @@ is_paused_nested_action(enum action_opcode opcode) case ACTION_OPCODE_BFD_MSG: case ACTION_OPCODE_ACTIVATION_STRATEGY_RARP: case ACTION_OPCODE_MG_SPLIT_BUF: + case ACTION_OPCODE_DHCP_RELAY_REQ_CHK: + case ACTION_OPCODE_DHCP_RELAY_RESP_CHK: default: return false; } @@ -2610,6 +2612,114 @@ ovnact_controller_event_free(struct ovnact_controller_event *event) free_gen_options(event->options, event->n_options); } +static void +format_dhcpv4_relay_chk(const char *name, + const struct ovnact_dhcp_relay *dhcp_relay, + struct ds *s) +{ + expr_field_format(&dhcp_relay->dst, s); + ds_put_format(s, " = %s("IP_FMT", "IP_FMT");", + name, + IP_ARGS(dhcp_relay->relay_ipv4), + IP_ARGS(dhcp_relay->server_ipv4)); +} + +static void +parse_dhcp_relay_chk(struct action_context *ctx, + const struct expr_field *dst, + struct ovnact_dhcp_relay *dhcp_relay) +{ + /* Skip dhcp_relay_req_chk/dhcp_relay_resp_chk( */ + lexer_force_match(ctx->lexer, LEX_T_LPAREN); + + /* Validate that the destination is a 1-bit, modifiable field. */ + char *error = expr_type_check(dst, 1, true, ctx->scope); + if (error) { + lexer_error(ctx->lexer, "%s", error); + free(error); + return; + } + dhcp_relay->dst = *dst; + + /* Parse relay ip and server ip. */ + if (ctx->lexer->token.format == LEX_F_IPV4) { + dhcp_relay->family = AF_INET; + dhcp_relay->relay_ipv4 = ctx->lexer->token.value.ipv4; + lexer_get(ctx->lexer); + lexer_match(ctx->lexer, LEX_T_COMMA); + if (ctx->lexer->token.format == LEX_F_IPV4) { + dhcp_relay->family = AF_INET; + dhcp_relay->server_ipv4 = ctx->lexer->token.value.ipv4; + lexer_get(ctx->lexer); + } else { + lexer_syntax_error(ctx->lexer, "expecting IPv4 dhcp server ip"); + return; + } + } else { + lexer_syntax_error(ctx->lexer, "expecting IPv4 dhcp relay " + "and server ips"); + return; + } + lexer_force_match(ctx->lexer, LEX_T_RPAREN); +} + +static void +encode_dhcpv4_relay_chk(const struct ovnact_dhcp_relay *dhcp_relay, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts, + enum action_opcode dhcp_relay_opcode) +{ + struct mf_subfield dst = expr_resolve_field(&dhcp_relay->dst); + size_t oc_offset = encode_start_controller_op(dhcp_relay_opcode, true, + ep->ctrl_meter_id, + ofpacts); + nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); + ovs_be32 ofs = htonl(dst.ofs); + ofpbuf_put(ofpacts, &ofs, sizeof ofs); + ofpbuf_put(ofpacts, &dhcp_relay->relay_ipv4, + sizeof(dhcp_relay->relay_ipv4)); + ofpbuf_put(ofpacts, &dhcp_relay->server_ipv4, + sizeof(dhcp_relay->server_ipv4)); + encode_finish_controller_op(oc_offset, ofpacts); +} + +static void +format_DHCPV4_RELAY_REQ_CHK(const struct ovnact_dhcp_relay *dhcp_relay, + struct ds *s) +{ + format_dhcpv4_relay_chk("dhcp_relay_req_chk",dhcp_relay, s); +} + +static void +encode_DHCPV4_RELAY_REQ_CHK(const struct ovnact_dhcp_relay *dhcp_relay, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_dhcpv4_relay_chk(dhcp_relay, ep, ofpacts, + ACTION_OPCODE_DHCP_RELAY_REQ_CHK); +} + +static void +format_DHCPV4_RELAY_RESP_CHK(const struct ovnact_dhcp_relay *dhcp_relay, + struct ds *s) +{ + format_dhcpv4_relay_chk("dhcp_relay_resp_chk",dhcp_relay, s); +} + +static void +encode_DHCPV4_RELAY_RESP_CHK(const struct ovnact_dhcp_relay *dhcp_relay, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_dhcpv4_relay_chk(dhcp_relay, ep, ofpacts, + ACTION_OPCODE_DHCP_RELAY_RESP_CHK); +} + +static void ovnact_dhcp_relay_free( + struct ovnact_dhcp_relay *dhcp_relay OVS_UNUSED) +{ +} + static void parse_put_opts(struct action_context *ctx, const struct expr_field *dst, struct ovnact_put_opts *po, const struct hmap *gen_opts, @@ -5312,6 +5422,12 @@ parse_set_action(struct action_context *ctx) lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { parse_chk_lb_aff(ctx, &lhs, ovnact_put_CHK_LB_AFF(ctx->ovnacts)); + } else if (lexer_match_id(ctx->lexer, "dhcp_relay_req_chk")) { + parse_dhcp_relay_chk(ctx, &lhs, + ovnact_put_DHCPV4_RELAY_REQ_CHK(ctx->ovnacts)); + } else if (lexer_match_id(ctx->lexer, "dhcp_relay_resp_chk")) { + parse_dhcp_relay_chk(ctx, &lhs, + ovnact_put_DHCPV4_RELAY_RESP_CHK(ctx->ovnacts)); } else { parse_assignment_action(ctx, false, &lhs); } diff --git a/ovn-sb.xml b/ovn-sb.xml index 4c26c6714..81ed824d0 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -2801,6 +2801,68 @@ tcp.flags = RST; use statistics of MAC cache.

+ +
R = dhcp_relay_req_chk(relay-ip, + server-ip);
+
+

+ Parameters: Logical Router Port IP relay-ip, DHCP + Server IP server-ip. +

+ +

+ Result: stored to a 1-bit subfield R. +

+ +

+ This action executes on the source node on which the DHCP request + (DHCPDISCOVER or DHCPREQUEST) originated. +

+ +

+ When this action applied successfully on the DHCP request packet, + it updates GIADDR in the DHCP packet with relay-ip and + stores 1 in R. +

+ +

+ When this action failed to apply on the packet, it leaves the + packet unchanged and stores 0 in R. +

+
+ +
R = dhcp_relay_resp_chk(relay-ip, + server-ip);
+
+

+ Parameters: Logical Router Port IP relay-ip, DHCP + Server IP server-ip. +

+ +

+ Result: stored to a 1-bit subfield R. +

+ +

+ This action executes on the first node (Redirect Chassis node) + which processes the DHCP response(DHCPOFFER, DHCPACK) from the DHCP + server. +

+ +

+ When this action applied successfully on the DHCP response packet, + it updates the destination MAC and destination IP in the packet and + stores 1 in R. + relay-ip and server-ip are used to validate + GIADDR and SERVER-ID in the DHCP response packet. +

+ +

+ When this action failed to apply on the packet, it leaves the + packet unchanged and stores 0 in R. +

+
+ diff --git a/tests/ovn.at b/tests/ovn.at index dc6aafd53..1ad4159cf 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1653,6 +1653,40 @@ reg1[[0]] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4); reg1[[0]] = put_dhcp_opts(offerip=1.2.3.4, domain_search_list=1.2.3.4); DHCPv4 option domain_search_list requires string value. +#dhcp_relay_req_chk +reg9[[7]] = dhcp_relay_req_chk(192.168.1.1, 172.16.1.1); + encodes as controller(userdata=00.00.00.1c.00.00.00.00.80.01.08.08.00.00.00.07.c0.a8.01.01.ac.10.01.01,pause) + +reg9[[7]] = dhcp_relay_req_chk(192.168.1.1,172.16.1.1); + formats as reg9[[7]] = dhcp_relay_req_chk(192.168.1.1, 172.16.1.1); + encodes as controller(userdata=00.00.00.1c.00.00.00.00.80.01.08.08.00.00.00.07.c0.a8.01.01.ac.10.01.01,pause) + +reg9[[7..8]] = dhcp_relay_req_chk(192.168.1.1, 172.16.1.1); + Cannot use 2-bit field reg9[[7..8]] where 1-bit field is required. + +reg9[[7]] = dhcp_relay_req_chk("192.168.1.1", "172.16.1.1"); + Syntax error at `"192.168.1.1"' expecting IPv4 dhcp relay and server ips. + +reg9[[7]] = dhcp_relay_req_chk(192.168.1, 172.16.1.1); + Invalid numeric constant. + +#dhcp_relay_resp_chk +reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 172.16.1.1); + encodes as controller(userdata=00.00.00.1d.00.00.00.00.80.01.08.08.00.00.00.08.c0.a8.01.01.ac.10.01.01,pause) + +reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1,172.16.1.1); + formats as reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 172.16.1.1); + encodes as controller(userdata=00.00.00.1d.00.00.00.00.80.01.08.08.00.00.00.08.c0.a8.01.01.ac.10.01.01,pause) + +reg9[[7..8]] = dhcp_relay_resp_chk(192.168.1.1, 172.16.1.1); + Cannot use 2-bit field reg9[[7..8]] where 1-bit field is required. + +reg9[[8]] = dhcp_relay_resp_chk("192.168.1.1", "172.16.1.1"); + Syntax error at `"192.168.1.1"' expecting IPv4 dhcp relay and server ips. + +reg9[[8]] = dhcp_relay_resp_chk(192.168.1, 172.16.1.1); + Invalid numeric constant. + # nd_ns nd_ns { nd.target = xxreg0; output; }; encodes as controller(userdata=00.00.00.09.00.00.00.00.00.1c.00.18.00.80.00.00.00.00.00.00.00.01.de.10.80.00.3e.10.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.OFTABLE_SAVE_INPORT_HEX.00.00.00,pause) diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index ee086a7ae..0103253e1 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -2329,6 +2329,63 @@ execute_put_dhcp_opts(const struct ovnact_put_opts *pdo, execute_put_opts(pdo, name, uflow, super); } +static void +execute_dhcpv4_relay_req_chk(const struct ovnact_dhcp_relay *dr, + struct flow *uflow, struct ovs_list *super) +{ + ovntrace_node_append( + super, OVNTRACE_NODE_ERROR, + "/* We assume that this packet is DHCPDISCOVER or DHCPREQUEST. */"); + + struct ds s = DS_EMPTY_INITIALIZER; + struct mf_subfield dst = expr_resolve_field(&dr->dst); + if (!mf_is_register(dst.field->id)) { + /* Format assignment. */ + ds_clear(&s); + expr_field_format(&dr->dst, &s); + ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, + "%s = 1", ds_cstr(&s)); + } + ds_destroy(&s); + + struct mf_subfield sf = expr_resolve_field(&dr->dst); + union mf_subvalue sv = { .u8_val = 1 }; + mf_write_subfield_flow(&sf, &sv, uflow); +} + +static void +execute_dhcpv4_relay_resp_chk(const struct ovnact_dhcp_relay *dr, + struct flow *uflow, struct ovs_list *super) +{ + ovntrace_node_append( + super, OVNTRACE_NODE_ERROR, + "/* We assume that this packet is DHCPOFFER or DHCPACK and " + "DHCP broadcast flag is set. Dest IP is set to broadcast. " + "Dest MAC is set to broadcast but in real network this is unicast " + "which is extracted from DHCP header. */"); + + /* Assume DHCP broadcast flag is set */ + uflow->nw_dst = htonl(0xFFFFFFFF); + /* Dest MAC is set to broadcast but in real network this is unicast */ + struct eth_addr bcast_mac = { .ea = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + uflow->dl_dst = bcast_mac; + + struct ds s = DS_EMPTY_INITIALIZER; + struct mf_subfield dst = expr_resolve_field(&dr->dst); + if (!mf_is_register(dst.field->id)) { + /* Format assignment. */ + ds_clear(&s); + expr_field_format(&dr->dst, &s); + ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, + "%s = 1", ds_cstr(&s)); + } + ds_destroy(&s); + + struct mf_subfield sf = expr_resolve_field(&dr->dst); + union mf_subvalue sv = { .u8_val = 1 }; + mf_write_subfield_flow(&sf, &sv, uflow); +} + static void execute_put_nd_ra_opts(const struct ovnact_put_opts *pdo, const char *name, struct flow *uflow, @@ -3215,6 +3272,16 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, "put_dhcpv6_opts", uflow, super); break; + case OVNACT_DHCPV4_RELAY_REQ_CHK: + execute_dhcpv4_relay_req_chk(ovnact_get_DHCPV4_RELAY_REQ_CHK(a), + uflow, super); + break; + + case OVNACT_DHCPV4_RELAY_RESP_CHK: + execute_dhcpv4_relay_resp_chk(ovnact_get_DHCPV4_RELAY_RESP_CHK(a), + uflow, super); + break; + case OVNACT_PUT_ND_RA_OPTS: execute_put_nd_ra_opts(ovnact_get_PUT_DHCPV6_OPTS(a), "put_nd_ra_opts", uflow, super); From patchwork Wed Apr 24 09:56:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naveen Yerramneni X-Patchwork-Id: 1927082 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=QkGca65r; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=NXLJJ933; dkim-atps=neutral Authentication-Results: legolas.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=patchwork.ozlabs.org) 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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VPZCG06nrz1yZr for ; Wed, 24 Apr 2024 19:56:58 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 1A5B040825; Wed, 24 Apr 2024 09:56:56 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id cnhjIOTAImqS; Wed, 24 Apr 2024 09:56:52 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 90ED440791 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=QkGca65r; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=NXLJJ933 Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 90ED440791; Wed, 24 Apr 2024 09:56:52 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 6C817C0077; Wed, 24 Apr 2024 09:56:52 +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 6F675C0037 for ; Wed, 24 Apr 2024 09:56:51 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id CA57F60BA8 for ; Wed, 24 Apr 2024 09:56:42 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 2ue0gUbu9og8 for ; Wed, 24 Apr 2024 09:56:41 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=148.163.155.12; helo=mx0b-002c1b01.pphosted.com; envelope-from=naveen.yerramneni@nutanix.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp3.osuosl.org D1E3D60B2C Authentication-Results: smtp3.osuosl.org; dmarc=pass (p=none dis=none) header.from=nutanix.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org D1E3D60B2C Authentication-Results: smtp3.osuosl.org; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=QkGca65r; dkim=pass (2048-bit key, unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=NXLJJ933 Received: from mx0b-002c1b01.pphosted.com (mx0b-002c1b01.pphosted.com [148.163.155.12]) by smtp3.osuosl.org (Postfix) with ESMTPS id D1E3D60B2C for ; Wed, 24 Apr 2024 09:56:40 +0000 (UTC) Received: from pps.filterd (m0127844.ppops.net [127.0.0.1]) by mx0b-002c1b01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 43O0S6NB031071; Wed, 24 Apr 2024 02:56:39 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :content-transfer-encoding:content-type:mime-version; s= proofpoint20171006; bh=W/pxnzopXuNQrhNqfn8PFntFvb8fUxj7Brq2M6Hy9 fc=; b=QkGca65r3njrVTZsiCphyWx2gn3ducTgCbMCQtSAyl/7pGGIyX+I3DKXk /r/yUTKu2Boip56/p4pdH/4zZEPj8xlaPvoaMxdVLtYl03R1DHcBj/r7XLI9aHxt /Qkt0+xNkqo6jhHGIVeXMUNFx81JQIehleYN9pgtJZb9oKwvgsDCeP4f9xjlIEW8 G5gUO+NyzWne+5cSQN+NKdYct9jYLrxfhdBePBrAv58T2wLkHzaZq+R/dYDw/dqm H9zHEfX3buD/zl92G1PzgU5rbQzmHpuc4JnThK5CW228N0y08ZCpFqJWbMd2ytYC rDtBQ1faLrPAyDobLM/XgWlMMgtQg== Received: from nam02-dm3-obe.outbound.protection.outlook.com (mail-dm3nam02lp2041.outbound.protection.outlook.com [104.47.56.41]) by mx0b-002c1b01.pphosted.com (PPS) with ESMTPS id 3xmd7yfsuc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 24 Apr 2024 02:56:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KwNWcynjk+rwQNudoueUK/VzB1pewcfK5vMVmtW9+fhDdvhKeNH9kWlDYBsN/y5K+of1AKlOT2A7CFi8ZEYQ2KknVRqkwFW/4bgYMiPf9WeU5N1chExtX3rN4CsKO4SQ8q2l/ME1/YT8hW+JNRsKR6tq/ptmoCW0Pk7soad78x3vZTdW0b3eIJTBfeVnrbVKYfKW+FIk7nWlmH1bXM8IrCFP7EEHwhm5l860/Ud7fjYqGJjIUIuM3DqaJm9wigfh2LOXb4y++DnK1hyLfWY623CE0aD7DHrdCoaPM34k/nlUZtCWVWMUaKsOuvTE1tj2D+01ZS7qgis0hRkBEs4omQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=W/pxnzopXuNQrhNqfn8PFntFvb8fUxj7Brq2M6Hy9fc=; b=FOHH3qPDi2/PwQrsvQk6/oXOYIy30onP5F2gB+PWk3mUomVfqwfl59aBk0RaDULVyZA69WtEF0uU8z+OVMpK2l7BOoFCpEwuyLv5u+/f9PMnrlVCc224THvRQRP68Nfcd9elTob/+HjO2W90B1/q6E5w7UjyYm4hXCBmSFoL/vEPp5kPJX63opM5AFg7b4eJYl5x8kB/TKhrKRYPhKPrPH5J0Sb5Q5IyeJRPKY+quNqHtRnQ0oPCt1w5QiA3hFnkl+uoafjScU7d0dSbJ5JH8lE9ihzWfRz42uwvITITAUwKxkNkwI1zJilRdc8lGbZcqb5M06YHuQ0/VXL4CPTluw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nutanix.com; dmarc=pass action=none header.from=nutanix.com; dkim=pass header.d=nutanix.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=W/pxnzopXuNQrhNqfn8PFntFvb8fUxj7Brq2M6Hy9fc=; b=NXLJJ933KrOD4FRMLkolhR+d8oCGxyCjMPaCk7CdQkFY6i1zNemU4OR8ucwCv5wtLBWrPQQKdVbK+TAieHsDYWZtxOZ4Z5muO34NOKmkxmSeLaxFMd/2qEgXNh+ih0NOIUjpkhr5ZrdIIYySy8xvEOkIX+iHVxVovMCkoINv+aZUo/UcGo1bKf+5unf7ziuIXvnvXwiCBBw1QEB0x1kKlcxjwBK1YwYzYpGFCNR2mHxfTlEjrObQjxSTVzXWom61c/Nnq8MWtygJunSFgLFnzIJGMLMOGZ0UET9GBg30Y6L0clkgnHAM/bQJdzwZ53LzX8plfW9nmEN1w6qaJwf3Tg== Received: from SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) by SJ0PR02MB7453.namprd02.prod.outlook.com (2603:10b6:a03:29b::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7519.23; Wed, 24 Apr 2024 09:56:37 +0000 Received: from SJ0PR02MB7808.namprd02.prod.outlook.com ([fe80::d95e:4ad8:aa24:7c4]) by SJ0PR02MB7808.namprd02.prod.outlook.com ([fe80::d95e:4ad8:aa24:7c4%3]) with mapi id 15.20.7519.021; Wed, 24 Apr 2024 09:56:37 +0000 From: Naveen Yerramneni To: dev@openvswitch.org Date: Wed, 24 Apr 2024 09:56:06 +0000 Message-Id: <20240424095607.129155-3-naveen.yerramneni@nutanix.com> X-Mailer: git-send-email 2.36.6 In-Reply-To: <20240424095607.129155-1-naveen.yerramneni@nutanix.com> References: <20240424095607.129155-1-naveen.yerramneni@nutanix.com> X-ClientProxiedBy: PH8PR21CA0001.namprd21.prod.outlook.com (2603:10b6:510:2ce::25) To SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR02MB7808:EE_|SJ0PR02MB7453:EE_ X-MS-Office365-Filtering-Correlation-Id: 589697dc-995f-49ed-7c69-08dc6444d4bf x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230031|366007|52116005|376005|1800799015|38350700005; X-Microsoft-Antispam-Message-Info: FxcrZf6O/y1kP41ZpiU1YpLEIWGF/QfYcG8LsUl6uplJlNt3AnXbPcL5qdXGz6J2FKvlQ/vY6FdvmCU98ovAZp2PrYmu3XHPx+UvfGUT4KROjA7nNvHpQ69Sq3oQJFXXOZvXaV+9CavAGlSCAj7LiVH3cNrxNgJ0VH5MyAV+6Cb86A01ys6ENGLRHiFCxKghQBvOn1oqhp+mA7tpFIpyD7Zx0Xodmwfhu92j9x4nV6zX4Az7+r2XN+se0NvEHKRo7eYQEt+lHH/M/PPVzy952toXkKnN43/lWYpQbztFeoS96WQYTDge8O9dJBay/oNXmdyv9IDL5nrnocG/j+LTkmG43mzUgkJgpVyhYYNRNsDPyzi/lxr4SGrOb90qCH1V53COq0i4VlAVuV2Dv36/8R00DjFd6Mpm9eyXq+orGJh9i29jxKi3SjVVkUKtHb8FlxAKyuArrA/KmePZBzuwZYwe/T0Y4MQOqgnedUIqx7BtQ2oQPM81dyqaJ46rx59upDxku/YNtkojolNUq9gbtq7tFkGo0JsvbqxsXEJV0LPExVpL1SeiwkidPw31DXk2WoxfswQzTWsm0tCSxlu4015Y4WfpZzkeMD8Tz6BsH2vnMzhc++hJ16Vmg8tOn23X8YmY4Kj+sEGYX84nnnb+9xDwF654RjTdrzY2dUYzrQ8VTC+cUNA4dDhM0kjZGd7881VX82/9/UVWdarLdDFPbD7qPKU/6K3Fl/j21I6930bR/KCn82qRKryRGrTWubKzPJuqMWd4ikmDAHJRBqgMyETOQteeCLvDjUbCwzbE0yqYf5I47hKpLqMgezjYBeqabPvt5+v+sj81MkdwaapveIg1q+QIReNMgbX0g2LEK8ZfOyrCaGJrQIw6I3sHCLsMdKTZeaUBal6TntJtnxSGnMu4ryGhKtR5VNPQTIH0ZfVUrXt4MJ9E5WwkTBUgLUeyC9fyUeI9tstSdBb5+KpOZ3Xn2/VETPbipfJpQqRCbSFiOQpt0z8kwZw1P3qk5BKCwx3WFMcROKMR/49b+BrizgrOp3HTNrgbfQjM94WNUbe7HpxhqiH0hQwlj08f40pYlXHW449V1PNgokL2Colc3f8tlpLk7WWbsnVTJ/bcQ/lnmwHa/Ldht7n9q2B7fRm+pmIZ7nW8fwiqiFF0H3DmSxyPWUExffezaC1JGg5+8xg+VZF075qoj33KeWW8QH92A0WucC+WJSkFZ5thfRnat9RwN0VcnDISSTSslbLw7W9CRlKbwW/gKorebpTOb2PI6z06RJw7+fFdTs9VpZxQu0eaZ66kcXxCe3rzYxqo1R5htIOBbjCIVkKX9dZMvcqqOO1KDapHoNSiOMs3G0T2Vg== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SJ0PR02MB7808.namprd02.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(366007)(52116005)(376005)(1800799015)(38350700005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: h76f5dHzUP86pjfMMSIga3RQ9Zr3ynQctLB1rFpN84+EIPDCamZ+do/NFR3ua8phkOpQVXqroP7ChCmCzw3EHbATUcRN3vw0HFbz4FwbhBw12H4K6zL7RQ9f8zfXQjhIZvyO7Zm+mCKYpCKiE8eCq8fGIaKOyHN2DHQZThJcP0wTxGt0yuNP7Hu+kVtj9OdHqLRnBQAYQD38ox9msKoaGnGsQ+F2H0EkIlw5NFRjbQ1yrqTt2m1sRTXDO8gRtW1aZlYwOGsZaWyiXZQFyV2bp4xGD6VAs5rcDaJyeL32pNI1+WQfLS3zpt3SebSpIeJIHHk0XJxWyp3cViG+N0DdFcZnpdnBj/I3uTqBiSRUmBd0B/M8pD8dAcC1PEHBMWUJJEHDixJHYm1Lat2RcKWA/E0WrpSgnu3xRhC9KVTxxHCciaQ9MkZhozR22fq+exNqF4fq+hcCcCcDt6Q9s+k1RkQHdXf+1kYUtFh/PeFYR4KyXJeqo2bULNc3JXq/AqWwVu/e9RXGSMkAbpMwUkOYVlTxukPi/UiKe8pmR6V4LEwt9uQsdKLM2VsFnRcg0v+LheCt2JVLp2ALsrnRqnzX/d6pdFiUsTGkWeUmUbze552W3sdyCb1364kDeEaMEEMOntXJvNcnIKs2TCBZmubfvqnxKuisc6ftx6y159hxlSyVtCQt29Pev37yZk365dKYuPva7x9rlNuh96o8sGBZu4IoDKSNoShI6qxw3TbmRDcvxwDBgYTcH45bDM9o1WZEh8ekRM0NHfF95ecsddwsaf6B/rMOTkkhp0dUybaX2PXz4VBrfIR5bE1egI1cxMA+BfUUt6M6+Y15jzZcepQ1XWR114hYRw7Ny2X2pc4R5pnKxIQjYjk1TyHdUr7N0TnuN7eSoi48ob0tUr0VGWWERZp4D1cLvkBOfPR+UF7xtfSqSHJduBg3f8b3qbhUbJ+cP+wa8fYvRdCLd1h6P9kvwLghk0SdSNO3IcVTAXAht0eropZHmr3pGQcL5NEI1H+ZEEfzJHNaMOvdFPhGt6Pwp+Dd7yAmYzKYjsvuf/ga9VFCnVkUBwA37sKa4MQMYX94/+n8hrz6l3ZQFeKN438CwPyIFdpxpHpOpV71U8rN1E8saiUWcvSnxbAFpxA602x8TzE1jg7JlvBko+hhNveeSBaYdyUiS1CaRbEB9iIXIItlcJ1JR6fgKz4pVSwXV+0D4MfJ0UhKqy9Xq2I1I/vZyjufeQMY2OYBQPoUzeYRbBJ8aQByOE7fzuvMvh/7929QKAHserGalUZelV26h8xt6+S/18MMgatAyaeHOSh+GlhkG7AY8SzHynYHF5Q28781es9OMm3QbR5Cxkgy+Asu/nvSEQZ+jUqevYUVg+av21lrScAnIeh4OPjRK8wcQjaoBQaLaHiXYh2JPjgNjxqOG4jI20geEJxuP0lqqJO9ZDkYyLUa6biyhy8c3yY3b8vuKsqufE7jIHe5fuYEumWKz232wQId3ImPs18NSQuS7SMoCHwXmWBZsCFveg1v9o3kZVF+v/IlheFNySPK/eEMhdeD57/dQ/PQzAzkBt9nc1fFDZ601EQ6wQLcBEA7rTXVkLo5FDuOujMqLMaLprMC/TtIft0oTGnKuvOp7zXxLS8= X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 589697dc-995f-49ed-7c69-08dc6444d4bf X-MS-Exchange-CrossTenant-AuthSource: SJ0PR02MB7808.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Apr 2024 09:56:37.1093 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: qNAA/Que7bTTV+gCWZsnalqNFn2qlUfXjruNsyvKFgYrK+Kn/DPbwo+7KFY6hIfLnuE5Aoo3aFJLtQyK7IYkmKS7ipLXbDj/12dZMzUl6s8= X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR02MB7453 X-Proofpoint-GUID: Rp-COrbJbigd0sF2B2FDvQDY2tSqC6jC X-Proofpoint-ORIG-GUID: Rp-COrbJbigd0sF2B2FDvQDY2tSqC6jC X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.650,FMLib:17.11.176.26 definitions=2024-04-24_07,2024-04-23_02,2023-05-22_02 X-Proofpoint-Spam-Reason: safe Cc: huzaifa.c@nutanix.com Subject: [ovs-dev] [PATCH OVN v6 2/3] controller: DHCP Relay Agent support for overlay IPv4 subnets. 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" Added changes in pinctrl to process DHCP Relay opcodes: - ACTION_OPCODE_DHCP_RELAY_REQ_CHK: For request packets - ACTION_OPCODE_DHCP_RELAY_RESP_CHK: For response packet Signed-off-by: Naveen Yerramneni --- controller/pinctrl.c | 597 ++++++++++++++++++++++++++++++++++++++----- lib/ovn-l7.h | 2 + 2 files changed, 530 insertions(+), 69 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index aa73facbf..50e090cd2 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -1993,6 +1993,515 @@ is_dhcp_flags_broadcast(ovs_be16 flags) return flags & htons(DHCP_BROADCAST_FLAG); } +static const char *dhcp_msg_str[] = { + [0] = "INVALID", + [DHCP_MSG_DISCOVER] = "DISCOVER", + [DHCP_MSG_OFFER] = "OFFER", + [DHCP_MSG_REQUEST] = "REQUEST", + [OVN_DHCP_MSG_DECLINE] = "DECLINE", + [DHCP_MSG_ACK] = "ACK", + [DHCP_MSG_NAK] = "NAK", + [OVN_DHCP_MSG_RELEASE] = "RELEASE", + [OVN_DHCP_MSG_INFORM] = "INFORM" +}; + +static bool +dhcp_relay_is_msg_type_supported(uint8_t msg_type) +{ + return (msg_type >= DHCP_MSG_DISCOVER && msg_type <= OVN_DHCP_MSG_RELEASE); +} + +static const char *dhcp_msg_str_get(uint8_t msg_type) +{ + if (!dhcp_relay_is_msg_type_supported(msg_type)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "Unknown DHCP msg type: %u", msg_type); + return "UNKNOWN"; + } + return dhcp_msg_str[msg_type]; +} + +static const struct dhcp_header * +dhcp_get_hdr_from_pkt(struct dp_packet *pkt_in, const char **in_dhcp_pptr, + const char *end) +{ + /* Validate the DHCP request packet. + * Format of the DHCP packet is + * ----------------------------------------------------------------------- + *| UDP HEADER | DHCP HEADER | 4 Byte DHCP Cookie | DHCP OPTIONS(var len) | + * ----------------------------------------------------------------------- + */ + + *in_dhcp_pptr = dp_packet_get_udp_payload(pkt_in); + if (*in_dhcp_pptr == NULL) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP: Invalid or incomplete DHCP packet received"); + return NULL; + } + + const struct dhcp_header *dhcp_hdr + = (const struct dhcp_header *) *in_dhcp_pptr; + (*in_dhcp_pptr) += sizeof *dhcp_hdr; + if (*in_dhcp_pptr > end) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP: Invalid or incomplete DHCP packet received, " + "bad data length"); + return NULL; + } + + if (dhcp_hdr->htype != 0x1) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP: Packet is recieved with " + "unsupported hardware type"); + return NULL; + } + + if (dhcp_hdr->hlen != 0x6) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP: Packet is recieved with " + "unsupported hardware length"); + return NULL; + } + + /* DHCP options follow the DHCP header. The first 4 bytes of the DHCP + * options is the DHCP magic cookie followed by the actual DHCP options. + */ + ovs_be32 magic_cookie = htonl(DHCP_MAGIC_COOKIE); + if ((*in_dhcp_pptr) + sizeof magic_cookie > end || + get_unaligned_be32((const void *) (*in_dhcp_pptr)) != magic_cookie) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP: Magic cookie not present in the DHCP packet"); + return NULL; + } + + (*in_dhcp_pptr) += sizeof magic_cookie; + + return dhcp_hdr; +} + +static void +dhcp_parse_options(const char **in_dhcp_pptr, const char *end, + const uint8_t **dhcp_msg_type_pptr, + ovs_be32 *request_ip_ptr, + bool *ipxe_req_ptr, ovs_be32 *server_id_ptr, + ovs_be32 *netmask_ptr, ovs_be32 *router_ip_ptr) +{ + while ((*in_dhcp_pptr) < end) { + const struct dhcp_opt_header *in_dhcp_opt = + (const struct dhcp_opt_header *) *in_dhcp_pptr; + if (in_dhcp_opt->code == DHCP_OPT_END) { + break; + } + if (in_dhcp_opt->code == DHCP_OPT_PAD) { + (*in_dhcp_pptr) += 1; + continue; + } + (*in_dhcp_pptr) += sizeof *in_dhcp_opt; + if ((*in_dhcp_pptr) > end) { + break; + } + (*in_dhcp_pptr) += in_dhcp_opt->len; + if ((*in_dhcp_pptr) > end) { + break; + } + + switch (in_dhcp_opt->code) { + case DHCP_OPT_MSG_TYPE: + if (dhcp_msg_type_pptr && in_dhcp_opt->len == 1) { + *dhcp_msg_type_pptr = DHCP_OPT_PAYLOAD(in_dhcp_opt); + } + break; + case DHCP_OPT_REQ_IP: + if (request_ip_ptr && in_dhcp_opt->len == 4) { + *request_ip_ptr = get_unaligned_be32( + DHCP_OPT_PAYLOAD(in_dhcp_opt)); + } + break; + case OVN_DHCP_OPT_CODE_SERVER_ID: + if (server_id_ptr && in_dhcp_opt->len == 4) { + *server_id_ptr = get_unaligned_be32( + DHCP_OPT_PAYLOAD(in_dhcp_opt)); + } + break; + case OVN_DHCP_OPT_CODE_NETMASK: + if (netmask_ptr && in_dhcp_opt->len == 4) { + *netmask_ptr = get_unaligned_be32( + DHCP_OPT_PAYLOAD(in_dhcp_opt)); + } + break; + case OVN_DHCP_OPT_CODE_ROUTER_IP: + if (router_ip_ptr && in_dhcp_opt->len == 4) { + *router_ip_ptr = get_unaligned_be32( + DHCP_OPT_PAYLOAD(in_dhcp_opt)); + } + break; + case DHCP_OPT_ETHERBOOT: + if (ipxe_req_ptr) { + *ipxe_req_ptr = true; + } + break; + default: + break; + } + } +} + +/* Called with in the pinctrl_handler thread context. */ +static void +pinctrl_handle_dhcp_relay_req_chk( + struct rconn *swconn, + struct dp_packet *pkt_in, struct ofputil_packet_in *pin, + struct ofpbuf *userdata, + struct ofpbuf *continuation) +{ + enum ofp_version version = rconn_get_version(swconn); + enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); + struct dp_packet *pkt_out_ptr = NULL; + uint32_t success = 0; + + /* Parse result field. */ + const struct mf_field *f; + enum ofperr ofperr = nx_pull_header(userdata, NULL, &f, NULL); + if (ofperr) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_REQ_CHK: bad result OXM (%s)", + ofperr_to_string(ofperr)); + goto exit; + } + ovs_be32 *ofsp = ofpbuf_try_pull(userdata, sizeof *ofsp); + /* Check that the result is valid and writable. */ + struct mf_subfield dst = { .field = f, .ofs = ntohl(*ofsp), .n_bits = 1 }; + ofperr = mf_check_dst(&dst, NULL); + if (ofperr) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_REQ_CHK: bad result bit (%s)", + ofperr_to_string(ofperr)); + goto exit; + } + + /* Parse relay IP and server IP. */ + ovs_be32 *relay_ip = ofpbuf_try_pull(userdata, sizeof *relay_ip); + ovs_be32 *server_ip = ofpbuf_try_pull(userdata, sizeof *server_ip); + if (!relay_ip || !server_ip) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_REQ_CHK: relay ip or server ip " + "not present in the userdata"); + goto exit; + } + + size_t in_l4_size = dp_packet_l4_size(pkt_in); + const char *end = (char *) dp_packet_l4(pkt_in) + in_l4_size; + const char *in_dhcp_ptr = NULL; + const struct dhcp_header *in_dhcp_data + = dhcp_get_hdr_from_pkt(pkt_in, &in_dhcp_ptr, end); + + if (!in_dhcp_data) { + goto exit; + } + ovs_assert(in_dhcp_ptr); + + if (in_dhcp_data->op != DHCP_OP_REQUEST) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_REQ_CHK: invalid opcode in the " + "DHCP packet: %d", in_dhcp_data->op); + goto exit; + } + + if (in_dhcp_data->giaddr) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_REQ_CHK: giaddr is already set"); + goto exit; + } + + const uint8_t *in_dhcp_msg_type = NULL; + ovs_be32 request_ip = in_dhcp_data->ciaddr; + + dhcp_parse_options(&in_dhcp_ptr, end, + &in_dhcp_msg_type, &request_ip, NULL, NULL, NULL, NULL); + + /* Check whether the DHCP Message Type (opt 53) is present or not */ + if (!in_dhcp_msg_type) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_REQ_CHK: missing message type"); + goto exit; + } + + /* Relay the DHCP request packet */ + uint16_t new_l4_size = in_l4_size; + size_t new_packet_size = pkt_in->l4_ofs + new_l4_size; + + struct dp_packet pkt_out; + dp_packet_init(&pkt_out, new_packet_size); + dp_packet_clear(&pkt_out); + dp_packet_prealloc_tailroom(&pkt_out, new_packet_size); + pkt_out_ptr = &pkt_out; + + /* Copy the L2 and L3 headers from the pkt_in as they would remain same*/ + dp_packet_put( + &pkt_out, dp_packet_pull(pkt_in, pkt_in->l4_ofs), pkt_in->l4_ofs); + + pkt_out.l2_5_ofs = pkt_in->l2_5_ofs; + pkt_out.l2_pad_size = pkt_in->l2_pad_size; + pkt_out.l3_ofs = pkt_in->l3_ofs; + pkt_out.l4_ofs = pkt_in->l4_ofs; + + struct udp_header *udp = dp_packet_put( + &pkt_out, dp_packet_pull(pkt_in, UDP_HEADER_LEN), UDP_HEADER_LEN); + + struct dhcp_header *dhcp_data = dp_packet_put(&pkt_out, + dp_packet_pull(pkt_in, new_l4_size - UDP_HEADER_LEN), + new_l4_size - UDP_HEADER_LEN); + + uint8_t hops = dhcp_data->hops + 1; + if (udp->udp_csum) { + udp->udp_csum = recalc_csum16(udp->udp_csum, + htons((uint16_t) dhcp_data->hops), htons((uint16_t) hops)); + } + dhcp_data->hops = hops; + + dhcp_data->giaddr = *relay_ip; + if (udp->udp_csum) { + udp->udp_csum = recalc_csum32(udp->udp_csum, + 0, dhcp_data->giaddr); + } + pin->packet = dp_packet_data(&pkt_out); + pin->packet_len = dp_packet_size(&pkt_out); + + /* Log the DHCP message. */ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(20, 40); + VLOG_INFO_RL(&rl, "DHCP_RELAY_REQ_CHK:: MSG_TYPE:%s MAC:"ETH_ADDR_FMT + " XID:%u" + " REQ_IP:"IP_FMT + " GIADDR:"IP_FMT + " SERVER_ADDR:"IP_FMT, + dhcp_msg_str_get(*in_dhcp_msg_type), + ETH_ADDR_BYTES_ARGS(dhcp_data->chaddr), ntohl(dhcp_data->xid), + IP_ARGS(request_ip), IP_ARGS(dhcp_data->giaddr), + IP_ARGS(*server_ip)); + success = 1; +exit: + if (!ofperr) { + union mf_subvalue sv; + sv.u8_val = success; + mf_write_subfield(&dst, &sv, &pin->flow_metadata); + } + queue_msg(swconn, ofputil_encode_resume(pin, continuation, proto)); + if (pkt_out_ptr) { + dp_packet_uninit(pkt_out_ptr); + } +} + +/* Called with in the pinctrl_handler thread context. */ +static void +pinctrl_handle_dhcp_relay_resp_chk( + struct rconn *swconn, + struct dp_packet *pkt_in, struct ofputil_packet_in *pin, + struct ofpbuf *userdata, + struct ofpbuf *continuation) +{ + enum ofp_version version = rconn_get_version(swconn); + enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); + struct dp_packet *pkt_out_ptr = NULL; + uint32_t success = 0; + + /* Parse result field. */ + const struct mf_field *f; + enum ofperr ofperr = nx_pull_header(userdata, NULL, &f, NULL); + if (ofperr) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP_CHK: bad result OXM (%s)", + ofperr_to_string(ofperr)); + goto exit; + } + ovs_be32 *ofsp = ofpbuf_try_pull(userdata, sizeof *ofsp); + /* Check that the result is valid and writable. */ + struct mf_subfield dst = { .field = f, .ofs = ntohl(*ofsp), .n_bits = 1 }; + ofperr = mf_check_dst(&dst, NULL); + if (ofperr) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP_CHK: bad result bit (%s)", + ofperr_to_string(ofperr)); + goto exit; + } + + /* Parse relay IP and server IP. */ + ovs_be32 *relay_ip = ofpbuf_try_pull(userdata, sizeof *relay_ip); + ovs_be32 *server_ip = ofpbuf_try_pull(userdata, sizeof *server_ip); + if (!relay_ip || !server_ip) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP_CHK: relay ip or server ip " + "not present in the userdata"); + goto exit; + } + + size_t in_l4_size = dp_packet_l4_size(pkt_in); + const char *end = (char *) dp_packet_l4(pkt_in) + in_l4_size; + const char *in_dhcp_ptr = NULL; + const struct dhcp_header *in_dhcp_data + = dhcp_get_hdr_from_pkt(pkt_in, &in_dhcp_ptr, end); + + if (!in_dhcp_data) { + goto exit; + } + ovs_assert(in_dhcp_ptr); + + if (in_dhcp_data->op != DHCP_OP_REPLY) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP_CHK: invalid opcode " + "in the packet: %d", in_dhcp_data->op); + goto exit; + } + + if (!in_dhcp_data->giaddr) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP_CHK: giaddr is " + "not set in request"); + goto exit; + } + + ovs_be32 giaddr = in_dhcp_data->giaddr; + ovs_be32 yiaddr = in_dhcp_data->yiaddr; + ovs_be32 server_id = 0, netmask = 0, router_ip = 0; + const uint8_t *in_dhcp_msg_type = NULL; + + dhcp_parse_options(&in_dhcp_ptr, end, + &in_dhcp_msg_type, NULL, NULL, &server_id, &netmask, &router_ip); + + /* Check whether the DHCP Message Type (opt 53) is present or not */ + if (!in_dhcp_msg_type) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP: missing message type"); + goto exit; + } + + if (!server_id) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP: missing server identifier"); + goto exit; + } + + if (server_id != *server_ip) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP: server identifier mismatch"); + goto exit; + } + + if (giaddr != *relay_ip) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "DHCP_RELAY_RESP: giaddr mismatch"); + goto exit; + } + + if (*in_dhcp_msg_type == DHCP_MSG_OFFER || + *in_dhcp_msg_type == DHCP_MSG_ACK) { + if ((yiaddr & netmask) != (giaddr & netmask)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_INFO_RL(&rl, "DHCP_RELAY_RESP_CHK:: Allocated ip adress and" + " giaddr are not in same subnet." + " MSG_TYPE:%s MAC:"ETH_ADDR_FMT + " XID:%u" + " YIADDR:"IP_FMT + " GIADDR:"IP_FMT + " SERVER_ADDR:"IP_FMT, + dhcp_msg_str_get(*in_dhcp_msg_type), + ETH_ADDR_BYTES_ARGS(in_dhcp_data->chaddr), + ntohl(in_dhcp_data->xid), + IP_ARGS(yiaddr), + IP_ARGS(giaddr), IP_ARGS(server_id)); + goto exit; + } + + if (router_ip && router_ip != giaddr) { + /* Log the default gateway mismatch and + * continue with rest of the processing */ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_INFO_RL(&rl, "DHCP_RELAY_RESP_CHK::" + " Router ip adress and giaddr are not same." + " MSG_TYPE:%s MAC:"ETH_ADDR_FMT + " XID:%u" + " YIADDR:"IP_FMT + " GIADDR:"IP_FMT + " SERVER_ADDR:"IP_FMT, + dhcp_msg_str_get(*in_dhcp_msg_type), + ETH_ADDR_BYTES_ARGS(in_dhcp_data->chaddr), + ntohl(in_dhcp_data->xid), + IP_ARGS(yiaddr), + IP_ARGS(giaddr), IP_ARGS(server_id)); + } + } + + /* Update destination MAC & IP so that the packet is forward to the + * right destination node. + */ + uint16_t new_l4_size = in_l4_size; + size_t new_packet_size = pkt_in->l4_ofs + new_l4_size; + + struct dp_packet pkt_out; + dp_packet_init(&pkt_out, new_packet_size); + dp_packet_clear(&pkt_out); + dp_packet_prealloc_tailroom(&pkt_out, new_packet_size); + pkt_out_ptr = &pkt_out; + + /* Copy the L2 and L3 headers from the pkt_in as they would remain same*/ + struct eth_header *eth = dp_packet_put( + &pkt_out, dp_packet_pull(pkt_in, pkt_in->l4_ofs), pkt_in->l4_ofs); + + pkt_out.l2_5_ofs = pkt_in->l2_5_ofs; + pkt_out.l2_pad_size = pkt_in->l2_pad_size; + pkt_out.l3_ofs = pkt_in->l3_ofs; + pkt_out.l4_ofs = pkt_in->l4_ofs; + + struct udp_header *udp = dp_packet_put( + &pkt_out, dp_packet_pull(pkt_in, UDP_HEADER_LEN), UDP_HEADER_LEN); + + struct dhcp_header *dhcp_data = dp_packet_put( + &pkt_out, dp_packet_pull(pkt_in, new_l4_size - UDP_HEADER_LEN), + new_l4_size - UDP_HEADER_LEN); + memcpy(ð->eth_dst, dhcp_data->chaddr, sizeof(eth->eth_dst)); + + /* Send a broadcast IP frame when BROADCAST flag is set. */ + struct ip_header *out_ip = dp_packet_l3(&pkt_out); + ovs_be32 ip_dst; + ovs_be32 ip_dst_orig = get_16aligned_be32(&out_ip->ip_dst); + if (!is_dhcp_flags_broadcast(dhcp_data->flags)) { + ip_dst = dhcp_data->yiaddr; + } else { + ip_dst = htonl(0xffffffff); + } + put_16aligned_be32(&out_ip->ip_dst, ip_dst); + out_ip->ip_csum = recalc_csum32(out_ip->ip_csum, + ip_dst_orig, ip_dst); + if (udp->udp_csum) { + udp->udp_csum = recalc_csum32(udp->udp_csum, + ip_dst_orig, ip_dst); + } + pin->packet = dp_packet_data(&pkt_out); + pin->packet_len = dp_packet_size(&pkt_out); + + /* Log the DHCP message. */ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(20, 40); + VLOG_INFO_RL(&rl, "DHCP_RELAY_RESP_CHK:: MSG_TYPE:%s MAC:"ETH_ADDR_FMT + " XID:%u" + " YIADDR:"IP_FMT + " GIADDR:"IP_FMT + " SERVER_ADDR:"IP_FMT, + dhcp_msg_str_get(*in_dhcp_msg_type), + ETH_ADDR_BYTES_ARGS(dhcp_data->chaddr), ntohl(dhcp_data->xid), + IP_ARGS(yiaddr), + IP_ARGS(giaddr), IP_ARGS(server_id)); + success = 1; +exit: + if (!ofperr) { + union mf_subvalue sv; + sv.u8_val = success; + mf_write_subfield(&dst, &sv, &pin->flow_metadata); + } + queue_msg(swconn, ofputil_encode_resume(pin, continuation, proto)); + if (pkt_out_ptr) { + dp_packet_uninit(pkt_out_ptr); + } +} + /* Called with in the pinctrl_handler thread context. */ static void pinctrl_handle_put_dhcp_opts( @@ -2040,30 +2549,16 @@ pinctrl_handle_put_dhcp_opts( goto exit; } - /* Validate the DHCP request packet. - * Format of the DHCP packet is - * ------------------------------------------------------------------------ - *| UDP HEADER | DHCP HEADER | 4 Byte DHCP Cookie | DHCP OPTIONS(var len)| - * ------------------------------------------------------------------------ - */ - const char *end = (char *)dp_packet_l4(pkt_in) + dp_packet_l4_size(pkt_in); - const char *in_dhcp_ptr = dp_packet_get_udp_payload(pkt_in); - if (!in_dhcp_ptr) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - VLOG_WARN_RL(&rl, "Invalid or incomplete DHCP packet received"); - goto exit; - } - + const char *in_dhcp_ptr = NULL; const struct dhcp_header *in_dhcp_data - = (const struct dhcp_header *) in_dhcp_ptr; - in_dhcp_ptr += sizeof *in_dhcp_data; - if (in_dhcp_ptr > end) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - VLOG_WARN_RL(&rl, "Invalid or incomplete DHCP packet received, " - "bad data length"); + = dhcp_get_hdr_from_pkt(pkt_in, &in_dhcp_ptr, end); + + if (!in_dhcp_data) { goto exit; } + ovs_assert(in_dhcp_ptr); + if (in_dhcp_data->op != DHCP_OP_REQUEST) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_WARN_RL(&rl, "Invalid opcode in the DHCP packet: %d", @@ -2071,58 +2566,11 @@ pinctrl_handle_put_dhcp_opts( goto exit; } - /* DHCP options follow the DHCP header. The first 4 bytes of the DHCP - * options is the DHCP magic cookie followed by the actual DHCP options. - */ - ovs_be32 magic_cookie = htonl(DHCP_MAGIC_COOKIE); - if (in_dhcp_ptr + sizeof magic_cookie > end || - get_unaligned_be32((const void *) in_dhcp_ptr) != magic_cookie) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - VLOG_WARN_RL(&rl, "DHCP magic cookie not present in the DHCP packet"); - goto exit; - } - in_dhcp_ptr += sizeof magic_cookie; - bool ipxe_req = false; const uint8_t *in_dhcp_msg_type = NULL; ovs_be32 request_ip = in_dhcp_data->ciaddr; - while (in_dhcp_ptr < end) { - const struct dhcp_opt_header *in_dhcp_opt = - (const struct dhcp_opt_header *)in_dhcp_ptr; - if (in_dhcp_opt->code == DHCP_OPT_END) { - break; - } - if (in_dhcp_opt->code == DHCP_OPT_PAD) { - in_dhcp_ptr += 1; - continue; - } - in_dhcp_ptr += sizeof *in_dhcp_opt; - if (in_dhcp_ptr > end) { - break; - } - in_dhcp_ptr += in_dhcp_opt->len; - if (in_dhcp_ptr > end) { - break; - } - - switch (in_dhcp_opt->code) { - case DHCP_OPT_MSG_TYPE: - if (in_dhcp_opt->len == 1) { - in_dhcp_msg_type = DHCP_OPT_PAYLOAD(in_dhcp_opt); - } - break; - case DHCP_OPT_REQ_IP: - if (in_dhcp_opt->len == 4) { - request_ip = get_unaligned_be32(DHCP_OPT_PAYLOAD(in_dhcp_opt)); - } - break; - case DHCP_OPT_ETHERBOOT: - ipxe_req = true; - break; - default: - break; - } - } + dhcp_parse_options(&in_dhcp_ptr, end, + &in_dhcp_msg_type, &request_ip, &ipxe_req, NULL, NULL, NULL); /* Check that the DHCP Message Type (opt 53) is present or not with * valid values - DHCP_MSG_DISCOVER or DHCP_MSG_REQUEST. @@ -2329,6 +2777,7 @@ pinctrl_handle_put_dhcp_opts( dhcp_data->yiaddr = 0; } + ovs_be32 magic_cookie = htonl(DHCP_MAGIC_COOKIE); dp_packet_put(&pkt_out, &magic_cookie, sizeof(ovs_be32)); uint16_t out_dhcp_opts_size = 12; @@ -3298,6 +3747,16 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg) ovs_mutex_unlock(&pinctrl_mutex); break; + case ACTION_OPCODE_DHCP_RELAY_REQ_CHK: + pinctrl_handle_dhcp_relay_req_chk(swconn, &packet, &pin, + &userdata, &continuation); + break; + + case ACTION_OPCODE_DHCP_RELAY_RESP_CHK: + pinctrl_handle_dhcp_relay_resp_chk(swconn, &packet, &pin, + &userdata, &continuation); + break; + case ACTION_OPCODE_PUT_DHCP_OPTS: pinctrl_handle_put_dhcp_opts(swconn, &packet, &pin, &headers, &userdata, &continuation); diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h index f4a30cc00..7f5673b12 100644 --- a/lib/ovn-l7.h +++ b/lib/ovn-l7.h @@ -68,7 +68,9 @@ struct gen_opts_map { * OVN_DHCP_OPT_CODE_. */ #define OVN_DHCP_OPT_CODE_NETMASK 1 +#define OVN_DHCP_OPT_CODE_ROUTER_IP 3 #define OVN_DHCP_OPT_CODE_LEASE_TIME 51 +#define OVN_DHCP_OPT_CODE_SERVER_ID 54 #define OVN_DHCP_OPT_CODE_T1 58 #define OVN_DHCP_OPT_CODE_T2 59 From patchwork Wed Apr 24 09:56:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naveen Yerramneni X-Patchwork-Id: 1927083 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=FvdBlWdw; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=ytxBhg4L; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VPZCZ20fgz1yZr for ; Wed, 24 Apr 2024 19:57:14 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id C1DC340838; Wed, 24 Apr 2024 09:57:11 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 9XqVgBiRIKWa; Wed, 24 Apr 2024 09:57:06 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 2E1AA4081E Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=FvdBlWdw; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=ytxBhg4L Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 2E1AA4081E; Wed, 24 Apr 2024 09:57:06 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id F1931C0077; Wed, 24 Apr 2024 09:57:05 +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 24D52C0077 for ; Wed, 24 Apr 2024 09:57:04 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id CAFF382014 for ; Wed, 24 Apr 2024 09:56:49 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id Y_tbTroyQK8N for ; Wed, 24 Apr 2024 09:56:47 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=148.163.151.68; helo=mx0a-002c1b01.pphosted.com; envelope-from=naveen.yerramneni@nutanix.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org 495BB81FAE Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=none dis=none) header.from=nutanix.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 495BB81FAE Authentication-Results: smtp1.osuosl.org; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=FvdBlWdw; dkim=pass (2048-bit key, unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=ytxBhg4L Received: from mx0a-002c1b01.pphosted.com (mx0a-002c1b01.pphosted.com [148.163.151.68]) by smtp1.osuosl.org (Postfix) with ESMTPS id 495BB81FAE for ; Wed, 24 Apr 2024 09:56:47 +0000 (UTC) Received: from pps.filterd (m0127839.ppops.net [127.0.0.1]) by mx0a-002c1b01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 43O0SNL1023417; Wed, 24 Apr 2024 02:56:46 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :content-transfer-encoding:content-type:mime-version; s= proofpoint20171006; bh=9oVb6fmA4rdKFI/Op9dJzc9c1rxFF/7x26lg3q6Np nI=; b=FvdBlWdwmdhCmvio/k3Nnsa+USE8W+xtH8qXtQM6PmYnTTE5KIMNNw1Dn k+nlCAo8A3Rk07DYWi5fzudUjEH2BeS9L5L0/n1buhvIekuhuhHKq+pSkoX0jNgk D/SlXwUkxtSmWQ5mW3mWN5EQg5wCssuL4mWpAFIwJRcjReEposTIXLqcM9nlRKpa BIAXhAcjU2ZlPQSZWgKX/JufaedhHF7IkuOUSZuWcRPeJA7Bd+L3L2uJdaKWfYkS ktYlA9msZPLpG60PIDxB6bCrTA57YNwtEBaPFvayG3UNss9K6jP6YK3flJfalGkK g4PfPzMppR8Y2XZLawETphXpcyY9Q== Received: from nam02-dm3-obe.outbound.protection.outlook.com (mail-dm3nam02lp2041.outbound.protection.outlook.com [104.47.56.41]) by mx0a-002c1b01.pphosted.com (PPS) with ESMTPS id 3xmcsdfxd7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 24 Apr 2024 02:56:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=E+2/0xo46Y7XETGTRRXiYt/A8eErt5BJX5LD45HlozVZgvLK2e/QJ+p0GI+hkNRBRkrXcXtD+ahvtHs6XlxaEtepSe0CjT5knYQFPKRruS0J3vKOX9JC6By3Xp8sZkqW7YlZC4INZFle3kW7hsJke4AMK4gCQbn54gKOc8F+Fd4faZnnCzrKxV+hBHnUBlBjkBJF7UiE1QcSXaE1QVOLNP6+6uPty4iM36dUZEHyfuxnCyqo7KLd3k/WYdKLuqpGl/R5AnHxWFTEyeD46RxvAZDfFzg1/Y1wC5eE/oMCcI89X7pZwndhUOaXIwX2b/3ru24okswAFvCKcxQzKL2NQg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=9oVb6fmA4rdKFI/Op9dJzc9c1rxFF/7x26lg3q6NpnI=; b=H6hGqF0Q21ChTXljSYJKEcoMMhCWlWMckAYwpWM9ZM2Q6Go37dbIEwhSIkFhn9juavpqza1bom6Q2pJERRjOWF3Faqqqhyue/8OpOrtqUnV4Nbb/K2kGIoe0ip/zCvBGCv95X12BHw/yzL6Nde8eCYGCya9zYCzATA+Sxvh9BKUSFDQPl9K8evXsBusS3swWpIKvvz7jOI2/8aVgGUnTKTbw+wnEPFfiYLvFFZMmrVfB4u3Y5WH1v7oKnhkeviI9/gAm40bM1SMYtA4BCbiQ4rOB3OsNgm/seuTkJSSNHLShzl6ulU46T59FnSU/qM/Xb0vn2fGjrStbG8taEtSEjw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nutanix.com; dmarc=pass action=none header.from=nutanix.com; dkim=pass header.d=nutanix.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9oVb6fmA4rdKFI/Op9dJzc9c1rxFF/7x26lg3q6NpnI=; b=ytxBhg4LFhvOcMvEjh9sRLisuUus4SbBvQ+WDHFiR1odyNgOA+reoHHzbPGDgF5xwq0Kj5vWHEkUe0vTtimfeGR0ua2Ur9flET8C8lImpglzgj1sbK7tOeWIFln7aQj81VGm28QI5QOzPkwN2NgPJ2mwXxhZNcyGP5L1JuBUxfZNW5Yk7RXCQKOM1/E8tACeXESL8n7NLBkoc7DYCs6ZNLggu9C77WCALvwf481Dmcy8/gIebLwfe2d2fuOtpFL0peArFf9Q9UTsx7HPnfOq8M51Ncc+rqSoY+2DFtEiKOz5U3vEJoKGXgBJnqhBP01nseSeCUg1f7nbNeWu6Wyb6Q== Received: from SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) by SJ0PR02MB7453.namprd02.prod.outlook.com (2603:10b6:a03:29b::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7519.23; Wed, 24 Apr 2024 09:56:43 +0000 Received: from SJ0PR02MB7808.namprd02.prod.outlook.com ([fe80::d95e:4ad8:aa24:7c4]) by SJ0PR02MB7808.namprd02.prod.outlook.com ([fe80::d95e:4ad8:aa24:7c4%3]) with mapi id 15.20.7519.021; Wed, 24 Apr 2024 09:56:43 +0000 From: Naveen Yerramneni To: dev@openvswitch.org Date: Wed, 24 Apr 2024 09:56:07 +0000 Message-Id: <20240424095607.129155-4-naveen.yerramneni@nutanix.com> X-Mailer: git-send-email 2.36.6 In-Reply-To: <20240424095607.129155-1-naveen.yerramneni@nutanix.com> References: <20240424095607.129155-1-naveen.yerramneni@nutanix.com> X-ClientProxiedBy: PH8PR21CA0001.namprd21.prod.outlook.com (2603:10b6:510:2ce::25) To SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR02MB7808:EE_|SJ0PR02MB7453:EE_ X-MS-Office365-Filtering-Correlation-Id: d6a833ee-184f-43a6-c320-08dc6444d892 x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230031|366007|52116005|376005|1800799015|38350700005; X-Microsoft-Antispam-Message-Info: C6Uex2TJF/72aNhkrDwe7aPXoY2Xpi4NL+wT18EAwtKOJmqBbJBoXLpmJIcKLggaRFlyEh39TfoNcz6wGizhFKsw/Rc5l+3NLYCM0iDxtlqE+cJujWU0WJCOvaTVRnzOy153hfGI4nRNPyEZ6FSRgPK+KNXli3AU3ldg2TUE9cz/EWIsGwp3i2BcHZPzbuYWhG52lt7hUBBXa6wIel/8AvTnA0Kj/unmpeMqimMqtgoFMWcMssotNZzOF6YMRNwUqjiCHNpFc2YfQxA1evzIQWBCgvEjvx/Z2bKk1qqtbQCx1XdA37Jj0PJCbBKXS9aMQWfen2lxYNhe5E0XM7STAGD30su2zCnpAOjJgOoMArVI5iqWohYIjalGJ3eeaXB0vSULLgMfaOHtpcSpWfIvgQa4h0fV0hBjoXIme8jgLs3yfFQCNit8FrWFgLJuarRLDySjHDJoGyugljQLfSjYlKJOH+NqvvGFwvizZCaQD1hVB6Q3GSVi7dvP2pvAFFb8wkva3eqibYzL6kdO9S0Ue4MdOGV+ohmSnRYfBMf7XoSyA75KbGudJeL6cceU9Mr66+y2deK2GA2+Sz9rwnNF3GE9YD9okQ1ucregBie/43e2ESQdAi6jKSrblfgXhaIir7TbhfpAcX0xrU1zq62nRgcmrEKtgEgNvplFL58hkuI281NY17THbrpxXhMRVXpNsj3Ze19+Jk7BNqdM+KL3wSSR3KlMDmydV6nC/kT42MjLf2FhyKD5i3TLthTZqnSE3Y6JNHXdSy2PWaE37u3eDe20eCbzaHYWhVLCGqL5S82B0qtlF3P/DCRsXEBIZkwdh2/gvwleMvvXi5T9afmrzg/EtLZ1RAjM5Xo1u/IeYnVnVK2quH0h3RkwQkEhyIvzpBLvWQultLwzREGJq+FUcqrN9vcvhp+U5G/D/PybpNtqJH9dP/AqFPoBSQcGxN4oVtfrPMc/HlNi7W0Pw9ttA5F7cViIV/Uof/7GPu1ExkFwpbMVJWaRgpVGUCc2MYolIpiliq7J629dLR+oyKpKr4d8UpJgyNa3naaxz+hlCgVloKtUJG+dDNY/90mxHjFhRJmfpq31h/RtXYyPAM9KdWl5x/db2eYCTwRars/hrZwiFjsKjohl8IuuYU67sXGOy94fbG7Yck6aej42kZB3ywo2UMlF8IlgUBA5yozZoRjVF3M+3QEbQQLHqwy33zVNsEuRjDO+tlWA+GOtCgZ/wWYvmt7rIo42jviZ337tul80a/iHcaLg9+ROUIErteMxCn9mHOzybsLtdAgXrKwLL+spW/v6FGeHySs5o2go33E0+nC89hqG12qn5TfjUvt0PE67rYZMwiIn1kH/t0XR6Q== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SJ0PR02MB7808.namprd02.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(366007)(52116005)(376005)(1800799015)(38350700005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 8l51/omvsfKX9LlA37TGxKav5BGazMqAuSW58fUAS3+Ai/bqLP1JtnfnVIspqnPdcas3vNC96HSRmy1e02zAukzIpeXArIt17AYWXTcTP2LVH70ohaNpAcWe6RCBG25SvtXJcoV+Xxiit3GbKcUrsluFTMkXXrjTi9hfjJf7JOH6BxaAvIXEb3KS+YYzeL44zLfABRP2pgS3bLv6+qfw3Sl9Rtlzp6IF2p00pDfS45/1Dl7SsF+XzHF9kLVOppwbriOb6yPddyD85c97FvWAlkCWK44S24I8qKHkKIMr61KlyYxoadzPH536ZOxjM/oaJvm+DI6p4SGLDt3JojdxO1/a1Uai9L93hSIl9s9/1B4lCDAVt/gV66l9/7AEOeWf6VHqcvcEDJYE3FaBijx33FO1VbE9j7DZihWvANzaom/V7Emry1CWnskeRwMD0RPMEsr5JjqqxyHMgz1v8D8wkcEUqw3v4rHowMWCNoWDpCi3yiIWPB2AX2WNV5gx2lCO9OJSUZ01uUqvxbMPi0A6PKsORbdMUYxRdfEEXiZ52qDSsYzVis+nuCn9WlYV/8cnC8LhJ8zWGPtsZZiczAGKQNMN0tgcIRh2+xa6qRQfj6q6gUIJtEicHriCed2ROhwen5P9AYbQ67ZM6ZMXtmcVbWk9EbfyhfuOLgvo2dzO3FVw6cHmm0Z0ZhN8RSWqmgMI6ueNtxuPau9q5LFuuB9fKGT5/fItC85tMggHz7gMbUoLLRvEMIV4bzhne/hayPojig7InhJeUVAJnslRGBvyICLSjOBH2DJ4LYnlWJCGazWBia90Waz+w2yUyaxlVSNiOuDUGZ1MPO1C95yQ1jjSAE3/MGQPLshGLf55Gh5FhMDLEK1aXpZaIXE0phfrH7V6OS3Pkd9BiN2wq8GFsGGLXMeGEfUyXBTg2KBuU5zwaTMZ1xanjmXBtTgfUjRVreWXsT6CPu5/6z29tZDl+Txs+mOUr10Ox8KcfryPaKHVEzMoxZVKBtAtUEdNP1U4jrP+TnoQjhdry1Pi5LVq+UG7AflXyd/q03nD6f+7iUrxk7zF16hGHkOTJ0NEWKPHYJVKyxUi/a87zJs90v4YZkbryVhsyS6qrSHGyaDf5cIToY7ksSF90/sddteNpCQQN2VoX8YLDulR/+/+jfsx3v5bF8JptLlU68sz4LTwBDZOL2zkYqqQpPFjaJ3y8AyE1b56ZwbhGBSd7xVGhgohilMbWnrAkG1GnSEaXVOioPq6DZvZm6QJjCPU5fiJzgJCocjVS/t1PFg9ppEcZCkzrV4rxWRGkNu2Dp8pjtqexMh3+q7hVeXjhmm73+tC2UBkmj3Dt4d7duhz3raDSwvA3tH709jVlNrNlFabt6iRVPIvq4KpXBpF6whsueWvcaNuFam0mBQCLU1My00GkTGiluNJXBPgDuRrAqX8Ef+QQNzIvlyXQNR+dpJRTm6/BM4CtWUhjHNDOEQKhorFL6ahUgQn7EDtFMX9KiN2tjMxGmxfbOLAxcB47WpFOANui/jdlLwUkLE20a+b5eKo4VxRqaEUTCvHTu421kO/sLNeI2ZD+UWcdIjpoi2+8jhbH9Zrk0V+gXNO45QIKHBzlEMpC24L8YcBp5W9akJGIsfEsvE3tMU= X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: d6a833ee-184f-43a6-c320-08dc6444d892 X-MS-Exchange-CrossTenant-AuthSource: SJ0PR02MB7808.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Apr 2024 09:56:43.6039 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: oF/aPJHI4SKU9nkiG53wFZc/F1K2JOIHYJzCm6iOFtimjCdsnchg/F1aDZ4I0KK0OIYIWj2ros55y/SZPIjRqOCK/G3ljd1icNVygag0YCo= X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR02MB7453 X-Proofpoint-ORIG-GUID: iiJ-b2p8EFDzUJfsUTSKrVC1h1ro5Hr_ X-Proofpoint-GUID: iiJ-b2p8EFDzUJfsUTSKrVC1h1ro5Hr_ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.650,FMLib:17.11.176.26 definitions=2024-04-24_07,2024-04-23_02,2023-05-22_02 X-Proofpoint-Spam-Reason: safe Cc: huzaifa.c@nutanix.com Subject: [ovs-dev] [PATCH OVN v6 3/3] northd, tests: DHCP Relay Agent support for overlay IPv4 subnets. 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" NB SCHEMA CHANGES ----------------- 1. New DHCP_Relay table "DHCP_Relay": { "columns": { "name": {"type": "string"}, "servers": {"type": {"key": "string", "min": 0, "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "options": {"type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "isRoot": true}, 2. New column to Logical_Router_Port table "dhcp_relay": {"type": {"key": {"type": "uuid", "refTable": "DHCP_Relay", "refType": "strong"}, "min": 0, "max": 1}}, NEW PIPELINE STAGES ------------------- Following stage is added for DHCP relay feature. Some of the flows are fitted into the existing pipeline tages. 1. lr_in_dhcp_relay_req - This stage process the DHCP request packets coming from DHCP clients. - DHCP request packets for which dhcp_relay_req_chk action (which gets applied in ip input stage) is successful are forwarded to DHCP server. - DHCP request packets for which dhcp_relay_req_chk action is unsuccessful gets dropped. 2. lr_in_dhcp_relay_resp_chk - This stage applied the dhcp_relay_resp_chk action for DHCP response packets coming from the DHCP server. 3. lr_in_dhcp_relay_resp - DHCP response packets for which dhcp_relay_resp_chk is sucessful are forwarded to the DHCP clients. - DHCP response packets for which dhcp_relay_resp_chk is unsucessful gets dropped. REGISTRY USAGE --------------- - reg9[7] : To store the result of dhcp_relay_req_chk action. - reg9[8] : To store the result of dhcp_relay_resp_chk action. - reg2 : To store the original dest ip for DHCP response packets. This is required to properly match the packets in lr_in_dhcp_relay_resp stage since dhcp_relay_resp_chk action changes the dest ip. FLOWS ----- Following are the flows added when DHCP Relay is configured on one overlay subnet, one additonal flow is added in ls_in_l2_lkup table for each VM part of the subnet. 1. table=27(ls_in_l2_lkup ), priority=100 , match=(inport == && eth.src == && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(eth.dst=;outport=;next;/* DHCP_RELAY_REQ */) 2. table=3 (lr_in_ip_input ), priority=110 , match=(inport == && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && ip.frag == 0 && udp.src == 68 && udp.dst == 67), action=(reg9[7] = dhcp_relay_req_chk(, );next; /* DHCP_RELAY_REQ */) 3. table=3 (lr_in_ip_input ), priority=110 , match=(ip4.src == && ip4.dst == && udp.src == 67 && udp.dst == 67), action=(next;/* DHCP_RELAY_RESP */) 4. table=4 (lr_in_dhcp_relay_req), priority=100 , match=(inport == "lrp1" && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67 && reg9[7]), action=(ip4.src=;ip4.dst=;udp.src=67;next; /* DHCP_RELAY_REQ */) 5. table=4 (lr_in_dhcp_relay_req), priority=1 , match=(inport == && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67 && reg9[7] == 0), action=(drop; /* DHCP_RELAY_REQ */) 6. table=18(lr_in_dhcp_relay_resp_chk), priority=100 , match=(ip4.src == && ip4.dst == && ip.frag == 0 && udp.src == 67 && udp.dst == 67), action=(reg2 = ip4.dst;reg9[8] = dhcp_relay_resp_chk(, );next;/* DHCP_RELAY_RESP */) 7. table=19(lr_in_dhcp_relay_resp), priority=100 , match=(ip4.src == && reg2 == && udp.src == 67 && udp.dst == 67 && reg9[8]), action=(ip4.src=;udp.dst=68;outport=;output; /* DHCP_RELAY_RESP */) 8. table=19(lr_in_dhcp_relay_resp), priority=1 , match=(ip4.src == && reg2 == && udp.src == 67 && udp.dst == 67 && reg9[8] == 0), action=(drop; /* DHCP_RELAY_RESP */) Commands to enable the feature ------------------------------ ovn-nbctl create DHCP_Relay name= servers= ovn-nbctl set Logical_Router_port dhcp_relay= ovn-nbctl set Logical_Switch other_config:dhcp_relay_port= Limitations: ------------ - All OVN features that needs IP address to be configured on logical port (like proxy arp, etc) will not be supported for overlay subnets on which DHCP relay is enabled. Signed-off-by: Naveen Yerramneni Co-authored-by: Huzaifa Calcuttawala Signed-off-by: Huzaifa Calcuttawala CC: Mary Manohar --- northd/northd.c | 271 +++++++++++++++++++++++++++++++++++++++- northd/northd.h | 41 +++--- northd/ovn-northd.8.xml | 211 +++++++++++++++++++++++++++---- ovn-nb.ovsschema | 21 +++- ovn-nb.xml | 39 ++++++ tests/atlocal.in | 3 + tests/ovn-northd.at | 38 ++++++ tests/ovn.at | 224 ++++++++++++++++++++++++++++++++- tests/system-ovn.at | 148 ++++++++++++++++++++++ 9 files changed, 948 insertions(+), 48 deletions(-) diff --git a/northd/northd.c b/northd/northd.c index 331d9c267..045c3576b 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -91,7 +91,6 @@ static bool use_ct_inv_match = true; static bool default_acl_drop; #define MAX_OVN_TAGS 4096 - /* Due to various hard-coded priorities need to implement ACLs, the * northbound database supports a smaller range of ACL priorities than @@ -153,6 +152,8 @@ static bool default_acl_drop; #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" #define REGBIT_DST_NAT_IP_LOCAL "reg9[4]" #define REGBIT_KNOWN_LB_SESSION "reg9[6]" +#define REGBIT_DHCP_RELAY_REQ_CHK "reg9[7]" +#define REGBIT_DHCP_RELAY_RESP_CHK "reg9[8]" /* Register to store the eth address associated to a router port for packets * received in S_ROUTER_IN_ADMISSION. @@ -168,6 +169,7 @@ static bool default_acl_drop; #define REG_NEXT_HOP_IPV6 "xxreg0" #define REG_SRC_IPV4 "reg1" #define REG_SRC_IPV6 "xxreg1" +#define REG_DHCP_RELAY_DIP_IPV4 "reg2" #define REG_ROUTE_TABLE_ID "reg7" /* Register used to store backend ipv6 address @@ -232,7 +234,7 @@ static bool default_acl_drop; * | R1 | SRC_IPV4 for ARP-REQ | 0 | | R | | * | | (>= IP_INPUT) | | | E | NEXT_HOP_IPV6 (>= DEFRAG ) | * +-----+---------------------------+---+-----------------+ G | | - * | R2 | UNUSED | X | | 0 | | + * | R2 REG_DHCP_RELAY_DIP_IPV4 | X | | 0 | | * | | | R | | | | * +-----+---------------------------+ E | UNUSED | | | * | R3 | UNUSED | G | | | | @@ -259,7 +261,9 @@ static bool default_acl_drop; * | | EGRESS_LOOPBACK/ | G | UNUSED | * | R9 | PKT_LARGER/ | 4 | | * | | LOOKUP_NEIGHBOR_RESULT/ | | | - * | | SKIP_LOOKUP_NEIGHBOR} | | | + * | | SKIP_LOOKUP_NEIGHBOR/ | | | + * | |REGBIT_DHCP_RELAY_REQ_CHK/ | | | + * | |REGBIT_DHCP_RELAY_RESP_CHK}| | | * | | | | | * | | REG_ORIG_TP_DPORT_ROUTER | | | * | | | | | @@ -8543,6 +8547,90 @@ build_dhcpv6_options_flows(struct ovn_port *op, ds_destroy(&match); } +static const char * +ls_dhcp_relay_port(const struct ovn_datapath *od) +{ + return smap_get(&od->nbs->other_config, "dhcp_relay_port"); +} + +static void +build_lswitch_dhcp_relay_flows(struct ovn_port *op, + const struct hmap *ls_ports, + struct lflow_table *lflows, + struct ds *match, + struct ds *actions) +{ + if (op->nbrp || !op->nbsp) { + return; + } + + /* consider only ports attached to VMs */ + if (strcmp(op->nbsp->type, "")) { + return; + } + + if (!op->od || !op->od->n_router_ports || + !op->od->nbs) { + return; + } + + /* configure dhcp relay flows only when peer router has + * relay config enabled */ + const char *dhcp_relay_port = ls_dhcp_relay_port(op->od); + if (!dhcp_relay_port) { + return; + } + + struct ovn_port *sp = ovn_port_find(ls_ports, dhcp_relay_port); + + if (!sp || !sp->nbsp || !sp->peer) { + return; + } + + struct ovn_port *rp = sp->peer; + if (!rp || !rp->nbrp || !rp->nbrp->dhcp_relay || rp->peer != sp) { + return; + } + + char *server_ip_str = NULL; + uint16_t port; + int addr_family; + struct in6_addr server_ip; + struct nbrec_dhcp_relay *dhcp_relay = rp->nbrp->dhcp_relay; + + if (!ip_address_and_port_from_lb_key(dhcp_relay->servers, &server_ip_str, + &server_ip, &port, &addr_family)) { + return; + } + + if (server_ip_str == NULL) { + return; + } + + ds_clear(match); + ds_clear(actions); + + ds_put_format( + match, "inport == %s && eth.src == %s && " + "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && " + "udp.src == 68 && udp.dst == 67", + op->json_key, op->lsp_addrs[0].ea_s); + ds_put_format(actions, + "eth.dst=%s;outport=%s;next;/* DHCP_RELAY_REQ */", + rp->lrp_networks.ea_s,sp->json_key); + ovn_lflow_add_with_hint__(lflows, op->od, + S_SWITCH_IN_L2_LKUP, 100, + ds_cstr(match), + ds_cstr(actions), + op->key, + NULL, + &op->nbsp->header_, + op->lflow_ref); + ds_clear(match); + ds_clear(actions); + free(server_ip_str); +} + static void build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, const struct ovn_port *port, @@ -9144,6 +9232,13 @@ build_lswitch_dhcp_options_and_response(struct ovn_port *op, return; } + if (op->od && op->od->nbs + && ls_dhcp_relay_port(op->od)) { + /* Don't add the DHCP server flows if DHCP Relay is enabled on the + * logical switch. */ + return; + } + bool is_external = lsp_is_external(op->nbsp); if (is_external && (!op->od->n_localnet_ports || !op->nbsp->ha_chassis_group)) { @@ -13623,6 +13718,166 @@ build_dhcpv6_reply_flows_for_lrouter_port( } } +static void +build_dhcp_relay_flows_for_lrouter_port( + struct ovn_port *op, struct lflow_table *lflows, + struct ds *match, struct ds *actions, + struct lflow_ref *lflow_ref) +{ + if (!op->nbrp || !op->nbrp->dhcp_relay) { + return; + + } + + /* configure dhcp relay flows only when peer switch has + * relay config enabled */ + struct ovn_port *sp = op->peer; + if (!sp || !sp->nbsp || sp->peer != op || + !sp->od || !ls_dhcp_relay_port(sp->od)) { + return; + } + + struct nbrec_dhcp_relay *dhcp_relay = op->nbrp->dhcp_relay; + if (!dhcp_relay->servers) { + return; + } + + int addr_family; + /* currently not supporting custom port, + * dhcp server port is always set to 67 when installing flows */ + uint16_t port; + char *server_ip_str = NULL; + struct in6_addr server_ip; + + if (!ip_address_and_port_from_lb_key(dhcp_relay->servers, &server_ip_str, + &server_ip, &port, &addr_family)) { + return; + } + + if (server_ip_str == NULL) { + return; + } + + ds_clear(match); + ds_clear(actions); + + ds_put_format( + match, "inport == %s && " + "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && " + "ip.frag == 0 && udp.src == 68 && udp.dst == 67", + op->json_key); + ds_put_format(actions, + REGBIT_DHCP_RELAY_REQ_CHK + " = dhcp_relay_req_chk(%s, %s);" + "next; /* DHCP_RELAY_REQ */", + op->lrp_networks.ipv4_addrs[0].addr_s, server_ip_str); + + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(actions); + + ds_put_format( + match, "inport == %s && " + "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && " + "udp.src == 68 && udp.dst == 67 && " + REGBIT_DHCP_RELAY_REQ_CHK, + op->json_key); + ds_put_format(actions, + "ip4.src=%s;ip4.dst=%s;udp.src=67;next; /* DHCP_RELAY_REQ */", + op->lrp_networks.ipv4_addrs[0].addr_s, server_ip_str); + + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_REQ, 100, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(actions); + + ds_put_format( + match, "inport == %s && " + "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && " + "udp.src == 68 && udp.dst == 67 && " + REGBIT_DHCP_RELAY_REQ_CHK" == 0", + op->json_key); + ds_put_format(actions, + "drop; /* DHCP_RELAY_REQ */"); + + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_REQ, 1, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(actions); + + ds_put_format( + match, "ip4.src == %s && ip4.dst == %s && " + "ip.frag == 0 && udp.src == 67 && udp.dst == 67", + server_ip_str, op->lrp_networks.ipv4_addrs[0].addr_s); + ds_put_format(actions, "next;/* DHCP_RELAY_RESP */"); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(actions); + + ds_put_format( + match, "ip4.src == %s && ip4.dst == %s && " + "udp.src == 67 && udp.dst == 67", + server_ip_str, op->lrp_networks.ipv4_addrs[0].addr_s); + ds_put_format(actions, + REG_DHCP_RELAY_DIP_IPV4" = ip4.dst;" + REGBIT_DHCP_RELAY_RESP_CHK + " = dhcp_relay_resp_chk(%s, %s);next;/* DHCP_RELAY_RESP */", + op->lrp_networks.ipv4_addrs[0].addr_s, server_ip_str); + + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_RESP_CHK, + 100, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_, lflow_ref); + + + ds_clear(match); + ds_clear(actions); + + ds_put_format( + match, "ip4.src == %s && " + REG_DHCP_RELAY_DIP_IPV4" == %s && " + "udp.src == 67 && udp.dst == 67 && " + REGBIT_DHCP_RELAY_RESP_CHK, + server_ip_str, op->lrp_networks.ipv4_addrs[0].addr_s); + ds_put_format(actions, + "ip4.src=%s;udp.dst=68;" + "outport=%s;output; /* DHCP_RELAY_RESP */", + op->lrp_networks.ipv4_addrs[0].addr_s, op->json_key); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_RESP, + 100, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(actions); + + ds_put_format( + match, "ip4.src == %s && " + REG_DHCP_RELAY_DIP_IPV4" == %s && " + "udp.src == 67 && udp.dst == 67 && " + REGBIT_DHCP_RELAY_RESP_CHK" == 0", + server_ip_str, op->lrp_networks.ipv4_addrs[0].addr_s); + ds_put_format(actions, + "drop; /* DHCP_RELAY_RESP */"); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_RESP, + 1, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_, lflow_ref); + ds_clear(match); + ds_clear(actions); + free(server_ip_str); +} + static void build_ipv6_input_flows_for_lrouter_port( struct ovn_port *op, struct lflow_table *lflows, @@ -14893,6 +15148,13 @@ static void build_lr_nat_defrag_and_lb_default_flows( lflow_ref); ovn_lflow_add(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 0, "1", "next;", lflow_ref); + ovn_lflow_add(lflows, od, S_ROUTER_IN_DHCP_RELAY_REQ, 0, "1", + "next;", lflow_ref); + ovn_lflow_add(lflows, od, S_ROUTER_IN_DHCP_RELAY_RESP_CHK, 0, "1", + "next;", lflow_ref); + ovn_lflow_add(lflows, od, S_ROUTER_IN_DHCP_RELAY_RESP, 0, "1", + "next;", lflow_ref); + /* Send the IPv6 NS packets to next table. When ovn-controller * generates IPv6 NS (for the action - nd_ns{}), the injected @@ -15652,6 +15914,7 @@ build_lswitch_and_lrouter_iterate_by_lsp(struct ovn_port *op, build_lswitch_icmp_packet_toobig_admin_flows(op, lflows, match, actions); build_lswitch_ip_unicast_lookup(op, lflows, actions, match); + build_lswitch_dhcp_relay_flows(op, ls_ports, lflows, match, actions); /* Build Logical Router Flows. */ build_arp_resolve_flows_for_lsp(op, lflows, lr_ports, match, actions); @@ -15681,6 +15944,8 @@ build_lswitch_and_lrouter_iterate_by_lrp(struct ovn_port *op, op->lflow_ref); build_dhcpv6_reply_flows_for_lrouter_port(op, lsi->lflows, &lsi->match, op->lflow_ref); + build_dhcp_relay_flows_for_lrouter_port(op, lsi->lflows, &lsi->match, + &lsi->actions, op->lflow_ref); build_ipv6_input_flows_for_lrouter_port(op, lsi->lflows, &lsi->match, &lsi->actions, lsi->meter_groups, diff --git a/northd/northd.h b/northd/northd.h index 18cad5234..940926945 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -441,24 +441,29 @@ enum ovn_stage { PIPELINE_STAGE(ROUTER, IN, LOOKUP_NEIGHBOR, 1, "lr_in_lookup_neighbor") \ PIPELINE_STAGE(ROUTER, IN, LEARN_NEIGHBOR, 2, "lr_in_learn_neighbor") \ PIPELINE_STAGE(ROUTER, IN, IP_INPUT, 3, "lr_in_ip_input") \ - PIPELINE_STAGE(ROUTER, IN, UNSNAT, 4, "lr_in_unsnat") \ - PIPELINE_STAGE(ROUTER, IN, DEFRAG, 5, "lr_in_defrag") \ - PIPELINE_STAGE(ROUTER, IN, LB_AFF_CHECK, 6, "lr_in_lb_aff_check") \ - PIPELINE_STAGE(ROUTER, IN, DNAT, 7, "lr_in_dnat") \ - PIPELINE_STAGE(ROUTER, IN, LB_AFF_LEARN, 8, "lr_in_lb_aff_learn") \ - PIPELINE_STAGE(ROUTER, IN, ECMP_STATEFUL, 9, "lr_in_ecmp_stateful") \ - PIPELINE_STAGE(ROUTER, IN, ND_RA_OPTIONS, 10, "lr_in_nd_ra_options") \ - PIPELINE_STAGE(ROUTER, IN, ND_RA_RESPONSE, 11, "lr_in_nd_ra_response") \ - PIPELINE_STAGE(ROUTER, IN, IP_ROUTING_PRE, 12, "lr_in_ip_routing_pre") \ - PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 13, "lr_in_ip_routing") \ - PIPELINE_STAGE(ROUTER, IN, IP_ROUTING_ECMP, 14, "lr_in_ip_routing_ecmp") \ - PIPELINE_STAGE(ROUTER, IN, POLICY, 15, "lr_in_policy") \ - PIPELINE_STAGE(ROUTER, IN, POLICY_ECMP, 16, "lr_in_policy_ecmp") \ - PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 17, "lr_in_arp_resolve") \ - PIPELINE_STAGE(ROUTER, IN, CHK_PKT_LEN, 18, "lr_in_chk_pkt_len") \ - PIPELINE_STAGE(ROUTER, IN, LARGER_PKTS, 19, "lr_in_larger_pkts") \ - PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 20, "lr_in_gw_redirect") \ - PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 21, "lr_in_arp_request") \ + PIPELINE_STAGE(ROUTER, IN, DHCP_RELAY_REQ, 4, "lr_in_dhcp_relay_req") \ + PIPELINE_STAGE(ROUTER, IN, UNSNAT, 5, "lr_in_unsnat") \ + PIPELINE_STAGE(ROUTER, IN, DEFRAG, 6, "lr_in_defrag") \ + PIPELINE_STAGE(ROUTER, IN, LB_AFF_CHECK, 7, "lr_in_lb_aff_check") \ + PIPELINE_STAGE(ROUTER, IN, DNAT, 8, "lr_in_dnat") \ + PIPELINE_STAGE(ROUTER, IN, LB_AFF_LEARN, 9, "lr_in_lb_aff_learn") \ + PIPELINE_STAGE(ROUTER, IN, ECMP_STATEFUL, 10, "lr_in_ecmp_stateful") \ + PIPELINE_STAGE(ROUTER, IN, ND_RA_OPTIONS, 11, "lr_in_nd_ra_options") \ + PIPELINE_STAGE(ROUTER, IN, ND_RA_RESPONSE, 12, "lr_in_nd_ra_response") \ + PIPELINE_STAGE(ROUTER, IN, IP_ROUTING_PRE, 13, "lr_in_ip_routing_pre") \ + PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 14, "lr_in_ip_routing") \ + PIPELINE_STAGE(ROUTER, IN, IP_ROUTING_ECMP, 15, "lr_in_ip_routing_ecmp") \ + PIPELINE_STAGE(ROUTER, IN, POLICY, 16, "lr_in_policy") \ + PIPELINE_STAGE(ROUTER, IN, POLICY_ECMP, 17, "lr_in_policy_ecmp") \ + PIPELINE_STAGE(ROUTER, IN, DHCP_RELAY_RESP_CHK, 18, \ + "lr_in_dhcp_relay_resp_chk") \ + PIPELINE_STAGE(ROUTER, IN, DHCP_RELAY_RESP, 19, \ + "lr_in_dhcp_relay_resp") \ + PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 20, "lr_in_arp_resolve") \ + PIPELINE_STAGE(ROUTER, IN, CHK_PKT_LEN, 21, "lr_in_chk_pkt_len") \ + PIPELINE_STAGE(ROUTER, IN, LARGER_PKTS, 22, "lr_in_larger_pkts") \ + PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 23, "lr_in_gw_redirect") \ + PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 24, "lr_in_arp_request") \ \ /* Logical router egress stages. */ \ PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL, 0, \ diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index b14a30285..1e7fb3888 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -1934,6 +1934,12 @@ output; logical switch. +
  • + A priority-100 flow that forwards all DHCP broadcast packets coming + from VIFs to the logical router port's MAC when DHCP relay is enabled + on the logical switch. +
  • +
  • Priority-90 flows for transit switches that forward registered IP multicast traffic to their corresponding multicast group , which @@ -2864,6 +2870,44 @@ icmp6_error {

  • +
  • +

    + For each logical router port configured with DHCP relay the + following priority-110 flows are added to manage the DHCP relay + traffic: + +

      +
    • +

      + if inport is lrp and ip4.src == 0.0.0.0 + and ip4.dst == 255.255.255.255 and + ip4.frag == 0 and udp.src == 68 + and udp.dst == 67, the dhcp_relay_req_chk + action is executed. +

      + +
      +                reg9[7] = dhcp_relay_req_chk(lrp_ip,
      +                                            dhcp_server_ip);next
      +              
      + +

      + if action is successful then, GIADDR in the dhcp header is + updated with lrp ip and stores 1 into reg9[7] else stores 0 + into reg9[7]. +

      +
    • + +
    • + if ip4.src is DHCP server ip and ip4.dst + is lrp IP and udp.src == 67 and + udp.dst == 67, the packet is advanced to the next + pipeline stage. +
    • +
    +

    +
  • +
  • L3 admission control: Priority-120 flows allows IGMP and MLD packets @@ -3328,8 +3372,50 @@ icmp6 { +

    Ingress Table 4: DHCP Relay Request

    +

    + This stage process the DHCP request packets on which + dhcp_relay_req_chk action is applied in the IP input stage. +

    +
      +
    • +

      + A priority-100 logical flow is added for each logical router port + configured with DHCP relay that matches inport is lrp + and ip4.src == 0.0.0.0 and + ip4.dst == 255.255.255.255 and udp.src == 68 + and udp.dst == 67 and reg9[7] == 1 + and applies following actions. If reg9[7] is set to 1 + then, dhcp_relay_req_chk action was successful. +

      + +
      +ip4.src=lrp ip;
      +ip4.dst=dhcp server ip;
      +udp.src = 67;
      +next;
      +        
      +
    • + +
    • +

      + A priority-1 logical flow is added for each logical router port + configured with DHCP relay that matches inport is lrp + and ip4.src == 0.0.0.0 and + ip4.dst == 255.255.255.255 and udp.src == 68 + and udp.dst == 67 and reg9[7] == 0 + and drops the packet. If reg9[7] is set to 0 then, + dhcp_relay_req_chk action was unsuccessful. +

      +
    • + +
    • + A priority-0 flow that matches all packets to advance to the next + table. +
    • +
    -

    Ingress Table 4: UNSNAT

    +

    Ingress Table 5: UNSNAT

    This is for already established connections' reverse traffic. @@ -3338,7 +3424,7 @@ icmp6 { unSNATted here.

    -

    Ingress Table 4: UNSNAT on Gateway and Distributed Routers

    +

    Ingress Table 5: UNSNAT on Gateway and Distributed Routers

    • @@ -3365,7 +3451,7 @@ icmp6 {

    -

    Ingress Table 4: UNSNAT on Gateway Routers

    +

    Ingress Table 5: UNSNAT on Gateway Routers

    • @@ -3414,7 +3500,7 @@ icmp6 {
    -

    Ingress Table 4: UNSNAT on Distributed Routers

    +

    Ingress Table 5: UNSNAT on Distributed Routers

    • @@ -3461,7 +3547,7 @@ icmp6 {
    -

    Ingress Table 5: DEFRAG

    +

    Ingress Table 6: DEFRAG

    This is to send packets to connection tracker for tracking and @@ -3504,7 +3590,7 @@ icmp6 { this allows potentially related ICMP traffic to pass through CT.

    -

    Ingress Table 6: Load balancing affinity check

    +

    Ingress Table 7: Load balancing affinity check

    Load balancing affinity check table contains the following @@ -3531,7 +3617,7 @@ icmp6 {

  • -

    Ingress Table 7: DNAT

    +

    Ingress Table 8: DNAT

    Packets enter the pipeline with destination IP address that needs to @@ -3539,7 +3625,7 @@ icmp6 { in the reverse direction needs to be unDNATed.

    -

    Ingress Table 7: Load balancing DNAT rules

    +

    Ingress Table 8: Load balancing DNAT rules

    Following load balancing DNAT flows are added for Gateway router or @@ -3660,7 +3746,7 @@ icmp6 { -

    Ingress Table 7: DNAT on Gateway Routers

    +

    Ingress Table 8: DNAT on Gateway Routers

    • @@ -3702,7 +3788,7 @@ icmp6 {
    -

    Ingress Table 7: DNAT on Distributed Routers

    +

    Ingress Table 8: DNAT on Distributed Routers

    On distributed routers, the DNAT table only handles packets @@ -3757,7 +3843,7 @@ icmp6 { -

    Ingress Table 8: Load balancing affinity learn

    +

    Ingress Table 9: Load balancing affinity learn

    Load balancing affinity learn table contains the following @@ -3785,7 +3871,7 @@ icmp6 { -

    Ingress Table 9: ECMP symmetric reply processing

    +

    Ingress Table 10: ECMP symmetric reply processing

    • If ECMP routes with symmetric reply are configured in the @@ -3804,7 +3890,7 @@ icmp6 {
    -

    Ingress Table 10: IPv6 ND RA option processing

    +

    Ingress Table 11: IPv6 ND RA option processing

    • @@ -3834,7 +3920,7 @@ reg0[5] = put_nd_ra_opts(options);next;
    -

    Ingress Table 11: IPv6 ND RA responder

    +

    Ingress Table 12: IPv6 ND RA responder

    This table implements IPv6 ND RA responder for the IPv6 ND RA replies @@ -3879,7 +3965,7 @@ output; -

    Ingress Table 12: IP Routing Pre

    +

    Ingress Table 13: IP Routing Pre

    If a packet arrived at this table from Logical Router Port P @@ -3909,7 +3995,7 @@ output; -

    Ingress Table 13: IP Routing

    +

    Ingress Table 14: IP Routing

    A packet that arrives at this table is an IP packet that should be @@ -4115,7 +4201,7 @@ select(reg8[16..31], MID1, MID2, ...); -

    Ingress Table 14: IP_ROUTING_ECMP

    +

    Ingress Table 15: IP_ROUTING_ECMP

    This table implements the second part of IP routing for ECMP routes @@ -4172,7 +4258,7 @@ outport = P; -

    Ingress Table 15: Router policies

    +

    Ingress Table 16: Router policies

    This table adds flows for the logical router policies configured on the logical router. Please see the @@ -4244,7 +4330,7 @@ next; -

    Ingress Table 16: ECMP handling for router policies

    +

    Ingress Table 17: ECMP handling for router policies

    This table handles the ECMP for the router policies configured with multiple nexthops. @@ -4293,7 +4379,84 @@ outport = P -

    Ingress Table 17: ARP/ND Resolution

    +

    Ingress Table 18: DHCP Relay Response Check

    +

    + This stage process the DHCP response packets coming from the DHCP server. +

    + +
      +
    • +

      + A priority 100 logical flow is added for each logical router port + configured with DHCP relay that matches ip4.src is + DHCP server ip and ip4.dst is lrp IP and + ip4.frag == 0 and udp.src == 67 and + udp.dst == 67 and applies dhcp_relay_resp_chk + action. Original destination ip is stored in reg2. +

      + +
      +        reg9[8] = dhcp_relay_resp_chk(lrp_ip,
      +                                      dhcp_server_ip);next
      +      
      + +

      + if action is successful then, dest mac and dest IP addresses are + updated in the packet and stores 1 into reg9[8] else stores 0 into + reg9[8]. +

      +
    • + +
    • + A priority-0 flow that matches all packets to advance to the next + table. +
    • +
    + +

    Ingress Table 19: DHCP Relay Response

    +

    + This stage process the DHCP response packets on which + dhcp_relay_resp_chk action is applied in the previous stage. +

    +
      +
    • +

      + A priority 100 logical flow is added for each logical router port + configured with DHCP relay that matches ip4.src is + DHCP server ip and reg2 is lrp IP and + udp.src == 67 and udp.dst == 67 + and reg9[8] == 1 and applies following actions. If + reg9[8] is set to 1 then, + dhcp_relay_resp_chk was successful. +

      + +
      +ip4.src = lrp ip;
      +udp.dst = 68;
      +outport = lrp port;
      +output;
      +        
      +
    • + +
    • +

      + A priority 1 logical flow is added for the logical router port + on which DHCP relay is enabled that matches ip4.src + is DHCP server ip and reg2 is lrp IP and + udp.src == 67 and udp.dst == 67 + and reg9[8] == 0 and drops the packet. If + reg9[8] is set to 0 then, + dhcp_relay_resp_chk was unsuccessful. +

      +
    • + +
    • + A priority-0 flow that matches all packets to advance to the next + table. +
    • +
    + +

    Ingress Table 20: ARP/ND Resolution

    Any packet that reaches this table is an IP packet whose next-hop @@ -4507,7 +4670,7 @@ outport = P -

    Ingress Table 18: Check packet length

    +

    Ingress Table 21: Check packet length

    For distributed logical routers or gateway routers with gateway @@ -4544,7 +4707,7 @@ REGBIT_PKT_LARGER = check_pkt_larger(L); next; and advances to the next table.

    -

    Ingress Table 19: Handle larger packets

    +

    Ingress Table 22: Handle larger packets

    For distributed logical routers or gateway routers with gateway port @@ -4607,7 +4770,7 @@ icmp6 { and advances to the next table.

    -

    Ingress Table 20: Gateway Redirect

    +

    Ingress Table 23: Gateway Redirect

    For distributed logical routers where one or more of the logical router @@ -4691,7 +4854,7 @@ icmp6 { -

    Ingress Table 21: ARP Request

    +

    Ingress Table 24: ARP Request

    In the common case where the Ethernet destination has been resolved, this diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema index a9c5b7af5..10ce50b25 100644 --- a/ovn-nb.ovsschema +++ b/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "7.3.0", - "cksum": "3546526738 34483", + "version": "7.3.1", + "cksum": "3899022625 35372", "tables": { "NB_Global": { "columns": { @@ -436,6 +436,11 @@ "ipv6_prefix": {"type": {"key": "string", "min": 0, "max": "unlimited"}}, + "dhcp_relay": {"type": {"key": {"type": "uuid", + "refTable": "DHCP_Relay", + "refType": "strong"}, + "min": 0, + "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, @@ -534,6 +539,18 @@ "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "isRoot": true}, + "DHCP_Relay": { + "columns": { + "name": {"type": "string"}, + "servers": {"type": {"key": "string", + "min": 0, + "max": 1}}, + "options": {"type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}, + "isRoot": true}, "Connection": { "columns": { "target": {"type": "string"}, diff --git a/ovn-nb.xml b/ovn-nb.xml index b652046a7..5cb6ba640 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -703,6 +703,13 @@ + + If set to the name of logical switch port of type router + then, DHCP Relay is enabled for this logical switch provided the + corresponding has DHCP Relay + configured. + + Value used to request to assign L2 address only if neither subnet nor ipv6_prefix are specified @@ -3066,6 +3073,11 @@ or port has all ingress and egress traffic dropped. + + This column is used to enabled DHCP Relay. Please refer + to table. + +

    Gateways, as documented under Gateways in the OVN @@ -4379,6 +4391,33 @@ or + +

    + OVN implements native DHCPv4 relay support which caters to the common + use case of relaying the DHCP requests to external DHCP server. +

    + +

    + A name for the DHCP Relay. +

    +
    + +

    + The DHCPv4 server IP address. +

    +
    + +

    + Future purpose. +

    +
    + + + See External IDs at the beginning of this document. + + +
    +

    Configuration for a database connection to an Open vSwitch database diff --git a/tests/atlocal.in b/tests/atlocal.in index 63d891b89..32d1c374e 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -187,6 +187,9 @@ fi # Set HAVE_DHCPD find_command dhcpd +# Set HAVE_DHCLIENT +find_command dhclient + # Set HAVE_BFDD_BEACON find_command bfdd-beacon diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index dcc29ffa8..7267c7017 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -12191,6 +12191,44 @@ check_row_count nb:QoS 0 AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([check DHCP RELAY]) +ovn_start NORTHD_TYPE + +check ovn-nbctl ls-add ls0 +check ovn-nbctl lsp-add ls0 ls0-port1 +check ovn-nbctl lsp-set-addresses ls0-port1 02:00:00:00:00:10 +check ovn-nbctl lr-add lr0 +check ovn-nbctl lrp-add lr0 lrp1 02:00:00:00:00:01 192.168.1.1/24 +check ovn-nbctl lsp-add ls0 lrp1-attachment +check ovn-nbctl lsp-set-type lrp1-attachment router +check ovn-nbctl lsp-set-addresses lrp1-attachment 00:00:00:00:ff:02 +check ovn-nbctl lsp-set-options lrp1-attachment router-port=lrp1 +check ovn-nbctl lrp-add lr0 lrp-ext 02:00:00:00:00:02 192.168.2.1/24 + +dhcp_relay=$(ovn-nbctl create DHCP_Relay servers=172.16.1.1) +check ovn-nbctl set Logical_Router_port lrp1 dhcp_relay=$dhcp_relay +check ovn-nbctl set Logical_Switch ls0 other_config:dhcp_relay_port=lrp1-attachment + +check ovn-nbctl --wait=sb sync + +ovn-sbctl lflow-list > lflows +AT_CAPTURE_FILE([lflows]) + +AT_CHECK([grep -e "DHCP_RELAY_" lflows | sed 's/table=../table=??/'], [0], [dnl + table=??(lr_in_ip_input ), priority=110 , match=(inport == "lrp1" && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && ip.frag == 0 && udp.src == 68 && udp.dst == 67), action=(reg9[[7]] = dhcp_relay_req_chk(192.168.1.1, 172.16.1.1);next; /* DHCP_RELAY_REQ */) + table=??(lr_in_ip_input ), priority=110 , match=(ip4.src == 172.16.1.1 && ip4.dst == 192.168.1.1 && ip.frag == 0 && udp.src == 67 && udp.dst == 67), action=(next;/* DHCP_RELAY_RESP */) + table=??(lr_in_dhcp_relay_req), priority=100 , match=(inport == "lrp1" && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67 && reg9[[7]]), action=(ip4.src=192.168.1.1;ip4.dst=172.16.1.1;udp.src=67;next; /* DHCP_RELAY_REQ */) + table=??(lr_in_dhcp_relay_req), priority=1 , match=(inport == "lrp1" && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67 && reg9[[7]] == 0), action=(drop; /* DHCP_RELAY_REQ */) + table=??(lr_in_dhcp_relay_resp_chk), priority=100 , match=(ip4.src == 172.16.1.1 && ip4.dst == 192.168.1.1 && udp.src == 67 && udp.dst == 67), action=(reg2 = ip4.dst;reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 172.16.1.1);next;/* DHCP_RELAY_RESP */) + table=??(lr_in_dhcp_relay_resp), priority=100 , match=(ip4.src == 172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && reg9[[8]]), action=(ip4.src=192.168.1.1;udp.dst=68;outport="lrp1";output; /* DHCP_RELAY_RESP */) + table=??(lr_in_dhcp_relay_resp), priority=1 , match=(ip4.src == 172.16.1.1 && reg2 == 192.168.1.1 && udp.src == 67 && udp.dst == 67 && reg9[[8]] == 0), action=(drop; /* DHCP_RELAY_RESP */) + table=??(ls_in_l2_lkup ), priority=100 , match=(inport == "ls0-port1" && eth.src == 02:00:00:00:00:10 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(eth.dst=02:00:00:00:00:01;outport="lrp1-attachment";next;/* DHCP_RELAY_REQ */) +]) + +AT_CLEANUP +]) + AT_SETUP([NB_Global and SB_Global incremental processing]) ovn_start diff --git a/tests/ovn.at b/tests/ovn.at index 1ad4159cf..395bcf142 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -34273,7 +34273,7 @@ check ovn-nbctl set nb_global . options:use_common_zone="true" check ovn-nbctl --wait=hv sync # Use constants so that if tables or registers change, this test can # be updated easily. -DNAT_TABLE=15 +DNAT_TABLE=16 SNAT_TABLE=45 DNAT_ZONE_REG="NXM_NX_REG11[[0..15]]" SNAT_ZONE_REG="NXM_NX_REG12[[0..15]]" @@ -37806,3 +37806,225 @@ OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=0 |grep priority=1 OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([DHCP RELAY]) +ovn_start +net_add n1 + +AT_CHECK([ovn-nbctl ls-add ls0]) +AT_CHECK([ovn-nbctl lsp-add ls0 vif0]) +AT_CHECK([ovn-nbctl lsp-set-addresses vif0 "50:54:00:00:00:10"]) +AT_CHECK([ovn-nbctl lsp-add ls0 lrp1-attachment]) +AT_CHECK([ovn-nbctl lsp-set-type lrp1-attachment router]) +AT_CHECK([ovn-nbctl lsp-set-addresses lrp1-attachment 50:54:00:00:00:01]) +AT_CHECK([ovn-nbctl lsp-set-options lrp1-attachment router-port=lrp1]) + +AT_CHECK([ovn-nbctl lr-add lr0]) +AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 50:54:00:00:00:01 192.168.1.1/24]) +AT_CHECK([ovn-nbctl lrp-add lr0 lrp2 50:54:00:00:00:02 172.16.1.254/24]) + +AT_CHECK([ovn-nbctl ls-add ls-ext]) +AT_CHECK([ovn-nbctl lsp-add ls-ext lrp2-attachment]) +AT_CHECK([ovn-nbctl lsp-set-type lrp2-attachment router]) +AT_CHECK([ovn-nbctl lsp-set-addresses lrp2-attachment 50:54:00:00:00:02]) +AT_CHECK([ovn-nbctl lsp-set-options lrp2-attachment router-port=lrp2]) +AT_CHECK([ovn-nbctl lsp-add ls-ext ln_port]) +AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown]) +AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet]) +AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1]) + +dhcp_relay=$(ovn-nbctl create DHCP_Relay servers=172.16.1.1) +AT_CHECK([ovn-nbctl set Logical_Router_port lrp1 dhcp_relay=$dhcp_relay]) +AT_CHECK([ovn-nbctl set Logical_Switch ls0 other_config:dhcp_relay_port=lrp1-attachment]) + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int vif0 -- \ + set interface vif0 external-ids:iface-id=vif0 \ + options:tx_pcap=hv1/vif0-tx.pcap \ + options:rxq_pcap=hv1/vif0-rx.pcap \ + ofport-request=1 +ovs-vsctl -- add-port br-phys ext0 -- \ + set interface ext0 \ + options:tx_pcap=hv1/ext0-tx.pcap \ + options:rxq_pcap=hv1/ext0-rx.pcap \ + ofport-request=2 + +ovs-vsctl set open . external_ids:ovn-bridge-mappings=physnet1:br-phys + +wait_for_ports_up +AT_CHECK([ovn-nbctl --wait=hv sync]) + +send_dhcp_packet() { + src_mac=${1} + src_ip=${2} + dst_mac=${3} + dst_ip=${4} + op_code=${5} + msg_type=${6} + yiaddr=$7 + giaddr=${8} + sid=${9} + iface=${10} + #echo "ARGS: ${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9} ${10}" + echo "ARGS: $@" + if [[ $op_code == "01" ]]; then + ip_len=0111 + udp_len=00fd + src_port=0044 + else + ip_len=011d + udp_len=0109 + src_port=0043 + fi + flags=0000 + + local pkt=${dst_mac}${src_mac}08004510${ip_len}0000000080110000${src_ip}${dst_ip} + # udp header and dhcp header + pkt=${pkt}${src_port}0043${udp_len}0000 + pkt=${pkt}${op_code}0106006359aa760000${flags}00000000${yiaddr}00000000${giaddr}${src_mac} + # client hardware padding + pkt=${pkt}00000000000000000000 + # server hostname + pkt=${pkt}0000000000000000000000000000000000000000000000000000000000000000 + pkt=${pkt}0000000000000000000000000000000000000000000000000000000000000000 + # boot file name + pkt=${pkt}0000000000000000000000000000000000000000000000000000000000000000 + pkt=${pkt}0000000000000000000000000000000000000000000000000000000000000000 + pkt=${pkt}0000000000000000000000000000000000000000000000000000000000000000 + pkt=${pkt}0000000000000000000000000000000000000000000000000000000000000000 + # dhcp magic cookie + pkt=${pkt}63825363 + # dhcp message type + pkt=${pkt}3501${msg_type} + # dhcp server identifier and subnet mask options + if [[ $op_code == "02" ]]; then + pkt=${pkt}3604${sid} + pkt=${pkt}0104ffffff00 + fi + # dhcp pad option + pkt=${pkt}00 + # dhcp end option + pkt=${pkt}ff + + tcpdump_hex "-- sending DHCP pkt on hv1-$iface" $pkt + + ovs-appctl netdev-dummy/receive $iface $pkt +} + +ovn-sbctl dump-flows > lflows +AT_CAPTURE_FILE([lflows]) + +# Get the OF table numbers +dhcp_relay_req_table=$(ovn-debug lflow-stage-to-oftable lr_in_dhcp_relay_req) +dhcp_relay_resp_table=$(ovn-debug lflow-stage-to-oftable lr_in_dhcp_relay_resp) + +# ==================================================== +# Send DHCP valid discovery +src_mac="505400000010" +src_ip=`ip_to_hex 0.0.0.0` +dst_mac="ffffffffffff" +dst_ip=`ip_to_hex 255.255.255.255` +yiaddr=`ip_to_hex 0.0.0.0` +giaddr=`ip_to_hex 0.0.0.0` +sid=$src_ip +# send packet +send_dhcp_packet $src_mac $src_ip $dst_mac $dst_ip 01 01 $yiaddr $giaddr $sid vif0 + +ovs-ofctl dump-flows br-int table=$dhcp_relay_req_table > pflows1_dhcp_relay_req +AT_CAPTURE_FILE([pflows1_dhcp_relay_req]) + +AT_CHECK([cat pflows1_dhcp_relay_req | grep -v NXST | grep 255.255.255.255 | grep resubmit | +cut -d ' ' -f5-5 | sed "s/,//"], [0], [dnl +n_packets=1 +]) + +# ==================================================== +# Send DHCP discovery with giaddr set +giaddr=`ip_to_hex 192.168.1.1` +# send packet +send_dhcp_packet $src_mac $src_ip $dst_mac $dst_ip 01 01 $yiaddr $giaddr $sid vif0 + +ovs-ofctl dump-flows br-int table=$dhcp_relay_req_table > pflows2_dhcp_relay_req +AT_CAPTURE_FILE([pflows2_dhcp_relay_req]) + +AT_CHECK([cat pflows2_dhcp_relay_req | grep -v NXST | grep 255.255.255.255 | grep drop | +cut -d ' ' -f5-5 | sed "s/,//"], [0], [dnl +n_packets=1 +]) + +# ==================================================== +# Send DHCP valid offer +src_mac="50540000001f" +src_ip=`ip_to_hex 172.16.1.1` +dst_mac="505400000002" +dst_ip=`ip_to_hex 192.168.1.1` +yiaddr=`ip_to_hex 192.168.1.10` +giaddr=`ip_to_hex 192.168.1.1` +sid=$src_ip +# send packet +send_dhcp_packet $src_mac $src_ip $dst_mac $dst_ip 02 02 $yiaddr $giaddr $sid ext0 + +ovs-ofctl dump-flows br-int table=$dhcp_relay_resp_table > pflows1_dhcp_relay_resp +AT_CAPTURE_FILE([pflows1_dhcp_relay_resp]) + +AT_CHECK([cat pflows1_dhcp_relay_resp | grep -v NXST | grep 172.16.1.1 | grep resubmit | +cut -d ' ' -f5-5 | sed "s/,//"], [0], [dnl +n_packets=1 +]) +# ==================================================== +# Send DHCP offer with incorrect giaddr +giaddr=`ip_to_hex 192.168.1.10` +# send packet +send_dhcp_packet $src_mac $src_ip $dst_mac $dst_ip 02 02 $yiaddr $giaddr $sid ext0 + +ovs-ofctl dump-flows br-int table=$dhcp_relay_resp_table > pflows2_dhcp_relay_resp +AT_CAPTURE_FILE([pflows2_dhcp_relay_resp]) + +AT_CHECK([cat pflows2_dhcp_relay_resp | grep -v NXST | grep 172.16.1.1 | grep drop | +cut -d ' ' -f5-5 | sed "s/,//"], [0], [dnl +n_packets=1 +]) + +giaddr=`ip_to_hex 192.168.1.1` + +# ==================================================== +# Send DHCP offer with yiaddr outside of the subnet +yiaddr=`ip_to_hex 192.168.2.10` +# send packet +send_dhcp_packet $src_mac $src_ip $dst_mac $dst_ip 02 02 $yiaddr $giaddr $sid ext0 + +ovs-ofctl dump-flows br-int table=$dhcp_relay_resp_table > pflows2_dhcp_relay_resp +AT_CAPTURE_FILE([pflows2_dhcp_relay_resp]) + +AT_CHECK([cat pflows2_dhcp_relay_resp | grep -v NXST | grep 172.16.1.1 | grep drop | +cut -d ' ' -f5-5 | sed "s/,//"], [0], [dnl +n_packets=2 +]) + +yiaddr=`ip_to_hex 192.168.1.10` + +# ==================================================== +# Send DHCP offer with differnt server identifier +sid=`ip_to_hex 172.16.1.100` +# send packet +send_dhcp_packet $src_mac $src_ip $dst_mac $dst_ip 02 02 $yiaddr $giaddr $sid ext0 + +ovs-ofctl dump-flows br-int table=$dhcp_relay_resp_table > pflows2_dhcp_relay_resp +AT_CAPTURE_FILE([pflows2_dhcp_relay_resp]) + +AT_CHECK([cat pflows2_dhcp_relay_resp | grep -v NXST | grep 172.16.1.1 | grep drop | +cut -d ' ' -f5-5 | sed "s/,//"], [0], [dnl +n_packets=3 +]) + +sid=`ip_to_hex 172.16.1.1` + +OVN_CLEANUP([hv1 +/WARN\|DHCP_RELAY/d +]) +AT_CLEANUP +]) diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 5848f3901..b9f731396 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -12512,3 +12512,151 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d /connection dropped.*/d"]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([DHCP RELAY]) +AT_SKIP_IF([test $HAVE_DHCPD = no]) +AT_SKIP_IF([test $HAVE_DHCLIENT = no]) +AT_SKIP_IF([test $HAVE_TCPDUMP = no]) +ovn_start +OVS_TRAFFIC_VSWITCHD_START() + +ADD_BR([br-int]) +ADD_BR([br-ext]) + +ovs-ofctl add-flow br-ext action=normal +# Set external-ids in br-int needed for ovn-controller +ovs-vsctl \ + -- set Open_vSwitch . external-ids:system-id=hv1 \ + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true + +# Start ovn-controller +start_daemon ovn-controller + +ADD_NAMESPACES(sw01) +ADD_VETH(sw01, sw01, br-int, "0", "f0:00:00:01:02:03") +ADD_NAMESPACES(sw11) +ADD_VETH(sw11, sw11, br-int, "0", "f0:00:00:02:02:03") +ADD_NAMESPACES(server) +ADD_VETH(s1, server, br-ext, "172.16.1.1/24", "f0:00:00:01:02:05", \ + "172.16.1.254") + +check ovn-nbctl lr-add R1 + +check ovn-nbctl ls-add sw0 +check ovn-nbctl ls-add sw1 +check ovn-nbctl ls-add sw-ext + +check ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24 +check ovn-nbctl lrp-add R1 rp-sw1 00:00:03:01:02:03 192.168.2.1/24 +check ovn-nbctl lrp-add R1 rp-ext 00:00:02:01:02:03 172.16.1.254/24 + +dhcp_relay=$(ovn-nbctl create DHCP_Relay servers=172.16.1.1) +check ovn-nbctl set Logical_Router_port rp-sw0 dhcp_relay=$dhcp_relay +check ovn-nbctl set Logical_Router_port rp-sw1 dhcp_relay=$dhcp_relay +check ovn-nbctl lrp-set-gateway-chassis rp-ext hv1 + +check ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \ + type=router options:router-port=rp-sw0 \ + -- lsp-set-addresses sw0-rp router +check ovn-nbctl lsp-add sw1 sw1-rp -- set Logical_Switch_Port sw1-rp \ + type=router options:router-port=rp-sw1 \ + -- lsp-set-addresses sw1-rp router + +check ovn-nbctl set Logical_Switch sw0 other_config:dhcp_relay_port=sw0-rp +check ovn-nbctl set Logical_Switch sw1 other_config:dhcp_relay_port=sw1-rp + +check ovn-nbctl lsp-add sw-ext ext-rp -- set Logical_Switch_Port ext-rp \ + type=router options:router-port=rp-ext \ + -- lsp-set-addresses ext-rp router +check ovn-nbctl lsp-add sw-ext lnet \ + -- lsp-set-addresses lnet unknown \ + -- lsp-set-type lnet localnet \ + -- lsp-set-options lnet network_name=phynet + +check ovn-nbctl lsp-add sw0 sw01 \ + -- lsp-set-addresses sw01 "f0:00:00:01:02:03" + +check ovn-nbctl lsp-add sw1 sw11 \ + -- lsp-set-addresses sw11 "f0:00:00:02:02:03" + +AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext]) + +OVN_POPULATE_ARP + +check ovn-nbctl --wait=hv sync + +DHCP_TEST_DIR="/tmp/dhcp-test" +rm -rf $DHCP_TEST_DIR +mkdir $DHCP_TEST_DIR +cat > $DHCP_TEST_DIR/dhcpd.conf < $DHCP_TEST_DIR/dhclien.conf < dhcpd.log 2>&1], [dhcpd.pid]) + +NS_CHECK_EXEC([server], [tcpdump -l -nvv -i s1 udp > pkt.pcap 2>tcpdump_err &]) +OVS_WAIT_UNTIL([grep "listening" tcpdump_err]) +on_exit 'kill $(pidof tcpdump)' + +NS_CHECK_EXEC([sw01], [dhclient -1 -q -lf $DHCP_TEST_DIR/dhclient-sw01.lease -pf $DHCP_TEST_DIR/dhclient-sw01.pid -cf $DHCP_TEST_DIR/dhclien.conf sw01]) +NS_CHECK_EXEC([sw11], [dhclient -1 -q -lf $DHCP_TEST_DIR/dhclient-sw11.lease -pf $DHCP_TEST_DIR/dhclient-sw11.pid -cf $DHCP_TEST_DIR/dhclien.conf sw11]) + +OVS_WAIT_UNTIL([ + total_pkts=$(cat pkt.pcap | wc -l) + test ${total_pkts} -ge 8 +]) + +on_exit 'kill `cat $DHCP_TEST_DIR/dhclient-sw01.pid` && +kill `cat $DHCP_TEST_DIR/dhclient-sw11.pid` && rm -rf $DHCP_TEST_DIR' + +NS_CHECK_EXEC([sw01], [ip addr show sw01 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'], [0], [dnl +192.168.1.10 +]) +NS_CHECK_EXEC([sw11], [ip addr show sw11 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'], [0], [dnl +192.168.2.10 +]) +OVS_APP_EXIT_AND_WAIT([ovn-controller]) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([ovn-northd]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d +/failed to query port patch-.*/d +/.*terminating with signal 15.*/d"]) +AT_CLEANUP +])