From patchwork Tue Mar 19 07:54:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naveen Yerramneni X-Patchwork-Id: 1913393 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=eZUshvCI; 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=MCdtL43o; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (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 4TzPCl56swz1yWv for ; Tue, 19 Mar 2024 18:55:31 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 2013460828; Tue, 19 Mar 2024 07:55:29 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iZHYMUB1b0V6; Tue, 19 Mar 2024 07:55:25 +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 smtp3.osuosl.org 887D160A4E Authentication-Results: smtp3.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=eZUshvCI; 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=MCdtL43o Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id 887D160A4E; Tue, 19 Mar 2024 07:55:25 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 640CFC0072; Tue, 19 Mar 2024 07:55:25 +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 C2524C0DCF for ; Tue, 19 Mar 2024 07:55:23 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 9420140675 for ; Tue, 19 Mar 2024 07:55:23 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9qt5_bDG-QP1 for ; Tue, 19 Mar 2024 07:55:19 +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 smtp4.osuosl.org 54FBD4065F 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 54FBD4065F Authentication-Results: smtp4.osuosl.org; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=proofpoint20171006 header.b=eZUshvCI; dkim=pass (2048-bit key, unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256 header.s=selector1 header.b=MCdtL43o Received: from mx0a-002c1b01.pphosted.com (mx0a-002c1b01.pphosted.com [148.163.151.68]) by smtp4.osuosl.org (Postfix) with ESMTPS id 54FBD4065F for ; Tue, 19 Mar 2024 07:55:19 +0000 (UTC) Received: from pps.filterd (m0127840.ppops.net [127.0.0.1]) by mx0a-002c1b01.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 42IHMX6t028851; Tue, 19 Mar 2024 00:55:18 -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=HDjW8Pr1GVuVufHBuwaJTlc9V9oA2lPFrkB843eYu ec=; b=eZUshvCIV3H9w7V6g9/jkNDtoszI8HY0ZCA5MdVtEWHyNMN8KIqmd09nQ o8x9m6CpVYJLBBAfSnlF/Racwz73gijAKq7ucI3Bvn7Q+EIcvjOaBqqCtvdCbBju LbruD+d/G+jB5F9gFsb+8BL4AkOlaiFt7nm5ObTAYFPYPM8ASToaxiyp/wW9mePG mVwFwUDKG6iitTlkTIdoUhspWQ05WS2XH67fVzwZ65b4ZZYm8lXqAXE6Nt5zNw0u i5a0iULz1u+yND54e9Lu2ctlB4mGqNJdDy6IsodXImsYZqDq6vjORNctwIFN1KDD Tky4aGE79TU4HUTung4ATNBsm10/A== Received: from byapr05cu005.outbound.protection.outlook.com (mail-westusazlp17011008.outbound.protection.outlook.com [40.93.1.8]) by mx0a-002c1b01.pphosted.com (PPS) with ESMTPS id 3ww7rtddrm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 19 Mar 2024 00:55:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nkisnQiJfJmvT63h1qSw/ccMdxd8muXHaOR4kbLxdfomXVxWopwxFMvITXMyRC/z7Vf72DuAF9W8Z4nSanBG9SzNvFd/zB2DL/+tUlSgZ3THdaI/4HtIuPD+kJlEzXbQlR/vcIxR0EQDqq3jvxFf9mk2Kg+Pil+C1toENt1rwEm4PcVQRqn0NPiQ+uMaWL3nvwkraPkkYkvct28kohGNhEhBebcDt+Xuc+ARimEkgF7SQ8z5aO0XJFOj18q1PdYjPUEC/GmvQ2aZEj/u+kQbmyFiECfjWcnFvQzomzEqYO1Y4LqY/GCyyN4+0JyB9zYIJq20YA0BiGAqzXSxg4BmtA== 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=HDjW8Pr1GVuVufHBuwaJTlc9V9oA2lPFrkB843eYuec=; b=iiGScI1LpJba84pZhHVFd5+EgRZOhd6mZB0d5yroiMmFJSqpzBAwxewW+STTlWUj9T+6zm/oLba6bmcl0DVySUMiEJM/S4Mp3JELiTLTr+bf0kqRFxown3W4c9K9GASwXaWrjTS20ZXUXU59nao156WQEY0GzRE+VxR3e1MwVfFVtCo3B3BHgpKvfomreawb3oxJO+LXtMJXPjbQodykx42VRmq/C3EDqYHpRpXYx+lCY8gXzqyGO/YOHbkaJw+N1XdZHFeOccvUh3ONmhnkEyKpGZHe5dj7YX8CCzTtBaB5dIhIJcYB+/lB0TrzHQLaPTUhLkHechM8N5AJV3oFYw== 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=HDjW8Pr1GVuVufHBuwaJTlc9V9oA2lPFrkB843eYuec=; b=MCdtL43oHz7ue5ikea751p4oQt3Vrzdud+Y9gd/tmg3IZBUJRnu54mvziv12jl7sPH9gOwtPuGKhjYV+6GfwawOTWyc15Wzz5W6dCBqC3P2v6W0QQ43t7u/oQk6fsCCn4MOu64exwjX3lMKbkcLsHDVvc1RGXFOhzKRfQKExgSwOvd2nyzetxqks0eRRGA2+4DtFJJUT/UwRcvcHNM6d5stIL8kO08Ehz2SDqAYo3Ojzh1ZtQrAHebRI301S3VzHVKWMRxkaIQEyyYiox1qKbTwHDjD2tJIok5u0jV2ZytWphsBtMYE2Rk08l+2SOxqyFiH0CgxMr8MWXg/7IuftgQ== Received: from SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) by SA2PR02MB7788.namprd02.prod.outlook.com (2603:10b6:806:135::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7386.27; Tue, 19 Mar 2024 07:55:17 +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.7386.025; Tue, 19 Mar 2024 07:55:16 +0000 From: Naveen Yerramneni To: dev@openvswitch.org Date: Tue, 19 Mar 2024 07:54:57 +0000 Message-Id: <20240319075458.49166-4-naveen.yerramneni@nutanix.com> X-Mailer: git-send-email 2.36.6 In-Reply-To: <20240319075458.49166-1-naveen.yerramneni@nutanix.com> References: <20240319075458.49166-1-naveen.yerramneni@nutanix.com> X-ClientProxiedBy: SJ0PR03CA0201.namprd03.prod.outlook.com (2603:10b6:a03:2ef::26) To SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR02MB7808:EE_|SA2PR02MB7788:EE_ x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: jffzBPtvq9y6eKbyHbC0kwS/J5ZEmGTnoTuK7y1eoCi1tdL7kvXsdmKV3R4z8EVswZPl18Mtt1oSefPFZyWBQ/Ffrwhdd2GQQgWe/uA4UYOGeSJmC8RTQVSG2NVsp6IeeOnrOzj0NwZpYjW/LMe4Zm55E6fnMRlNcOpAHL7eVjj3K+XKmzrkK+F9ejMg6/XbEoaA418RLfrHAJ56kHRQaWUw8VkGilLXxdelhz80Eaafai3rQKS1VJonNCw7qowx0n9o2O3TluheIdyWp3DIKD6QKkFulGUWIbndIEBVqpcG6WyEIeRsg7r1Zv85rqjn6WCLgAFzA6dxdh8Iug9m4N8LeRiGJWAh4JsoeqoFJWPzZlxa4wr/UbzOcyE2+5zdYH62+HXTGGzhlUsGEle53Nb7fuAXx8uUUn34k2+hchALjzN9K9pgTRwmRPh9so69rpj0JY8mKm1enUOfQAOw1OtmieuyhtUMVFhxyfgmITZhJ6CO6qN0jLfmMw+Jtioch56jAo8bZ6dY2ON30LKn8xVrYsOtwTb1xK97m4DCfEltDsyzkPLaoWOsL4ErAdy6JUl9+vI4tqJhsoQuPoBIPT4/DbmJh5s8LkG4OYGDnWm1ghhalFrLQ4m3S8QKglkNnhn0K59QDIyuzQlR/YodbaFn51cZeeOQzSBSa5Lm8ILfmzNrFw6VauXnUgkG1Oltz49ys4L4GhXyD9fLaffwbZofJvaCs4IgTq0Fwcl6A5Q= 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)(1800799015)(52116005)(376005)(38350700005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: oK2NiHtdA/SYkXl/8MsvZMKppwrINycvj/iSwKT8WZG7rqePg+VUX7yFa9hxZXqCLUhfHjRf5VoWjr3UQkYUDQMh39u1V69K9sisGvLxdQAwHWQcJCXhPkCGXToZf7NRjJsJmjm7x6HpEp8/lRYFyHh+t6pjwWOIdKprEp9S+EKqySASvuUxDNzzVFoLTS5Rp5tVzYHxtvTokSHmk+fs3WapNf9tTIST/Gw1bZ9H+cdIFy2Z9/g30s0WzKRxUFKNHWAESOlCdU7/86hlE+Wl5Z+eALP2JrBJyPTmmwYkCTd7A5KvnsIuymGjY4LOi/pfLtgwsmp9ko84qRXNwmk9tNUlNW2sy70EJiWU54K+8ffvAIGHHp+gwQ4CgAy/ENQZUgJ5eVLeKd10l3cR8u1CEVwGWY4h9CE95CVTocHoBeNlg73qDSYzr43YU4l0Vze7THgqGxHIm4sRG11MZGV8R7zjWs98FlEeWQZDak4qwXRdsWO8ZZtGFjBuiBfeKdrnYzis4ufMOtGqa/9WYcSjhZRdFFfdgWXZq8Mfa1/UlCjQ9UVQmpV5gZvd5DxE/K0lNS97v7/9cQg5/F0onKKXOE+6TFlwQAxh+RM9HofvxcfB9LN7RZ4RpZaUEV7pcM9pByrOIK47Wz/k6Y4h4SgrS0bhpIc8qXnbvCD5IOQsUCizcTyEf5HpxZM0CCAJ2ugshyiIkV/CMDWvuuCmX3cnrxR2HOP591qhFZ68P7Qa7HsxEcOotIUBUgqPGoybekAZxbOA8itXJxg5xgXhUEGmxxHioODHauiUFEDWh0WXxilqY+vnCEkB3Z4sULpTwG8ea4/+aJyqHZleHCUETMPQE3KUI+JRokmFMNn+wgIsVqwJnGf2qOmfUwkOrqrKblYIe0OT8GIkz3lNKkElt8Hq9OaaeiIR1Ii5i9E7BfSbT+2BaOoYUDe4C9QrPRRLfM1Wta/5fFmNmtjO9D1xrBH/uLXZEf0niyTZeUqtvWqGm5dqGKTYDtIrcIyuGVKZ40nTiOP/RGOzsLfoxL2jx5odRM/LKOjREzlcKE0JJfqAli8Ah/tpjdYp7Z8Fnotqk5f2Dc94Om1tVCbRhzdlX0uskJXvJmMWg+mfk/Co76Ol1uBMHoY8au02HJ8HntSBlfIbAUR6EsU3ghQyh9r/CgapwDZGhfcj5VcHthPGfuysQW0J5poc0hlxWYM4+cnUDL6vYZlt7KY01IEQZCjVjcFYZen10045J3q4xU/erDrCRVC5WM/FzvGkmQ2EJd6Ia6SfRvHgtTs4Zm198YzY1nY5ZkrFwZ8zQtvmTvhoOc69R8W90P00nuySLOU52G6JVG9doaQtslbo61T9Ulyc0dFxUcQozuuiZlKwAQVHTeSs/di/zF2MMcY0yqxD7djS3YhvW5dEVpSmQEeFgDjJ1MvokwdjxsLJGTAg25cKhsbZwWD64H5qXiliLqVqw2FqsiqkYJJ9Cf6X7Yt9bLCBCihbhHAS/lfddx7NOm3Dw7ZwmpcaQwBsnGOuRCwQfJo2kZeWssOG3PFWdt7JsZ3m+VTYmprJfogmfp5U0C/oZ0JJfwEk/I/p4G9JqeaeqFMKG7o5lSGKabKs5rxycB03NOdidnQdIOECCfM/rqimFLc8UUk= X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: c8e1aacd-8365-4c0d-d3d0-08dc47e9ea82 X-MS-Exchange-CrossTenant-AuthSource: SJ0PR02MB7808.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Mar 2024 07:55:16.8761 (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: k41f+zYPjujUshAfbGAlQSDH1In74X9MifK1Y+i4y75QOEPFXvsrE9mUPRz8LaNNnFaQ2oSb3U6cx1l+oiAbp5NHNV3m9U+3zIIxdSHYLGk= X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR02MB7788 X-Proofpoint-ORIG-GUID: 0D0auSm2MQzYFNg-zx8B3P1ixMtY86P2 X-Proofpoint-GUID: 0D0auSm2MQzYFNg-zx8B3P1ixMtY86P2 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-03-18_12,2024-03-18_03,2023-05-22_02 X-Proofpoint-Spam-Reason: safe Cc: huzaifa.c@nutanix.com Subject: [ovs-dev] [PATCH OVN v3 3/4] northd: 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 --- northd/northd.c | 265 +++++++++++++++++++++++++++++++++++++++++- northd/northd.h | 41 ++++--- ovn-nb.ovsschema | 19 ++- ovn-nb.xml | 39 +++++++ utilities/ovn-trace.c | 67 +++++++++++ 5 files changed, 409 insertions(+), 22 deletions(-) diff --git a/northd/northd.c b/northd/northd.c index 2c3560ce2..870427fce 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 | | | * | | | | | @@ -8555,6 +8559,85 @@ 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) +{ + 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 ds match = DS_EMPTY_INITIALIZER; + struct ds action = DS_EMPTY_INITIALIZER; + 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_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(&action, + "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(&action), + op->key, + NULL, + &op->nbsp->header_, + op->lflow_ref); + free(server_ip_str); +} + static void build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, const struct ovn_port *port, @@ -9156,6 +9239,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)) { @@ -13636,6 +13726,165 @@ 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 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; + } + + struct ds dhcp_action = DS_EMPTY_INITIALIZER; + ds_clear(match); + 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(&dhcp_action, + 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(&dhcp_action), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(&dhcp_action); + + 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(&dhcp_action, + "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(&dhcp_action), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(&dhcp_action); + + 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(&dhcp_action, + "drop; /* DHCP_RELAY_REQ */"); + + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_REQ, 1, + ds_cstr(match), ds_cstr(&dhcp_action), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(&dhcp_action); + + 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(&dhcp_action, "next;/* DHCP_RELAY_RESP */"); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, + ds_cstr(match), ds_cstr(&dhcp_action), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(&dhcp_action); + + 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(&dhcp_action, + 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(&dhcp_action), + &op->nbrp->header_, lflow_ref); + + + ds_clear(match); + ds_clear(&dhcp_action); + + 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(&dhcp_action, + "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(&dhcp_action), + &op->nbrp->header_, lflow_ref); + + ds_clear(match); + ds_clear(&dhcp_action); + + 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(&dhcp_action, + "drop; /* DHCP_RELAY_RESP */"); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_DHCP_RELAY_RESP, + 1, + ds_cstr(match), ds_cstr(&dhcp_action), + &op->nbrp->header_, lflow_ref); + ds_clear(match); + ds_clear(&dhcp_action); + + free(server_ip_str); +} + static void build_ipv6_input_flows_for_lrouter_port( struct ovn_port *op, struct lflow_table *lflows, @@ -14906,6 +15155,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 @@ -15670,6 +15926,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); /* Build Logical Router Flows. */ build_arp_resolve_flows_for_lsp(op, lflows, lr_ports, match, actions); @@ -15699,6 +15956,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, + 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 3f1cd8341..0a349c8f7 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -437,24 +437,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/ovn-nb.ovsschema b/ovn-nb.ovsschema index a9c5b7af5..a616dbd6b 100644 --- a/ovn-nb.ovsschema +++ b/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", "version": "7.3.0", - "cksum": "3546526738 34483", + "cksum": "3858903371 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 e0b983ed6..6f0210325 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 @@ -3059,6 +3066,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 @@ -4372,6 +4384,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/utilities/ovn-trace.c b/utilities/ovn-trace.c index e0f1c3ec9..dd7016fc3 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, @@ -3216,6 +3273,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);