From patchwork Tue Mar 19 19:17:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naveen Yerramneni X-Patchwork-Id: 1913759 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=F5ph1Ucn; 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=hPOCQA/i; 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 4TzhNr2THSz1yWs for ; Wed, 20 Mar 2024 06:19:24 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 5A8DB40782; Tue, 19 Mar 2024 19:19:22 +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 kMhV3-7x5TdJ; Tue, 19 Mar 2024 19:19:20 +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 2892D40557 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=F5ph1Ucn; 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=hPOCQA/i Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 2892D40557; Tue, 19 Mar 2024 19:19:20 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0CB6AC0072; Tue, 19 Mar 2024 19:19:20 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 34129C0DD0 for ; Tue, 19 Mar 2024 19:19:18 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 023C34077A for ; Tue, 19 Mar 2024 19:19:11 +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 MMbigqPMuJFp for ; Tue, 19 Mar 2024 19:19:08 +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 A8BEC40743 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 A8BEC40743 Received: from mx0a-002c1b01.pphosted.com (mx0a-002c1b01.pphosted.com [148.163.151.68]) by smtp4.osuosl.org (Postfix) with ESMTPS id A8BEC40743 for ; Tue, 19 Mar 2024 19:19:08 +0000 (UTC) Received: from pps.filterd (m0127839.ppops.net [127.0.0.1]) by mx0a-002c1b01.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 42JHuGRU020457; Tue, 19 Mar 2024 12:19:08 -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=MorUuOa1Wv4FcbYa6Mcjs9935Lf8Wz6At08MO4sQI qQ=; b=F5ph1Ucnp15tQtNS2RxRb7FRIbyBMwWCaPfCcF9RTjDE+ecbA+xSgyv2H Qof1q2mkvrI8GPskAIm9nQVTOaPqtZ0y211S6aFM6Hr0iaFcFfZd+yIuNoH2boDC PyrEXS7bI/Pn0Nee6GGvV+aRkGMw3waY7OagFFvX1qnmSnYWwR46mmyNfqtgiSPc VzYM1dME6syGUP8UU3kfnAlJsb3JZMT9YlroLTrfltF/kyHwxGIlHEH1gfJn0yV9 VJMOIzVJSdZ1+dY97SS9xI3CVQgPkE4sWV8EmeC00Lu1CDfN1BpecNmAuPtL6FTW dbp72uyrgbt6xzzkZ/9fzbpcLTb9Q== Received: from dm5pr21cu001.outbound.protection.outlook.com (mail-centralusazlp17014044.outbound.protection.outlook.com [40.93.13.44]) by mx0a-002c1b01.pphosted.com (PPS) with ESMTPS id 3wwagdequm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 19 Mar 2024 12:19:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ETx7bkzCEconZmfaOgxl4NdwFkpHMx3mu0srlkpjCsfNUZGKa0y0NS4wrUAkcs+FcqfuCrQ8E6FXGvxGkUm5xex2VYRA4K5W63jlUMNyV31eWJv9LCEOppcSJyC4fUSgi7/SfnqDkRuwAXMmFGMeb2fYmez+V6jfZu0hmczxUMLA7yM+B8xavo9m7KvkJlYD9xdDARhdNh4qiU4LldY2B3sAP0T51PfYIidt9uSYGkZFFAlIp+RhMHxY4/4wO4JUOFqgj205FqoPwRzVyTk5hMl+WRW8Bv1K13sPMYBNxxDlJDTErwVLIpyu2kZU0K0wUr+m3yFFitu/46jjYTxlYw== 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=MorUuOa1Wv4FcbYa6Mcjs9935Lf8Wz6At08MO4sQIqQ=; b=b+i7YcGloDc1w+rApR5AXk4eiTCab/73adj1VCZvmW87P/takl6InQHGZ5m3fKii5NPwxyybc/5KYgQGJmZQQfTi4VpS28f4B7sxNrVAopDS1l46uXPZX7QChz28xdJfiyoSVxsuTZg1nFNPnz9PfoeSzlXMORyPn30XHPitJw0QCOJgU/4lKx4FvEQ5MLRWucJgUpdQ9YWVJSP2ED3r38yhW44O4uBcdJxmA6QG8tR81Vzk3Jh6Ar9jrVVyvJbNUQanSn7ozA7GA6p62JKuLUvjPbh3rb7bkxI7d45nFjokaCbswJfq2KVA3HSKPzqpJPVGYMPbZ/DJxDmjJev2oA== 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=MorUuOa1Wv4FcbYa6Mcjs9935Lf8Wz6At08MO4sQIqQ=; b=hPOCQA/ivU3gkQmrNmSIQdD7tYXRu7HC/JUTYzUYTlZgR2uk6uPusk6IjvlNqvRTEdfPliDneOb1WXbqsy6IfgWEkUZS2CB0gZaMhAxSmERVnjEBbpLqdbykGKUuq4pU9GCze5KCNn+FxwPE/RCx2WEJljf+nh/p+J/+htXmUd33KkSiP/xGoO00KBeiiGHQDLGPAu6tjGt/e2ngyFuE7UmiUqV/E1D633wyGC0y0Xj9QMJF+QUKqtuUfg3ACY7C835KN+dSvjRrw7oWebOea6W3iJO0EZZfMcZnPtNIwIhhSzVsEWgbh0hJRzULhbx0rSRYTkr/yBKoVDjLNFD5hQ== Received: from SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) by CO6PR02MB8770.namprd02.prod.outlook.com (2603:10b6:303:141::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7386.26; Tue, 19 Mar 2024 19:19:05 +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 19:19:05 +0000 From: Naveen Yerramneni To: dev@openvswitch.org Date: Tue, 19 Mar 2024 19:17:25 +0000 Message-Id: <20240319191726.165359-4-naveen.yerramneni@nutanix.com> X-Mailer: git-send-email 2.36.6 In-Reply-To: <20240319191726.165359-1-naveen.yerramneni@nutanix.com> References: <20240319191726.165359-1-naveen.yerramneni@nutanix.com> X-ClientProxiedBy: SJ0PR03CA0097.namprd03.prod.outlook.com (2603:10b6:a03:333::12) To SJ0PR02MB7808.namprd02.prod.outlook.com (2603:10b6:a03:326::16) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR02MB7808:EE_|CO6PR02MB8770:EE_ X-MS-Office365-Filtering-Correlation-Id: 732ebbd2-9d98-45b2-7973-08dc48497179 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: OyPoK+F59H1yqhZ8lhbvaKS01u5H13DjFGJQVAee69sYbHAXZMVMku8cffwbmPYS9Iihv5+8iigtlnwi1+pKmKFyFvbOR6L3ewvwnBrkIc6g87caJ9S9hEAlLBSqyqTBIl3u7slT/gaKDrIl0PzFo5p7AJfD9YkVE2tWDKCvjEiyhjI+pVx2ukxT/kdGTJeRh4w/V1FrE4YGLEoaU9/AbsVEmj55XoZA0Gyh4wi2LxmebLudfnc84F1nxdro7hPs6qO4ihIwTHVkymIWNN3cslQiJhGySyhQtvzhJxko2uNSpcqjO0KobESraqQoe1LNjo10b7zWqGvWK7NJ5SHx6gokt3IHY5k6HI0dCmy1gjmoWR/Fk/Uc5JstBxRvjhH7Vn3jM4guHstw/K7tN0JBHVlKZAPqRmuKtvhdPydqGTKRGNjuxVCG6YrrO/lNaIY40dpKt20PhIBzTnss5be14hqrWz71+lFLm7BA4gS4W3vuy51mWE3+yuLv949Eqrws2MEg5vlb98jybo67/tNNXemCb4NQ4s0yD9YK+paDkdla2Q8IbZjWaG1PLO5C0oJl+QiBnoGCZi5ipZY/7Yuw3v1ce9MorWFjI59fOQXjYe7d0nmaf1K+e9kTadrP6h+EPIFSrhkyzE/jHvjpw35vWqqiIVyUn2duR4Zv67498Wqb0HhgIfR0C/ZsjCUrkRsHJyXhMebW7ubx67h7T0E6/NAQTK4X3F8ClY/L0+lxdrs= 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)(376005)(52116005)(1800799015)(366007)(38350700005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: oiNzuZfU4MGQSeaJYfgy8OsqdqQKNJAFVjR+q4QN+1aGKyKPCtFIMDuDBoFVKinEtMkP9Xsn/5GYaHwwL7QbhBG2Bs9pCwPemX1saMFirOBSO8BGGmfs3gn4JVFZrMVZFeAPiVRxSFiYezVF+8ZTbrqP9vggVO0/DBVNWtzxf0SAML866ybFp8xAiQH3VwHt4Q13ebWwzpMFH7i57VlKBzRKojYEAVu2Xz08OOv7sLnxJkg/z/C3K7XUNTKWjK3wcCTYwV2BEFHnZUB/dwfuCBsyEnRTshQ8lZeG25Omujh2on20kznkypd8xTLq/TgWtFo6hi7oFRZ3P4fMTSLXkggv6HQqkmAlaA76+Dy6boJsJcm476SEhV6yD/ZqwwKsKzVRWH1R3ytTAff9Vi8jZM6psRf7h1P6c3wxJ8mjA5HXeCtkP/b/mLnj/3O16SMAos50hUDMe4qVY66Arb6BUPh5BQiO8DvOCM6k3nFzTstwqXv/aOOG6m3GTZhV4h3+UapqG5eTdEMARQmhsicUPyDhX4CeSYoQoT1F+kXDHGvvYM4FRSiEdhQI4LgQ9HCjLMaOwMjuSY0JMp/VW5IDe8LYxD0xbwjyd7Dy4AQDaoN4EsVTTaMBH4o/AOnBG6Y5IZQgUZuMAHcJ3E4e2N+A84uVtzEuIoJHqztcW2xdiFFokN1CVfAWgJx/3UYNc0+wsIT1QwI+NW30bXTxnZHqQ3JSHkH9c+sK9gNTn6Zg5aj3TFBlp9Y/9I5Yy4o7GoinVaZlbuVFBmNOrUtuwiIMgOdbgeC38MorBzA8TJ9vBLeYq2omh1vqQiMUf/+oEKkgiJHHfSfsP9uZClaV3gX+d4Skl3ihY0c8CUusKu5PApzh1kOkCLYi5Z/SzieUDtzIjpBseSOwlM2mnxNUvpt7ooBV5Gfa04eg4i4cPVmh/FUs13z1MA4eyHag3Sfxg8/PKeHj9AcWkpSVZa/H38yFrbDfPmDDx181El9gKu2Xw8moeHjn5kM4CeEnVN7AUZTA9F68tIWfdu+5GO0uHf+aS6c1oJ6EAax+xmm9z/hQ7/FX/GKTEjZr5QsmR0hcl4u2gwkj4HuCTLlAyTCtwTlY67VaESspyGaUz6pXfAv9dadch2del4crKzuhcq6Pdf6S5NkMzMR7TAhJXb6ZpNejzhN1CUsKvWoWxvFpECU4mtZ+a5eV1ICEo3NSVHPmsq9pQMa4YAzjgiwmPIqFaEmUk1itY9rn7P7vWgLMJixXohaijRLd0S+N3wSIdEeWpt+edwtXbFW9/tm5atrVbkdGdBH0s8auSNjGK9+nYQpiIkCdrvZaBkCp0Cb2e0eyywrL02MWiR4Xg6V63gdghJCwTXU9ahEdaWL8vTYkpK17iKanHpblhM0fKcm2ePQVazFjNy+J/tkwmnP8xkVVe/UkyaEKTFhwvONVoRbtRvmp/Rsh78ijWhFftwPB/EaZ8eavrBpAL+fUtr39oDvhkDDNqTyEjoEsIjnONSDYloAu199BbR2JKYmzrPTvaHxQkpkJ9KsKAeNNON4fYUceNzOiERAh1LstHEAD4Lp3E1QEan5zFFlAjozbeZOQvQjU9Ps7ej7f6w8eRrdeIHoeizwxjEzmKaC0bzbwkXmvDnoVFpY= X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 732ebbd2-9d98-45b2-7973-08dc48497179 X-MS-Exchange-CrossTenant-AuthSource: SJ0PR02MB7808.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Mar 2024 19:19:05.5403 (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: CMBNadPb5LUV86f6hYfX72d9enlpEyoZCUg0MOV/ZwLCXZJ61kmdVANjjDdwlrHrQ/UeafjZH/cuXLX7MGJmkZDM7lvmfZ27+DIekYdBTnM= X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO6PR02MB8770 X-Proofpoint-GUID: mRfUwGVtlVoyXnL7_xgKUp-HAdjIuugS X-Proofpoint-ORIG-GUID: mRfUwGVtlVoyXnL7_xgKUp-HAdjIuugS 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-19_08,2024-03-18_03,2023-05-22_02 X-Proofpoint-Spam-Reason: safe Cc: huzaifa.c@nutanix.com Subject: [ovs-dev] [PATCH OVN v4 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 Co-authored-by: Huzaifa Calcuttawala Signed-off-by: Huzaifa Calcuttawala CC: Mary Manohar --- northd/northd.c | 265 ++++++++++++++++++++++++++++++++++++++++++++++- northd/northd.h | 41 ++++---- ovn-nb.ovsschema | 19 +++- ovn-nb.xml | 39 +++++++ 4 files changed, 342 insertions(+), 22 deletions(-) diff --git a/northd/northd.c b/northd/northd.c index 1839b7d8b..33641218d 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)) { @@ -13611,6 +13701,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, @@ -14881,6 +15130,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 @@ -15640,6 +15896,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); @@ -15669,6 +15926,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 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