From patchwork Wed Jun 12 06:50:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felix Huettner X-Patchwork-Id: 1946666 X-Patchwork-Delegate: nusiddiq@redhat.com 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=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=ywWPjEuO; dkim=fail reason="signature verification failed" (2048-bit key) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=ywWPjEuO; 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 4VzblX4C5Kz20Pb for ; Wed, 12 Jun 2024 16:50:32 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 3A0A2406F9; Wed, 12 Jun 2024 06:50:27 +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 3ZW0Sf0j-xNQ; Wed, 12 Jun 2024 06:50:22 +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 092FC4058B Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=ywWPjEuO; dkim=fail reason="signature verification failed" (2048-bit key) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=ywWPjEuO Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 092FC4058B; Wed, 12 Jun 2024 06:50:21 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id C333DC0012; Wed, 12 Jun 2024 06:50:21 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 323FAC0011 for ; Wed, 12 Jun 2024 06:50:20 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 1746E81F8A for ; Wed, 12 Jun 2024 06:50:20 +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 C4dxnsRqZLUH for ; Wed, 12 Jun 2024 06:50:17 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2a01:111:f403:260d::600; helo=eur03-dba-obe.outbound.protection.outlook.com; envelope-from=felix.huettner@mail.schwarz; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org 8488481EE8 Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=reject dis=none) header.from=mail.schwarz DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 8488481EE8 Authentication-Results: smtp1.osuosl.org; dkim=pass (2048-bit key, unprotected) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=ywWPjEuO; dkim=pass (2048-bit key) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=ywWPjEuO Received: from EUR03-DBA-obe.outbound.protection.outlook.com (mail-dbaeur03on20600.outbound.protection.outlook.com [IPv6:2a01:111:f403:260d::600]) by smtp1.osuosl.org (Postfix) with ESMTPS id 8488481EE8 for ; Wed, 12 Jun 2024 06:50:15 +0000 (UTC) ARC-Seal: i=2; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass; b=m5y8kaeugICsZwbt23zLZS4zFqRky556nMoa1gJ7+wlydLYHLXMumbHMLur+lCGXeBvD2UWAZmdKNwYR/ZIT2thlLrdTBQUZB+CbypmznpB6sK3SbynbJBV4jRqFiyQNzcCjc8ga54DlO+xMQZp8mBar9YW3tU/N42UckjL1Q9tkEUIcXziZpmXyGIkJ7pMZqrgbHMpg4xqyOePiQCz0tpdC+jSfBkyNaVMLtzCBctyH9hY3G4gfWaKGExwh0T344rdzqlqwdJhSoI0UajaHGmPvo41Jf6bXjf3NPt0pxm0ag1D5o8g55QC1CwKPyZsiXdhOuMzRyI2UhgxGAhNANA== ARC-Message-Signature: i=2; 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=03EFRSF0ZW16El+RrBYZUWZe4FVaTOCcrAFl6qZ3T5Y=; b=jdqt9PDMMvl3UKHfG4EJrIi8sqfiE6fuK/lWkZzfqelZLHae/R7o51Mp4PF0alAii+LxNCctzLUFsg7StLZ8Uv7rs7cB2E2nXMwZX85q8VXdS+YiyREADhviqNmkIWE62+qVDsHvScdOKHodupHG1DP9KFNK3YyKiUPRZ5/bKJilpY288qwRcbNvOiRNdZY5re5FWQ7hHAJkBA9fslSwYkPZmovKjv/9rqgSVl6aVwO5i4VMG4lEyG/hrHbyB5sGx989FKV0EqQB5mrV+A4kCb5lXYIA4miyVtRJaZg19ODJGHKTaGGwoK9QB35fqZg0rOeOnazucB3qCOZlL3FRGQ== ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is 52.169.0.179) smtp.rcpttodomain=openvswitch.org smtp.mailfrom=mail.schwarz; dmarc=pass (p=reject sp=none pct=100) action=none header.from=mail.schwarz; dkim=pass (signature was verified) header.d=mail.schwarz; arc=pass (0 oda=1 ltdi=1 spf=[1,1,smtp.mailfrom=mail.schwarz] dkim=[1,1,header.d=mail.schwarz] dmarc=[1,1,header.from=mail.schwarz]) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mail.schwarz; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=03EFRSF0ZW16El+RrBYZUWZe4FVaTOCcrAFl6qZ3T5Y=; b=ywWPjEuOPBqesh4diAs/uj9vt5N+g5gKN9eN+zgeltOXd9wC72AqM6UTtjycLvFGT7G52gLuzS2x/xlLv5Vn3vpTeagVvi5EDDesW8nmKWehK6/tpYvca9+WE7pbXYyyzq6iwXD5TNNo+fsTDk3f88urIyg3P0EEhIgXKLXvRo7VATvn2DL32E5D6v822r0nFWPzl4l4WPpAm1y5CSr0rpA8KwdvDQ9j3/CByE5T0TPF3ZW15g78uvxEajOFTYqjBzHaF7clhXm4aVA1k3/0IwxOUWJj3F2BZtEZkIGSyHetd/klKpYw6u7uAmclcbdabn43pYr0Bhx1KSgDEdSqeA== Received: from AM0PR10CA0107.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:208:e6::24) by AS8PR10MB6532.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:20b:565::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7677.20; Wed, 12 Jun 2024 06:50:11 +0000 Received: from AM4PEPF00027A6C.eurprd04.prod.outlook.com (2603:10a6:208:e6:cafe::60) by AM0PR10CA0107.outlook.office365.com (2603:10a6:208:e6::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7677.17 via Frontend Transport; Wed, 12 Jun 2024 06:50:11 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 52.169.0.179) smtp.mailfrom=mail.schwarz; dkim=pass (signature was verified) header.d=mail.schwarz;dmarc=pass action=none header.from=mail.schwarz; Received-SPF: Pass (protection.outlook.com: domain of mail.schwarz designates 52.169.0.179 as permitted sender) receiver=protection.outlook.com; client-ip=52.169.0.179; helo=eu2.smtp.exclaimer.net; pr=C Received: from eu2.smtp.exclaimer.net (52.169.0.179) by AM4PEPF00027A6C.mail.protection.outlook.com (10.167.16.90) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.7677.15 via Frontend Transport; Wed, 12 Jun 2024 06:50:09 +0000 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (104.47.14.49) by eu2.smtp.exclaimer.net (52.169.0.179) with Exclaimer Signature Manager ESMTP Proxy eu2.smtp.exclaimer.net (tlsversion=TLS12, tlscipher=TLS_ECDHE_WITH_AES256_SHA384); Wed, 12 Jun 2024 06:50:10 +0000 X-ExclaimerHostedSignatures-MessageProcessed: true X-ExclaimerProxyLatency: 8160093 X-ExclaimerImprintLatency: 1995548 X-ExclaimerImprintAction: 08fbb61093a44940a63269aaf0e18d8f ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=kd40FUcB6fi9P5b9aw5FsdCerpOIGvJM/BuoEFB860ite1iPpGk6ugODq1/BQr/xR4hnOhGAe1Qasg4RjlWLM7Nz6u0pJsTR1CR5zL+fjVLKqHHUfoiBlZzL18QugFFw9erE+lw6aQacQscybzjqjk/wuGuBxz+WunSs2uMWxunU/hLoMlY4+krZ/tJIjyfcLT/Nk4EtQCEtVdOR2kH1b23Df+QVUrSmIKiOfP+4Y+JFXyPAqgn4tLzG1u9hfpAGXTHnVlRtswxIN5PJKB8vEJzSwjFnbSVLwKvwzy3ephl3EidVkpO995grykHLoUf6BJgULO1FY0oW/JsPmNeTxA== 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=03EFRSF0ZW16El+RrBYZUWZe4FVaTOCcrAFl6qZ3T5Y=; b=CZYgNiSNzz6PODHg2qVxdRIBe3IN9BIMV1UUPWmluvB78n9HdsiLROk6+EZL2TTd2XAFX3hD3CqSssJmpNWIl5hLk6/jWjUSi4ih5t1slaVqZaaFnIjahhP5OP/vnGPDLNIwniMNPoCm7xEaV3mvNRxiIDgt2MIFttXD51FoK39X3o8Dtm/dHoozqnTIlkp7kgAywAN44SmPIY+rIPYEhqOg0wtzJ365vmv9GcOMpgc3/dGC9IoMbHfdzbFPPqSB8eUv9u+JTOnbxBkxZS5HzTMh/WPC1CPMoNUKYJx2++v2+mOdtgH56jLR5/1HocvIjxLzRFJMhYjaROGPp+fUiQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=mail.schwarz; dmarc=pass action=none header.from=mail.schwarz; dkim=pass header.d=mail.schwarz; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mail.schwarz; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=03EFRSF0ZW16El+RrBYZUWZe4FVaTOCcrAFl6qZ3T5Y=; b=ywWPjEuOPBqesh4diAs/uj9vt5N+g5gKN9eN+zgeltOXd9wC72AqM6UTtjycLvFGT7G52gLuzS2x/xlLv5Vn3vpTeagVvi5EDDesW8nmKWehK6/tpYvca9+WE7pbXYyyzq6iwXD5TNNo+fsTDk3f88urIyg3P0EEhIgXKLXvRo7VATvn2DL32E5D6v822r0nFWPzl4l4WPpAm1y5CSr0rpA8KwdvDQ9j3/CByE5T0TPF3ZW15g78uvxEajOFTYqjBzHaF7clhXm4aVA1k3/0IwxOUWJj3F2BZtEZkIGSyHetd/klKpYw6u7uAmclcbdabn43pYr0Bhx1KSgDEdSqeA== Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=mail.schwarz; Received: from PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:102:30d::9) by AS4PR10MB5272.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:20b:4b8::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.37; Wed, 12 Jun 2024 06:50:07 +0000 Received: from PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM ([fe80::f00d:feeb:e45e:54f8]) by PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM ([fe80::f00d:feeb:e45e:54f8%2]) with mapi id 15.20.7633.036; Wed, 12 Jun 2024 06:50:07 +0000 Date: Wed, 12 Jun 2024 08:50:03 +0200 To: dev@openvswitch.org Message-ID: Mail-Followup-To: dev@openvswitch.org Content-Disposition: inline X-ClientProxiedBy: FR3P281CA0110.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:a3::7) To PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:102:30d::9) MIME-Version: 1.0 X-MS-TrafficTypeDiagnostic: PAVPR10MB6914:EE_|AS4PR10MB5272:EE_|AM4PEPF00027A6C:EE_|AS8PR10MB6532:EE_ X-MS-Office365-Filtering-Correlation-Id: 874cdfdc-f13e-4c67-0de6-08dc8aabe736 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230032|1800799016|376006|366008; X-Microsoft-Antispam-Message-Info-Original: 2CQt3KQQpqZrJ8MJq9vYOv8nDPC7p4uW1yUDzoGrIoXnGoOtihcT8vNVftY4izpGiv82x6QWWNJt++aIWN7ohlO2sJ+nrFKZ3h8jd2Lrcbwm8ocLDNCgvfYJFzU2hjN55EXBTv+WgHjJWsVpYDaJLSMws9urDthNKyK56L5SbXSBCtOpQV9fk43k/rYpP7cC6upUAKGnvL5bTuDgSbgje90Wsuz5OOULGuQbDs++BJdrTFcs1OtNxejkAbDWeGjt7VETTKuGEoYaNaKupZy4+9csye5sUJE87iSYGw6TkrcS+8NT+5Lnv2SF+qMeNRQ7RW2dsZX0lDPjLKPZsobXT8cKPDHEA8Mb5hKf9X4BClAr/LmhBFJitfZ5eofB78OQFR808RFm5zizhxJMYKeEA6mx1RFzDOMDQEOvBPgtSW9nMuMdtoWqVMu/A+BWrgkF0w3o+vJmJNDuSAxKqCdZqNtsU/Qa4XMnp8m9w33DyZyFET9kOs2e63eWICqo4Z/P2LDg5aS657g2x2d9TV+SnjwTGFLLtont+eawl5tdqRjMVY/dSb+HYFklZIJ8NnnWbUicmexzxex/9/OSYKNXfCGa5kemBzlXwpMxU85MNAvegOWpQntlwzcWY+IaQOOOEAHgdnayphnXhPwOdotB/20UVJJiShKZpJ8CEQf5vjUEXO3E4PKcUhKqyf0TmIofH9XWbksMgSQ9aHqn82Ylfo6cKKNjTU5x4BQwIs3BnCXfpvswWx4btDy7WVO/+Ie0A9wmYg3T1ZkfzaRS/tWVz3Nmvk+ot5TrZZ2pDhD/a3XOvibEOOEGGW9PMttQQqQDKJ6By4j1dtp9uADa1NRx2RfKEdnL2hPlHgzAFMQsWv1fpENLwhKeg6FZRUlpWEATHV7iKPNOMrh7gtcofhoc3joHJqd8iCKDFA/tOe6Z/RjcW3/wlCehyDT2ZUR6TSHkIXoCtX2D98S1h5Dr+xgO+s9F6scCoxj/n2u6gMtXM9MNjmohutB1Se7mVBMx7WDu9NtGbc41gmX3KKkUiXkaW+p/pfJ5iJqhkQZBGhzn41K8g6w9iF5rA3CG0G7J/nE5QJebMCiSurYBihKbFDSLHSdRHvqBLbdHl8j9Bjk/+03RVM5enSMyEzpCUyONCKB85uUMPkLGoSqYgsGqn6s4ma4hWfo1Cf/jDpN3XQJdeu9fyyp5MStDVl6v3Ig8XnsNC3s+TjbeTYlDNGsIcCjAm0l27+77yqDZninQYsrTMXQl5twvUWYqWLWtM9YWF8yKOWinXE18atlavhmt8a2d4XfBMFol5TzS57B3r/wQGhDi5l+IHHq/RAA7aKoCsIX9 X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM; PTR:; CAT:NONE; SFS:(13230032)(1800799016)(376006)(366008); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR10MB5272 X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM4PEPF00027A6C.eurprd04.prod.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: ce9734e0-6b97-4bf6-7581-08dc8aabe4b8 X-Microsoft-Antispam: BCL:0; ARA:13230032|376006|35042699014|36860700005|1800799016|82310400018; X-Microsoft-Antispam-Message-Info: 8IifZ4MS6z1NCsq3TOvaBp90F1dxbr0t96g0LYR2zeDvKStAbDtY5+Rd0ighgpO8f3cUkBE3bp+ttTPZp8FXS05riw6WLsfKWGyKCK8Y3IaLVGxdnYkcZpUqOqLlwft9V6BlODjyJIlBBg/ZovABCIC6MVNBDS0CnTbVaB45HJ0r4z2itYhmrnGNGEifGRn1xCcS0xtaYPYmWqt1d3K/MIRN1fGrma4bT0pRuMK5dOOVls9xALOQel0NxHPRVyvvXm23ifCe2+IabkpkEgUbHNfxXncPi/zYUhoVktgdXJCrYJ0Wmttq3YnF5QDMdAwQL+IJ9ZMSLcVT9XeOaw08pXVwHulqX0Eie0MTR9+ZG46BMlUZ8sL598BYdjd/h5B/dhloSd63jLHktaC1KM6WO1WeDVQJtRD9SIUP3jCsDec+0utcFCitssCMkbtvQBd3lsoNYVtYR+cbYs1hrxuDcg2OPP8095wHb7pBOCsOZs0lh0VUl2uj0rI9MECCrfYTutosg8QGySdHNDD9KPlJEJdprWor9zYXBOUyHAKT3r0o578/Z6pbIbniN/2tr3zSrjVepSeBsg+CeOuze/ph1+Kr7bo/Z6nFpdC82Lfz4vC/LxV3wirnMWbeUIIrcUjNn+0PQ1elkAWdy+dOFCi+Z+fp1mfuAchbvHcwhe++oZb/W63QMuLJpEjJ/FFgdYydkGepA6wFBxl7kddU08rYA+Sn9Hxf9uuW6R/pWP34HCgjPQfva9zVvvNBCFkMmeE6dGJ6aPYM54tslktzSQ+aoyohuxq7DrukxjZENkIYvrDXvlmC3VnjY5O2P2mxcxSjkXjQoL7karLgASZpamZCana5XbByCaKHM1/F0IfoseSpb91Q8qU8+v65v4wVCYdDaaXxM4QAPSXCNlppWtydLBndl5lTtVEhgLVO2txG0cxmN54LKl8upYAiAq6hBLLma8BjnUZ6cK4quy3F1uI2+Vz5WN0AEuTD9wkIHd1LzYBfRK7Pk2b57x9iUl9/cdPu1TnKGL6DPRNz2YWuqVDKTq7W9ypDhnk5Ek0wA1xhYtIBMyFuMU5XsCuDJzV287MELxqCDwXd8rIliUMiOkfeUCM0ZZngEHlfPB4X8o3ZQV7heYzGIFpc78XzKxN89KHF5KaU6zN8KIQtAjsbmrpCa0Iyna1goHUuf8TSUghuqsEjmha5DGeHynQpyID5upX91UNesWpP8KibgTBs6tqcLiLLuGY9Muw2BtRxjocT6yU2NgeG+1qcDQtYVbOCP4w5Ri52tCWBnUdcZES/TBkATVuc7tRLzXaVmxUMN+NSBV6xBthmYZSJ9Y5C2BWKyQPdIIKsbLgjf2vjJIYRTyzoMCSqF0SDnFNC5Ict73h9ibL1G9LiIqIydsMZgwE91hAlNTbS4cMBx1ScQw6y49fEMQ== X-Forefront-Antispam-Report: CIP:52.169.0.179; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:eu2.smtp.exclaimer.net; PTR:eu2.smtp.exclaimer.net; CAT:NONE; SFS:(13230032)(376006)(35042699014)(36860700005)(1800799016)(82310400018); DIR:OUT; SFP:1101; X-OriginatorOrg: mail.schwarz X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Jun 2024 06:50:09.8981 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 874cdfdc-f13e-4c67-0de6-08dc8aabe736 X-MS-Exchange-CrossTenant-Id: d04f4717-5a6e-4b98-b3f9-6918e0385f4c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=d04f4717-5a6e-4b98-b3f9-6918e0385f4c; Ip=[52.169.0.179]; Helo=[eu2.smtp.exclaimer.net] X-MS-Exchange-CrossTenant-AuthSource: AM4PEPF00027A6C.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR10MB6532 Subject: [ovs-dev] [PATCH ovn v5 1/2] northd: Handle routing for other address families. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Huettner via dev From: Felix Huettner Reply-To: Felix Huettner Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" In most cases IPv4 packets are routed only over other IPv4 networks and IPv6 packets are routed only over IPv6 networks. However there is no inherent reason for this limitation. Routing IPv4 packets over IPv6 networks just requires the router to contain a route for an IPv4 network with an IPv6 nexthop. This was previously prevented in OVN in ovn-nbctl and northd. By removing these filters the forwarding will work if the mac addresses are prepopulated. If the mac addresses are not prepopulated we will attempt to resolve them using the original address family of the packet and not the address family of the nexthop. This will fail and we will not forward the packet. This feature can for example be used by service providers to interconnect multiple IPv4 networks of a customer without needing to negotiate free IPv4 addresses by just using any IPv6 address. Signed-off-by: Felix Huettner --- v4->v5: rebase v3->v4: - additional tests - add additional regbit for nexthop address family v2->v3: fix uninitialized variable v1->v2: - move ipv4 info to parsed_route - add tests for lr-route-add - switch tests to use fmt_pkt - some minor test cleanups NEWS | 4 + northd/northd.c | 83 +++--- tests/ovn-nbctl.at | 26 +- tests/ovn-northd.at | 128 ++++++--- tests/ovn.at | 645 ++++++++++++++++++++++++++++++++++++++++++ utilities/ovn-nbctl.c | 12 +- 6 files changed, 818 insertions(+), 80 deletions(-) base-commit: 7b4395969465ffc3bd4b38e6a9796ad38984877d diff --git a/NEWS b/NEWS index 3bdc55172..14345c96b 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,10 @@ Post v24.03.0 has been renamed to "options:ic-route-denylist" in order to comply with inclusive language guidelines. The previous name is still recognized to aid with backwards compatibility. + - Allow Static Routes where the address families of ip_prefix and nexthop + diverge (e.g. IPv4 packets over IPv6 links). This is currently limited to + nexthops that have their mac addresses prepopulated (so + dynamic_neigh_routers must be false). OVN v24.03.0 - 01 Mar 2024 -------------------------- diff --git a/northd/northd.c b/northd/northd.c index b0d0c4747..e697973ce 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -156,6 +156,7 @@ static bool default_acl_drop; #define REGBIT_KNOWN_LB_SESSION "reg9[6]" #define REGBIT_DHCP_RELAY_REQ_CHK "reg9[7]" #define REGBIT_DHCP_RELAY_RESP_CHK "reg9[8]" +#define REGBIT_NEXTHOP_IS_IPV4 "reg9[9]" /* Register to store the eth address associated to a router port for packets * received in S_ROUTER_IN_ADMISSION. @@ -265,7 +266,8 @@ static bool default_acl_drop; * | | LOOKUP_NEIGHBOR_RESULT/ | | | * | | SKIP_LOOKUP_NEIGHBOR/ | | | * | |REGBIT_DHCP_RELAY_REQ_CHK/ | | | - * | |REGBIT_DHCP_RELAY_RESP_CHK}| | | + * | |REGBIT_DHCP_RELAY_RESP_CHK | | | + * | |REGBIT_NEXTHOP_IS_IPV4} | | | * | | | | | * | | REG_ORIG_TP_DPORT_ROUTER | | | * | | | | | @@ -10084,13 +10086,15 @@ build_routing_policy_flow(struct lflow_table *lflows, struct ovn_datapath *od, "outport = %s; " "flags.loopback = 1; " REG_ECMP_GROUP_ID" = 0; " + REGBIT_NEXTHOP_IS_IPV4" = %d; " "next;", is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6, nexthop, is_ipv4 ? REG_SRC_IPV4 : REG_SRC_IPV6, lrp_addr_s, out_port->lrp_networks.ea_s, - out_port->json_key); + out_port->json_key, + is_ipv4); } else if (!strcmp(rule->action, "drop")) { ds_put_cstr(&actions, debug_drop_action()); @@ -10185,13 +10189,15 @@ build_ecmp_routing_policy_flows(struct lflow_table *lflows, "eth.src = %s; " "outport = %s; " "flags.loopback = 1; " + REGBIT_NEXTHOP_IS_IPV4" = %d; " "next;", is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6, rule->nexthops[i], is_ipv4 ? REG_SRC_IPV4 : REG_SRC_IPV6, lrp_addr_s, out_port->lrp_networks.ea_s, - out_port->json_key); + out_port->json_key, + is_ipv4); ds_clear(&match); ds_put_format(&match, REG_ECMP_GROUP_ID" == %"PRIu16" && " @@ -10309,6 +10315,8 @@ struct parsed_route { const struct nbrec_logical_router_static_route *route; bool ecmp_symmetric_reply; bool is_discard_route; + bool is_ipv4_prefix; + bool is_ipv4_nexthop; }; static uint32_t @@ -10334,6 +10342,8 @@ parsed_routes_add(struct ovn_datapath *od, const struct hmap *lr_ports, /* Verify that the next hop is an IP address with an all-ones mask. */ struct in6_addr nexthop; unsigned int plen; + bool is_ipv4_nexthop = true; + bool is_ipv4_prefix; bool is_discard_route = !strcmp(route->nexthop, "discard"); bool valid_nexthop = route->nexthop[0] && !is_discard_route; if (valid_nexthop) { @@ -10352,6 +10362,7 @@ parsed_routes_add(struct ovn_datapath *od, const struct hmap *lr_ports, UUID_ARGS(&route->header_.uuid)); return NULL; } + is_ipv4_nexthop = IN6_IS_ADDR_V4MAPPED(&nexthop); } /* Parse ip_prefix */ @@ -10363,18 +10374,7 @@ parsed_routes_add(struct ovn_datapath *od, const struct hmap *lr_ports, UUID_ARGS(&route->header_.uuid)); return NULL; } - - /* Verify that ip_prefix and nexthop have same address familiy. */ - if (valid_nexthop) { - if (IN6_IS_ADDR_V4MAPPED(&prefix) != IN6_IS_ADDR_V4MAPPED(&nexthop)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Address family doesn't match between 'ip_prefix'" - " %s and 'nexthop' %s in static route "UUID_FMT, - route->ip_prefix, route->nexthop, - UUID_ARGS(&route->header_.uuid)); - return NULL; - } - } + is_ipv4_prefix = IN6_IS_ADDR_V4MAPPED(&prefix); /* Verify that ip_prefix and nexthop are on the same network. */ if (!is_discard_route && @@ -10417,6 +10417,8 @@ parsed_routes_add(struct ovn_datapath *od, const struct hmap *lr_ports, pr->ecmp_symmetric_reply = smap_get_bool(&route->options, "ecmp_symmetric_reply", false); pr->is_discard_route = is_discard_route; + pr->is_ipv4_prefix = is_ipv4_prefix; + pr->is_ipv4_nexthop = is_ipv4_nexthop; ovs_list_insert(routes, &pr->list_node); return pr; } @@ -10792,7 +10794,7 @@ build_ecmp_route_flow(struct lflow_table *lflows, struct ovn_datapath *od, struct lflow_ref *lflow_ref) { - bool is_ipv4 = IN6_IS_ADDR_V4MAPPED(&eg->prefix); + bool is_ipv4_prefix = IN6_IS_ADDR_V4MAPPED(&eg->prefix); uint16_t priority; struct ecmp_route_list_node *er; struct ds route_match = DS_EMPTY_INITIALIZER; @@ -10801,7 +10803,8 @@ build_ecmp_route_flow(struct lflow_table *lflows, struct ovn_datapath *od, int ofs = !strcmp(eg->origin, ROUTE_ORIGIN_CONNECTED) ? ROUTE_PRIO_OFFSET_CONNECTED: ROUTE_PRIO_OFFSET_STATIC; build_route_match(NULL, eg->route_table_id, prefix_s, eg->plen, - eg->is_src_route, is_ipv4, &route_match, &priority, ofs); + eg->is_src_route, is_ipv4_prefix, &route_match, + &priority, ofs); free(prefix_s); struct ds actions = DS_EMPTY_INITIALIZER; @@ -10834,7 +10837,8 @@ build_ecmp_route_flow(struct lflow_table *lflows, struct ovn_datapath *od, /* Find the outgoing port. */ const char *lrp_addr_s = NULL; struct ovn_port *out_port = NULL; - if (!find_static_route_outport(od, lr_ports, route, is_ipv4, + if (!find_static_route_outport(od, lr_ports, route, + route_->is_ipv4_nexthop, &lrp_addr_s, &out_port)) { continue; } @@ -10858,13 +10862,16 @@ build_ecmp_route_flow(struct lflow_table *lflows, struct ovn_datapath *od, "%s = %s; " "eth.src = %s; " "outport = %s; " + REGBIT_NEXTHOP_IS_IPV4" = %d; " "next;", - is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6, + route_->is_ipv4_nexthop ? + REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6, route->nexthop, - is_ipv4 ? REG_SRC_IPV4 : REG_SRC_IPV6, + route_->is_ipv4_nexthop ? REG_SRC_IPV4 : REG_SRC_IPV6, lrp_addr_s, out_port->lrp_networks.ea_s, - out_port->json_key); + out_port->json_key, + route_->is_ipv4_nexthop); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP, 100, ds_cstr(&match), ds_cstr(&actions), &route->header_, lflow_ref); @@ -10881,15 +10888,15 @@ add_route(struct lflow_table *lflows, struct ovn_datapath *od, const char *network_s, int plen, const char *gateway, bool is_src_route, const uint32_t rtb_id, const struct ovsdb_idl_row *stage_hint, bool is_discard_route, - int ofs, struct lflow_ref *lflow_ref) + int ofs, struct lflow_ref *lflow_ref, + bool is_ipv4_prefix, bool is_ipv4_nexthop) { - bool is_ipv4 = strchr(network_s, '.') ? true : false; struct ds match = DS_EMPTY_INITIALIZER; uint16_t priority; const struct ovn_port *op_inport = NULL; /* IPv6 link-local addresses must be scoped to the local router port. */ - if (!is_ipv4) { + if (!is_ipv4_prefix) { struct in6_addr network; ovs_assert(ipv6_parse(network_s, &network)); if (in6_is_lla(&network)) { @@ -10897,7 +10904,7 @@ add_route(struct lflow_table *lflows, struct ovn_datapath *od, } } build_route_match(op_inport, rtb_id, network_s, plen, is_src_route, - is_ipv4, &match, &priority, ofs); + is_ipv4_prefix, &match, &priority, ofs); struct ds common_actions = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; @@ -10905,22 +10912,25 @@ add_route(struct lflow_table *lflows, struct ovn_datapath *od, ds_put_cstr(&actions, debug_drop_action()); } else { ds_put_format(&common_actions, REG_ECMP_GROUP_ID" = 0; %s = ", - is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6); + is_ipv4_nexthop ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6); if (gateway && gateway[0]) { ds_put_cstr(&common_actions, gateway); } else { - ds_put_format(&common_actions, "ip%s.dst", is_ipv4 ? "4" : "6"); + ds_put_format(&common_actions, "ip%s.dst", + is_ipv4_prefix ? "4" : "6"); } ds_put_format(&common_actions, "; " "%s = %s; " "eth.src = %s; " "outport = %s; " "flags.loopback = 1; " + REGBIT_NEXTHOP_IS_IPV4" = %d; " "next;", - is_ipv4 ? REG_SRC_IPV4 : REG_SRC_IPV6, + is_ipv4_nexthop ? REG_SRC_IPV4 : REG_SRC_IPV6, lrp_addr_s, op->lrp_networks.ea_s, - op->json_key); + op->json_key, + is_ipv4_nexthop); ds_put_format(&actions, "ip.ttl--; %s", ds_cstr(&common_actions)); } @@ -10969,7 +10979,8 @@ build_static_route_flow(struct lflow_table *lflows, struct ovn_datapath *od, add_route(lflows, route_->is_discard_route ? od : out_port->od, out_port, lrp_addr_s, prefix_s, route_->plen, route->nexthop, route_->is_src_route, route_->route_table_id, &route->header_, - route_->is_discard_route, ofs, lflow_ref); + route_->is_discard_route, ofs, lflow_ref, + route_->is_ipv4_prefix, route_->is_ipv4_nexthop); free(prefix_s); } @@ -12707,7 +12718,7 @@ build_ip_routing_flows_for_lrp( op->lrp_networks.ipv4_addrs[i].network_s, op->lrp_networks.ipv4_addrs[i].plen, NULL, false, 0, &op->nbrp->header_, false, ROUTE_PRIO_OFFSET_CONNECTED, - lflow_ref); + lflow_ref, true, true); } for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) { @@ -12715,7 +12726,7 @@ build_ip_routing_flows_for_lrp( op->lrp_networks.ipv6_addrs[i].network_s, op->lrp_networks.ipv6_addrs[i].plen, NULL, false, 0, &op->nbrp->header_, false, ROUTE_PRIO_OFFSET_CONNECTED, - lflow_ref); + lflow_ref, false, false); } } @@ -12951,11 +12962,13 @@ build_arp_resolve_flows_for_lrouter( "ip4.mcast || ip6.mcast", "next;", lflow_ref); - ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 1, "ip4", + ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 1, + REGBIT_NEXTHOP_IS_IPV4 " == 1", "get_arp(outport, " REG_NEXT_HOP_IPV4 "); next;", lflow_ref); - ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 1, "ip6", + ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 1, + REGBIT_NEXTHOP_IS_IPV4 " == 0", "get_nd(outport, " REG_NEXT_HOP_IPV6 "); next;", lflow_ref); @@ -15695,7 +15708,7 @@ build_routable_flows_for_router_port( laddrs->ipv4_addrs[k].plen, NULL, false, 0, &router_port->nbrp->header_, false, ROUTE_PRIO_OFFSET_CONNECTED, - lrp->stateful_lflow_ref); + lrp->stateful_lflow_ref, true, true); } } } diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 5248e6c76..4a219ab61 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -1757,7 +1757,7 @@ AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24 11.0.0.2]) AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.10.0/24 lp0]) AT_CHECK([ovn-nbctl --bfd lr-route-add lr0 10.0.20.0/24 11.0.2.1 lp0]) AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.10.0/24 lp1], [1], [], - [ovn-nbctl: bad IPv4 nexthop argument: lp1 + [ovn-nbctl: bad nexthop argument: lp1 ]) dnl Add overlapping route with 10.0.0.1/24 @@ -1771,13 +1771,13 @@ AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24a 11.0.0.1], [1], [], [ovn-nbctl: bad prefix argument: 10.0.0.111/24a ]) AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24 11.0.0.1a], [1], [], - [ovn-nbctl: bad IPv4 nexthop argument: 11.0.0.1a + [ovn-nbctl: bad nexthop argument: 11.0.0.1a ]) AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24 11.0.0.1/24], [1], [], - [ovn-nbctl: bad IPv4 nexthop argument: 11.0.0.1/24 + [ovn-nbctl: bad nexthop argument: 11.0.0.1/24 ]) AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1/64], [1], [], - [ovn-nbctl: bad IPv6 nexthop argument: 2001:0db8:0:f103::1/64 + [ovn-nbctl: bad nexthop argument: 2001:0db8:0:f103::1/64 ]) AT_CHECK([ovn-nbctl --ecmp lr-route-add lr0 20.0.0.0/24 discard], [1], [], [ovn-nbctl: ecmp is not valid for discard routes. @@ -2005,6 +2005,24 @@ check ovn-nbctl lr-route-del lr0 AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl ]) +dnl Check IPv4 over v6 and IPv6 over v4 routes +AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24 2001:0db8:0:f103::10]) +AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64 11.0.1.10]) + +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +IPv4 Routes +Route Table
: + 10.0.0.0/24 2001:db8:0:f103::10 dst-ip + +IPv6 Routes +Route Table
: + 2001:db8::/64 11.0.1.10 dst-ip +]) + +check ovn-nbctl lr-route-del lr0 +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +]) + dnl Check IPv4 routes in route table check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 0.0.0.0/0 192.168.0.1 check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0 diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 8a1db5fc0..41761ba96 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -3377,8 +3377,8 @@ AT_CHECK([grep "lr_in_policy" lr0flows3 | ovn_strip_lflows], [0], [dnl table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = 0; next;) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.3), action=(reg8[[0..15]] = 1; reg8[[16..31]] = select(1, 2);) table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) table=??(lr_in_policy_ecmp ), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) ]) @@ -3393,11 +3393,11 @@ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | ovn_strip_lf table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.3), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2);) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.4), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2, 3);) table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 3), action=(reg0 = 172.168.0.103; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 3), action=(reg0 = 172.168.0.103; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) table=??(lr_in_policy_ecmp ), priority=150 , match=(reg8[[0..15]] == ), action=(next;) ]) @@ -3411,13 +3411,13 @@ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | ovn_strip_lf table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = ; next;) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.3), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2);) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.4), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2, 3);) - table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; next;) + table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; reg9[[9]] = 1; next;) table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 3), action=(reg0 = 172.168.0.103; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 3), action=(reg0 = 172.168.0.103; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) table=??(lr_in_policy_ecmp ), priority=150 , match=(reg8[[0..15]] == ), action=(next;) ]) @@ -3430,11 +3430,11 @@ sed 's/reg8\[[0..15\]] = [[0-9]]*/reg8\[[0..15\]] = /' | \ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | ovn_strip_lflows], [0], [dnl table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = ; next;) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.4), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2, 3);) - table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; next;) + table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; reg9[[9]] = 1; next;) table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) - table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 3), action=(reg0 = 172.168.0.103; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 3), action=(reg0 = 172.168.0.103; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) table=??(lr_in_policy_ecmp ), priority=150 , match=(reg8[[0..15]] == ), action=(next;) ]) @@ -3446,7 +3446,7 @@ AT_CHECK([grep "lr_in_policy" lr0flows3 | \ sed 's/reg8\[[0..15\]] = [[0-9]]*/reg8\[[0..15\]] = /' | \ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | ovn_strip_lflows], [0], [dnl table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = ; next;) - table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; next;) + table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; reg9[[9]] = 1; next;) table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) table=??(lr_in_policy_ecmp ), priority=150 , match=(reg8[[0..15]] == ), action=(next;) ]) @@ -6684,8 +6684,8 @@ AT_CHECK([grep -e "lr_in_ip_routing.*select" lr0flows | ovn_strip_lflows], [0], ]) AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 's/192\.168\.0\..0/192.168.0.??/' | ovn_strip_lflows], [0], [dnl table=??(lr_in_ip_routing_ecmp), priority=0 , match=(1), action=(drop;) - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; next;) - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; next;) + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]] = 1; next;) table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) ]) @@ -6720,8 +6720,8 @@ AT_CHECK([grep -e "lr_in_ip_routing.*select" lr0flows | ovn_strip_lflows], [0], ]) AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 's/192\.168\.0\..0/192.168.0.??/' | ovn_strip_lflows], [0], [dnl table=??(lr_in_ip_routing_ecmp), priority=0 , match=(1), action=(drop;) - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; next;) - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; next;) + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]] = 1; next;) table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) ]) @@ -6732,14 +6732,74 @@ check ovn-nbctl --wait=sb lr-route-add lr0 1.0.0.0/24 192.168.0.10 ovn-sbctl dump-flows lr0 > lr0flows AT_CHECK([grep -e "lr_in_ip_routing.*192.168.0.10" lr0flows | ovn_strip_lflows], [0], [dnl - table=??(lr_in_ip_routing ), priority=73 , match=(reg7 == 0 && ip4.dst == 1.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) + table=??(lr_in_ip_routing ), priority=73 , match=(reg7 == 0 && ip4.dst == 1.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) ]) check ovn-nbctl --wait=sb lr-route-add lr0 2.0.0.0/24 lr0-public ovn-sbctl dump-flows lr0 > lr0flows AT_CHECK([grep -e "lr_in_ip_routing.*2.0.0.0" lr0flows | ovn_strip_lflows], [0], [dnl - table=??(lr_in_ip_routing ), priority=73 , match=(reg7 == 0 && ip4.dst == 2.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) + table=??(lr_in_ip_routing ), priority=73 , match=(reg7 == 0 && ip4.dst == 2.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) +]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([ovn -- static routes multiple address families flows]) +AT_KEYWORDS([static-routes-flows]) +ovn_start + +check ovn-sbctl chassis-add ch1 geneve 127.0.0.1 + +check ovn-nbctl lr-add lr0 +check ovn-nbctl set logical_router lr0 options:chassis=ch1 +check ovn-nbctl ls-add public +check ovn-nbctl ls-add private +check ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 192.168.0.1/24 +check ovn-nbctl lsp-add public public-lr0 +check ovn-nbctl lsp-set-type public-lr0 router +check ovn-nbctl lsp-set-addresses public-lr0 router +check ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public + +check ovn-nbctl lrp-add lr0 lr0-private 00:00:20:20:12:14 2001:db8::1/64 +check ovn-nbctl lsp-add private private-lr0 +check ovn-nbctl lsp-set-type private-lr0 router +check ovn-nbctl lsp-set-addresses private-lr0 router +check ovn-nbctl lsp-set-options private-lr0 router-port=lr0-private + +check ovn-nbctl --wait=sb lr-route-add lr0 10.0.0.0/24 192.168.0.10 +check ovn-nbctl --wait=sb lr-route-add lr0 11.0.0.0/24 2001:db8::10 +check ovn-nbctl --wait=sb lr-route-add lr0 2001:db8:1::/64 192.168.0.20 +check ovn-nbctl --wait=sb lr-route-add lr0 2001:db8:2::/64 2001:db8::20 + +ovn-sbctl dump-flows lr0 > lr0flows +AT_CHECK([grep -e "lr_in_ip_routing " lr0flows | ovn_strip_lflows], [0], [dnl + table=??(lr_in_ip_routing ), priority=0 , match=(1), action=(drop;) + table=??(lr_in_ip_routing ), priority=10550, match=(nd_rs || nd_ra), action=(drop;) + table=??(lr_in_ip_routing ), priority=193 , match=(reg7 == 0 && ip6.dst == 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.20; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing ), priority=193 , match=(reg7 == 0 && ip6.dst == 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 2001:db8::20; xxreg1 = 2001:db8::1; eth.src = 00:00:20:20:12:14; outport = "lr0-private"; flags.loopback = 1; reg9[[9]] = 0; next;) + table=??(lr_in_ip_routing ), priority=194 , match=(inport == "lr0-private" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:20ff:fe20:1214; eth.src = 00:00:20:20:12:14; outport = "lr0-private"; flags.loopback = 1; reg9[[9]] = 0; next;) + table=??(lr_in_ip_routing ), priority=194 , match=(inport == "lr0-public" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;) + table=??(lr_in_ip_routing ), priority=194 , match=(ip6.dst == 2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 2001:db8::1; eth.src = 00:00:20:20:12:14; outport = "lr0-private"; flags.loopback = 1; reg9[[9]] = 0; next;) + table=??(lr_in_ip_routing ), priority=73 , match=(reg7 == 0 && ip4.dst == 10.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing ), priority=73 , match=(reg7 == 0 && ip4.dst == 11.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:20:20:12:14; outport = "lr0-private"; flags.loopback = 1; reg9[[9]] = 0; next;) + table=??(lr_in_ip_routing ), priority=74 , match=(ip4.dst == 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 1; next;) +]) + +AT_CHECK([grep -e "lr_in_arp_resolve" lr0flows | ovn_strip_lflows], [0], [dnl + table=??(lr_in_arp_resolve ), priority=0 , match=(1), action=(drop;) + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == 0), action=(get_nd(outport, xxreg0); next;) + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == 1), action=(get_arp(outport, reg0); next;) + table=??(lr_in_arp_resolve ), priority=500 , match=(ip4.mcast || ip6.mcast), action=(next;) +]) + +AT_CHECK([grep -e "lr_in_arp_request" lr0flows | ovn_strip_lflows], [0], [dnl + table=??(lr_in_arp_request ), priority=0 , match=(1), action=(output;) + table=??(lr_in_arp_request ), priority=100 , match=(eth.dst == 00:00:00:00:00:00 && ip4), action=(arp { eth.dst = ff:ff:ff:ff:ff:ff; arp.spa = reg1; arp.tpa = reg0; arp.op = 1; output; }; output;) + table=??(lr_in_arp_request ), priority=100 , match=(eth.dst == 00:00:00:00:00:00 && ip6), action=(nd_ns { nd.target = xxreg0; output; }; output;) + table=??(lr_in_arp_request ), priority=200 , match=(eth.dst == 00:00:00:00:00:00 && ip6 && xxreg0 == 2001:db8::10), action=(nd_ns { eth.dst = 33:33:ff:00:00:10; ip6.dst = ff02::1:ff00:10; nd.target = 2001:db8::10; output; }; output;) + table=??(lr_in_arp_request ), priority=200 , match=(eth.dst == 00:00:00:00:00:00 && ip6 && xxreg0 == 2001:db8::20), action=(nd_ns { eth.dst = 33:33:ff:00:00:20; ip6.dst = ff02::1:ff00:20; nd.target = 2001:db8::20; output; }; output;) ]) AT_CLEANUP @@ -7163,16 +7223,16 @@ AT_CHECK([grep "lr_in_ip_routing_pre" lr0flows | ovn_strip_lflows], [0], [dnl grep -e "(lr_in_ip_routing ).*outport" lr0flows AT_CHECK([grep -e "(lr_in_ip_routing ).*outport" lr0flows | ovn_strip_lflows], [0], [dnl - table=??(lr_in_ip_routing ), priority=1 , match=(reg7 == 0 && ip4.dst == 0.0.0.0/0), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=1 , match=(reg7 == 2 && ip4.dst == 0.0.0.0/0), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=194 , match=(inport == "lrp0" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=194 , match=(inport == "lrp1" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:101; eth.src = 00:00:00:00:01:01; outport = "lrp1"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=194 , match=(inport == "lrp2" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:201; eth.src = 00:00:00:00:02:01; outport = "lrp2"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=73 , match=(reg7 == 1 && ip4.dst == 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.1.10; reg1 = 192.168.1.1; eth.src = 00:00:00:00:01:01; outport = "lrp1"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=74 , match=(ip4.dst == 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=74 , match=(ip4.dst == 192.168.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.1.1; eth.src = 00:00:00:00:01:01; outport = "lrp1"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=74 , match=(ip4.dst == 192.168.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.2.1; eth.src = 00:00:00:00:02:01; outport = "lrp2"; flags.loopback = 1; next;) - table=??(lr_in_ip_routing ), priority=97 , match=(reg7 == 2 && ip4.dst == 1.1.1.1/32), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.20; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; next;) + table=??(lr_in_ip_routing ), priority=1 , match=(reg7 == 0 && ip4.dst == 0.0.0.0/0), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing ), priority=1 , match=(reg7 == 2 && ip4.dst == 0.0.0.0/0), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing ), priority=194 , match=(inport == "lrp0" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; reg9[[9]] = 0; next;) + table=??(lr_in_ip_routing ), priority=194 , match=(inport == "lrp1" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:101; eth.src = 00:00:00:00:01:01; outport = "lrp1"; flags.loopback = 1; reg9[[9]] = 0; next;) + table=??(lr_in_ip_routing ), priority=194 , match=(inport == "lrp2" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:201; eth.src = 00:00:00:00:02:01; outport = "lrp2"; flags.loopback = 1; reg9[[9]] = 0; next;) + table=??(lr_in_ip_routing ), priority=73 , match=(reg7 == 1 && ip4.dst == 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.1.10; reg1 = 192.168.1.1; eth.src = 00:00:00:00:01:01; outport = "lrp1"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing ), priority=74 , match=(ip4.dst == 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing ), priority=74 , match=(ip4.dst == 192.168.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.1.1; eth.src = 00:00:00:00:01:01; outport = "lrp1"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing ), priority=74 , match=(ip4.dst == 192.168.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg1 = 192.168.2.1; eth.src = 00:00:00:00:02:01; outport = "lrp2"; flags.loopback = 1; reg9[[9]] = 1; next;) + table=??(lr_in_ip_routing ), priority=97 , match=(reg7 == 2 && ip4.dst == 1.1.1.1/32), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.20; reg1 = 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; reg9[[9]] = 1; next;) ]) AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index af0eaeed3..1f1a7963d 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -38323,3 +38323,648 @@ OVN_CLEANUP([hv1 ]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([2 HVs, 2 LS, 1 lport/LS, 2 peer LRs, IPv4 over IPv6]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +# Logical network: +# Two LRs - R1 and R2 that are connected to each other as peers in 2001:db8::/64 +# network. R1 has a switchs ls1 (192.168.1.0/24) connected to it. +# R2 has ls2 (172.16.1.0/24) connected to it. + +ls1_lp1_mac="f0:00:00:01:02:03" +rp_ls1_mac="00:00:00:01:02:03" +rp_ls2_mac="00:00:00:01:02:04" +ls2_lp1_mac="f0:00:00:01:02:04" + +ls1_lp1_ip="192.168.1.2" +ls2_lp1_ip="172.16.1.2" + +check ovn-nbctl lr-add R1 +check ovn-nbctl lr-add R2 + +check ovn-nbctl ls-add ls1 +check ovn-nbctl ls-add ls2 + +# Connect ls1 to R1 +check ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24 + +check ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \ + options:router-port=ls1 addresses=\"$rp_ls1_mac\" + +# Connect ls2 to R2 +check ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24 + +check ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \ + options:router-port=ls2 addresses=\"$rp_ls2_mac\" + +# Connect R1 to R2 +check ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 2001:db8::1/64 peer=R2_R1 +check ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 2001:db8::2/64 peer=R1_R2 + +AT_CHECK([ovn-nbctl lr-route-add R1 "0.0.0.0/0" 2001:db8::2]) +AT_CHECK([ovn-nbctl lr-route-add R2 "0.0.0.0/0" 2001:db8::1]) + +# Create logical port ls1-lp1 in ls1 +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip" + +# Create logical port ls2-lp1 in ls2 +check ovn-nbctl lsp-add ls2 ls2-lp1 \ +-- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +check ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +# Allow some time for ovn-northd and ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +# Packet to send. +packet=$(fmt_pkt "Ether(dst='${rp_ls1_mac}', src='${ls1_lp1_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=64)/ \ + UDP(sport=53, dport=4369)") +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# Packet to Expect +# The TTL should be decremented by 2. +expected=$(fmt_pkt "Ether(dst='${ls2_lp1_mac}', src='${rp_ls2_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=62)/ \ + UDP(sport=53, dport=4369)") +echo ${expected} > expected +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [1 +]) + +# Disable the ls2-lp1 port. +check ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [0 +]) + +# Send the same packet again and it should not be delivered +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# The 2nd packet sent shound not be received. +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([2 HVs, 2 LS, 1 lport/LS, LRs connected via LS, IPv4 over IPv6]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +# Logical network: +# Two LRs - R1 and R2 that are connected to ls-transfer in 2001:db8::/64 +# network. R1 has a switchs ls1 (192.168.1.0/24) connected to it. +# R2 has ls2 (172.16.1.0/24) connected to it. + +ls1_lp1_mac="f0:00:00:01:02:03" +rp_ls1_mac="00:00:00:01:02:03" +rp_ls2_mac="00:00:00:01:02:04" +ls2_lp1_mac="f0:00:00:01:02:04" + +ls1_lp1_ip="192.168.1.2" +ls2_lp1_ip="172.16.1.2" + +check ovn-nbctl lr-add R1 +check ovn-nbctl lr-add R2 + +check ovn-nbctl ls-add ls1 +check ovn-nbctl ls-add ls2 +check ovn-nbctl ls-add ls-transfer + +# Connect ls1 to R1 +check ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24 + +check ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \ + options:router-port=ls1 addresses=\"$rp_ls1_mac\" + +# Connect ls2 to R2 +check ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24 + +check ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \ + options:router-port=ls2 addresses=\"$rp_ls2_mac\" + +# Connect R1 to R2 +check ovn-nbctl lrp-add R1 R1_ls-transfer 00:00:00:02:03:04 2001:db8::1/64 +check ovn-nbctl lrp-add R2 R2_ls-transfer 00:00:00:02:03:05 2001:db8::2/64 + +check ovn-nbctl lsp-add ls-transfer ls-transfer_r1 -- \ + set Logical_Switch_Port ls-transfer_r1 type=router \ + options:router-port=R1_ls-transfer addresses=\"router\" +check ovn-nbctl lsp-add ls-transfer ls-transfer_r2 -- \ + set Logical_Switch_Port ls-transfer_r2 type=router \ + options:router-port=R2_ls-transfer addresses=\"router\" + +AT_CHECK([ovn-nbctl lr-route-add R1 "0.0.0.0/0" 2001:db8::2]) +AT_CHECK([ovn-nbctl lr-route-add R2 "0.0.0.0/0" 2001:db8::1]) + +# Create logical port ls1-lp1 in ls1 +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip" + +# Create logical port ls2-lp1 in ls2 +check ovn-nbctl lsp-add ls2 ls2-lp1 \ +-- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +check ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +# Allow some time for ovn-northd and ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +# Packet to send. +packet=$(fmt_pkt "Ether(dst='${rp_ls1_mac}', src='${ls1_lp1_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=64)/ \ + UDP(sport=53, dport=4369)") +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# Packet to Expect +# The TTL should be decremented by 2. +expected=$(fmt_pkt "Ether(dst='${ls2_lp1_mac}', src='${rp_ls2_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=62)/ \ + UDP(sport=53, dport=4369)") +echo ${expected} > expected +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [1 +]) + +# Disable the ls2-lp1 port. +check ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [0 +]) + +# Send the same packet again and it should not be delivered +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# The 2nd packet sent shound not be received. +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([2 HVs, 2 LS, 1 lport/LS, LRs connected via LS, IPv4 over IPv6, static mac]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +# Logical network: +# Two LRs - R1 and R2 that are connected to ls-transfer in 2001:db8::/64 +# network. R1 has a switchs ls1 (192.168.1.0/24) connected to it. +# R2 has ls2 (172.16.1.0/24) connected to it. + +ls1_lp1_mac="f0:00:00:01:02:03" +rp_ls1_mac="00:00:00:01:02:03" +rp_ls2_mac="00:00:00:01:02:04" +ls2_lp1_mac="f0:00:00:01:02:04" + +ls1_lp1_ip="192.168.1.2" +ls2_lp1_ip="172.16.1.2" + +check ovn-nbctl lr-add R1 +check ovn-nbctl lr-add R2 + +check ovn-nbctl ls-add ls1 +check ovn-nbctl ls-add ls2 +check ovn-nbctl ls-add ls-transfer + +# Connect ls1 to R1 +check ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24 +check ovn-nbctl set Logical_Router R1 options:dynamic_neigh_routers=true + +check ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \ + options:router-port=ls1 addresses=\"$rp_ls1_mac\" + +# Connect ls2 to R2 +check ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24 +check ovn-nbctl set Logical_Router R2 options:dynamic_neigh_routers=true + +check ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \ + options:router-port=ls2 addresses=\"$rp_ls2_mac\" + +# Connect R1 to R2 +check ovn-nbctl lrp-add R1 R1_ls-transfer 00:00:00:02:03:04 2001:db8::1/64 +check ovn-nbctl lrp-add R2 R2_ls-transfer 00:00:00:02:03:05 2001:db8::2/64 + +check ovn-nbctl lsp-add ls-transfer ls-transfer_r1 -- \ + set Logical_Switch_Port ls-transfer_r1 type=router \ + options:router-port=R1_ls-transfer addresses=\"router\" +check ovn-nbctl lsp-add ls-transfer ls-transfer_r2 -- \ + set Logical_Switch_Port ls-transfer_r2 type=router \ + options:router-port=R2_ls-transfer addresses=\"router\" + +# Static mac binding entries +check ovn-nbctl static-mac-binding-add R1_ls-transfer 2001:db8::2 00:00:00:02:03:05 +check ovn-nbctl static-mac-binding-add R2_ls-transfer 2001:db8::1 00:00:00:02:03:04 + +AT_CHECK([ovn-nbctl lr-route-add R1 "0.0.0.0/0" 2001:db8::2]) +AT_CHECK([ovn-nbctl lr-route-add R2 "0.0.0.0/0" 2001:db8::1]) + +# Create logical port ls1-lp1 in ls1 +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip" + +# Create logical port ls2-lp1 in ls2 +check ovn-nbctl lsp-add ls2 ls2-lp1 \ +-- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +check ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +# Allow some time for ovn-northd and ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +# Packet to send. +packet=$(fmt_pkt "Ether(dst='${rp_ls1_mac}', src='${ls1_lp1_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=64)/ \ + UDP(sport=53, dport=4369)") +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# Packet to Expect +# The TTL should be decremented by 2. +expected=$(fmt_pkt "Ether(dst='${ls2_lp1_mac}', src='${rp_ls2_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=62)/ \ + UDP(sport=53, dport=4369)") +echo ${expected} > expected +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [1 +]) + +# Disable the ls2-lp1 port. +check ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [0 +]) + +# Send the same packet again and it should not be delivered +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# The 2nd packet sent shound not be received. +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([2 HVs, 2 LS, 1 lport/LS, LRs connected via LS, IPv4 over IPv6, ECMP]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +# Logical network: +# Two LRs - R1 and R2 that are connected to ls-transfer1 and lr-transfer2 in +# 2001:db8:1::/64 and 2001:db8:2::/64 +# network. R1 has a switchs ls1 (192.168.1.0/24) connected to it. +# R2 has ls2 (172.16.1.0/24) connected to it. + +ls1_lp1_mac="f0:00:00:01:02:03" +rp_ls1_mac="00:00:00:01:02:03" +rp_ls2_mac="00:00:00:01:02:04" +ls2_lp1_mac="f0:00:00:01:02:04" + +ls1_lp1_ip="192.168.1.2" +ls2_lp1_ip="172.16.1.2" + +check ovn-nbctl lr-add R1 +check ovn-nbctl lr-add R2 + +check ovn-nbctl ls-add ls1 +check ovn-nbctl ls-add ls2 +check ovn-nbctl ls-add ls-transfer1 +check ovn-nbctl ls-add ls-transfer2 + +# Connect ls1 to R1 +check ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24 + +check ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \ + options:router-port=ls1 addresses=\"$rp_ls1_mac\" + +# Connect ls2 to R2 +check ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24 + +check ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \ + options:router-port=ls2 addresses=\"$rp_ls2_mac\" + +# Connect R1 to R2 (ls-transfer1) +check ovn-nbctl lrp-add R1 R1_ls-transfer1 00:00:00:02:03:04 2001:db8:1::1/64 +check ovn-nbctl lrp-add R2 R2_ls-transfer1 00:00:00:02:03:05 2001:db8:1::2/64 + +check ovn-nbctl lsp-add ls-transfer1 ls-transfer1_r1 -- \ + set Logical_Switch_Port ls-transfer1_r1 type=router \ + options:router-port=R1_ls-transfer1 addresses=\"router\" +check ovn-nbctl lsp-add ls-transfer1 ls-transfer1_r2 -- \ + set Logical_Switch_Port ls-transfer1_r2 type=router \ + options:router-port=R2_ls-transfer1 addresses=\"router\" + +# Connect R1 to R2 (ls-transfer2) +check ovn-nbctl lrp-add R1 R1_ls-transfer2 00:00:00:02:03:14 2001:db8:2::1/64 +check ovn-nbctl lrp-add R2 R2_ls-transfer2 00:00:00:02:03:15 2001:db8:2::2/64 + +check ovn-nbctl lsp-add ls-transfer2 ls-transfer2_r1 -- \ + set Logical_Switch_Port ls-transfer2_r1 type=router \ + options:router-port=R1_ls-transfer2 addresses=\"router\" +check ovn-nbctl lsp-add ls-transfer2 ls-transfer2_r2 -- \ + set Logical_Switch_Port ls-transfer2_r2 type=router \ + options:router-port=R2_ls-transfer2 addresses=\"router\" + +AT_CHECK([ovn-nbctl lr-route-add R1 "0.0.0.0/0" 2001:db8:1::2]) +AT_CHECK([ovn-nbctl --ecmp lr-route-add R1 "0.0.0.0/0" 2001:db8:2::2]) +AT_CHECK([ovn-nbctl lr-route-add R2 "0.0.0.0/0" 2001:db8:1::1]) +AT_CHECK([ovn-nbctl --ecmp lr-route-add R2 "0.0.0.0/0" 2001:db8:2::1]) + +# Create logical port ls1-lp1 in ls1 +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip" + +# Create logical port ls2-lp1 in ls2 +check ovn-nbctl lsp-add ls2 ls2-lp1 \ +-- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +check ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +# Allow some time for ovn-northd and ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +# Packet to send. +packet=$(fmt_pkt "Ether(dst='${rp_ls1_mac}', src='${ls1_lp1_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=64)/ \ + UDP(sport=53, dport=4369)") +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# Packet to Expect +# The TTL should be decremented by 2. +expected=$(fmt_pkt "Ether(dst='${ls2_lp1_mac}', src='${rp_ls2_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=62)/ \ + UDP(sport=53, dport=4369)") +echo ${expected} > expected +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [1 +]) + +# Disable the ls2-lp1 port. +check ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [0 +]) + +# Send the same packet again and it should not be delivered +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# The 2nd packet sent shound not be received. +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([2 HVs, 2 LS, 1 lport/LS, 2 peer LRs, IPv6 over IPv4]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +# Logical network: +# Two LRs - R1 and R2 that are connected to each other as peers in 10.0.0.0/24 +# network. R1 has a switchs ls1 (2001:db8:1::/64) connected to it. +# R2 has ls2 (2001:db8:2::/64) connected to it. + +ls1_lp1_mac="f0:00:00:01:02:03" +rp_ls1_mac="00:00:00:01:02:03" +rp_ls2_mac="00:00:00:01:02:04" +ls2_lp1_mac="f0:00:00:01:02:04" + +ls1_lp1_ip="2001:db8:1::2" +ls2_lp1_ip="2001:db8:2::2" + +check ovn-nbctl lr-add R1 +check ovn-nbctl lr-add R2 + +check ovn-nbctl ls-add ls1 +check ovn-nbctl ls-add ls2 + +# Connect ls1 to R1 +check ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 2001:db8:1::1/64 + +check ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \ + options:router-port=ls1 addresses=\"$rp_ls1_mac\" + +# Connect ls2 to R2 +check ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 2001:db8:2::1/64 + +check ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \ + options:router-port=ls2 addresses=\"$rp_ls2_mac\" + +# Connect R1 to R2 +check ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 10.0.0.1/24 peer=R2_R1 +check ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 10.0.0.2/24 peer=R1_R2 + +AT_CHECK([ovn-nbctl lr-route-add R1 "::/0" 10.0.0.2]) +AT_CHECK([ovn-nbctl lr-route-add R2 "::/0" 10.0.0.1]) + +# Create logical port ls1-lp1 in ls1 +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip" + +# Create logical port ls2-lp1 in ls2 +check ovn-nbctl lsp-add ls2 ls2-lp1 \ +-- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +check ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +# Allow some time for ovn-northd and ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +# Packet to send. +packet=$(fmt_pkt "Ether(dst='${rp_ls1_mac}', src='${ls1_lp1_mac}')/ \ + IPv6(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', hlim=64)/ \ + UDP(sport=53, dport=4369)") +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# Packet to Expect +# The TTL should be decremented by 2. +expected=$(fmt_pkt "Ether(dst='${ls2_lp1_mac}', src='${rp_ls2_mac}')/ \ + IPv6(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', hlim=62)/ \ + UDP(sport=53, dport=4369)") +echo ${expected} > expected +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "xxreg0 == 2001:db8:2::2" | wc -l], [0], [1 +]) + +# Disable the ls2-lp1 port. +check ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "xxreg0 == 2001:db8:2::2" | wc -l], [0], [0 +]) + +# Send the same packet again and it should not be delivered +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# The 2nd packet sent shound not be received. +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP +]) diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c index 99d2cba8c..bfba4049d 100644 --- a/utilities/ovn-nbctl.c +++ b/utilities/ovn-nbctl.c @@ -4548,11 +4548,9 @@ nbctl_lr_route_add(struct ctl_context *ctx) } char *route_table = shash_find_data(&ctx->options, "--route-table"); - bool v6_prefix = false; prefix = normalize_ipv4_prefix_str(ctx->argv[2]); if (!prefix) { prefix = normalize_ipv6_prefix_str(ctx->argv[2]); - v6_prefix = true; } if (!prefix) { ctl_error(ctx, "bad prefix argument: %s", ctx->argv[2]); @@ -4563,15 +4561,15 @@ nbctl_lr_route_add(struct ctl_context *ctx) if (is_discard_route) { next_hop = xasprintf("discard"); } else { - next_hop = v6_prefix - ? normalize_ipv6_addr_str(ctx->argv[3]) - : normalize_ipv4_addr_str(ctx->argv[3]); + next_hop = normalize_ipv4_addr_str(ctx->argv[3]); + if (!next_hop) { + next_hop = normalize_ipv6_addr_str(ctx->argv[3]); + } if (!next_hop) { /* check if it is a output port. */ error = lrp_by_name_or_uuid(ctx, ctx->argv[3], true, &out_lrp); if (error) { - ctl_error(ctx, "bad %s nexthop argument: %s", - v6_prefix ? "IPv6" : "IPv4", ctx->argv[3]); + ctl_error(ctx, "bad nexthop argument: %s", ctx->argv[3]); free(error); goto cleanup; } From patchwork Wed Jun 12 06:50:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felix Huettner X-Patchwork-Id: 1946667 X-Patchwork-Delegate: nusiddiq@redhat.com 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=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=XL2mV4SP; dkim=fail reason="signature verification failed" (2048-bit key) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=XL2mV4SP; 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 4Vzblc5NSxz20Pb for ; Wed, 12 Jun 2024 16:50:36 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 4FF8F406E5; Wed, 12 Jun 2024 06:50:34 +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 w0zQj0wdfpnN; Wed, 12 Jun 2024 06:50:30 +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 AFFE040833 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=XL2mV4SP; dkim=fail reason="signature verification failed" (2048-bit key) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=XL2mV4SP Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id AFFE040833; Wed, 12 Jun 2024 06:50:29 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 61501C0012; Wed, 12 Jun 2024 06:50:29 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id B5398C0011 for ; Wed, 12 Jun 2024 06:50:28 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id A28F740BAE for ; Wed, 12 Jun 2024 06:50:28 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id vOySKA4AB_qU for ; Wed, 12 Jun 2024 06:50:26 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2a01:111:f403:2607::600; helo=eur02-vi1-obe.outbound.protection.outlook.com; envelope-from=felix.huettner@mail.schwarz; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org 444F440BAA Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=reject dis=none) header.from=mail.schwarz DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 444F440BAA Authentication-Results: smtp2.osuosl.org; dkim=pass (2048-bit key, unprotected) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=XL2mV4SP; dkim=pass (2048-bit key) header.d=mail.schwarz header.i=@mail.schwarz header.a=rsa-sha256 header.s=selector1 header.b=XL2mV4SP Received: from EUR02-VI1-obe.outbound.protection.outlook.com (mail-vi1eur02on20600.outbound.protection.outlook.com [IPv6:2a01:111:f403:2607::600]) by smtp2.osuosl.org (Postfix) with ESMTPS id 444F440BAA for ; Wed, 12 Jun 2024 06:50:26 +0000 (UTC) ARC-Seal: i=2; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass; b=lVNVGJTQr4iKfkwidKC2j1y6c45EEwLZGFlPIhrZVm+QbtzIvD8NKVLC9HOD9qulXNsf73ewlXukgaqncuPU1CBVZPzAxDnWOg9RiR+OhXvDsHruA+u1XlPEIdaRUNFByd61tigoyK1vZ9yKuZS7EBJ8cPt9g0w5Mg75mYyPkGDaXoERqAm1gEdUH0Nifgo+qEDPLrfbqwy0WqkP48KGMLyD3ywmuTTwcWRyFo+77mLHnIZHWjPTih4EJiouUfTMqlaWkR5QaHRU1KmIABe53cQreCe3tDsfqUm2NKsn9oJD971qiIot06jwpwHPLrJJRx38rB2uLa02kVPzDjc7zQ== ARC-Message-Signature: i=2; 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=j0t+TzQSvnW/X1fODy4QBKVaTaQ4EuRCxuFEbsiJeBw=; b=Y1Rt4Clg3LS0fganEtuLCZtD/3IU7nze+LCtEfGBJKJQkRUtffr6h+b2W39re+hgDRrk6VCGSy2suQS5/j7Skmh9d4EQLFVSVww/CVloEuWLHzoSkiXfvQyX8pNdq3OQr5irlBzJu7jk2j7F999NvZlxCgprwoLxQvr3nq3MeyQX8gOkOOK1E6TslmQXTLADyuHK8Lhb/fiehsgILI9bMhbw2G9wKqvY5qHYjH0O0GaUIDNvqqFCXVtzsQaYQz9Jj7xDNo4Dir/jDWCxrhcvCqyxIWQaEvr2mwgI1TlFVzZ9BHhs9bKb9G+Qj93MxJK7uXY/Os4MtIOyek1vreSgPw== ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is 52.169.0.179) smtp.rcpttodomain=openvswitch.org smtp.mailfrom=mail.schwarz; dmarc=pass (p=reject sp=none pct=100) action=none header.from=mail.schwarz; dkim=pass (signature was verified) header.d=mail.schwarz; arc=pass (0 oda=1 ltdi=1 spf=[1,1,smtp.mailfrom=mail.schwarz] dkim=[1,1,header.d=mail.schwarz] dmarc=[1,1,header.from=mail.schwarz]) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mail.schwarz; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=j0t+TzQSvnW/X1fODy4QBKVaTaQ4EuRCxuFEbsiJeBw=; b=XL2mV4SPy4jFpn05iL3URm3PFAu5oj/skfojEE0TBYZlvwM2+/CXK8EcCJ9UdsI8ATGoRR+6y9SD7fi6t/I0Cf3F7WG268xewucOV7qYL4t5FoyM1pJ0LxzT5wgSA/EsV1Dn9PH29Z6/+fw+0Dum0Rp03d+FuaoXYH2ZiodFFdJWkgWHkbdhNNFfhW1+ob4Y4LWDhRRgtBe+74BYd6hpYQJ7Vj7F70nUad/dhEt+l03ye6PTeMm7hok6Lh4jftSCZMz+h58x4wptC2EMeAQbJd7y/vjaYEife9ssFyv64F9p6fTYQoMP+uBGLrW5h+hgVP/Fge0vbMdedEe7Kdb3cA== Received: from DUZP191CA0041.EURP191.PROD.OUTLOOK.COM (2603:10a6:10:4f8::20) by PA1PR10MB8585.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:102:444::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.37; Wed, 12 Jun 2024 06:50:22 +0000 Received: from DU2PEPF00028D04.eurprd03.prod.outlook.com (2603:10a6:10:4f8:cafe::f1) by DUZP191CA0041.outlook.office365.com (2603:10a6:10:4f8::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7677.20 via Frontend Transport; Wed, 12 Jun 2024 06:50:22 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 52.169.0.179) smtp.mailfrom=mail.schwarz; dkim=pass (signature was verified) header.d=mail.schwarz;dmarc=pass action=none header.from=mail.schwarz; Received-SPF: Pass (protection.outlook.com: domain of mail.schwarz designates 52.169.0.179 as permitted sender) receiver=protection.outlook.com; client-ip=52.169.0.179; helo=eu2.smtp.exclaimer.net; pr=C Received: from eu2.smtp.exclaimer.net (52.169.0.179) by DU2PEPF00028D04.mail.protection.outlook.com (10.167.242.164) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.7677.15 via Frontend Transport; Wed, 12 Jun 2024 06:50:19 +0000 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (104.47.14.40) by eu2.smtp.exclaimer.net (52.169.0.179) with Exclaimer Signature Manager ESMTP Proxy eu2.smtp.exclaimer.net (tlsversion=TLS12, tlscipher=TLS_ECDHE_WITH_AES256_SHA384); Wed, 12 Jun 2024 06:50:20 +0000 X-ExclaimerHostedSignatures-MessageProcessed: true X-ExclaimerProxyLatency: 12520826 X-ExclaimerImprintLatency: 9357228 X-ExclaimerImprintAction: 7a193470d7f2486ab1ce3b552bffa16a ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=CSkks/UdasqJGA0tOWlyBH7I9CPuLHqFdaKWoKwMNFdjPwjn8PU+srvkr6Q+ZicNNTlpOLKtRKggj3tJgu0PZA3czGK115uZTvj8vfn8m80zWW3RbcG3gpzugEMhawImJ9sMd55VX00LSUnMsfeWrJ4KKlZib8uP2pFAeBGZ/+uItFGf8NyxUqqX6152IailhgV0jYafSLm1sxxRa0TAgE22qjguWLnKLg3RRzwlXPIOlFJBWTezR0GhNiq0dKS9cD5Php14ucbNnDYF9+VW3KwvDRpN96mFGPTB+Axxy54LgqJLpu7gVLN4ChNDwvW8ATGR/zqHxYEKJDHZ5x8YXQ== 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=j0t+TzQSvnW/X1fODy4QBKVaTaQ4EuRCxuFEbsiJeBw=; b=MSZ+0UdLr5WRS+p89CjkA/LcuoMN5v6njl5FWiCMUJC8yhywf/0DMZMkyBSTF5HQnTbU9rM5Yx+eNTa3RXOQrVkf6QIaW8GIgCRp2E3+ieSmqJmYHBx+BkIylUjUGhsHRkGP8d8jr929AYKBHOvcUJ78kOg7krcFzFKlQkMVMxVQzfg/0rkNQTaZx0pGm4HzRP0wafVhJ14ESrbNFS0TGdbSBADQNpkiyLzti/mXyX3aSdWd9nzMvx40ggBLFpslSWcqgXgzhEKA/QjNBAIevnNDF2rqGRtyTcGsAhvGRDndiar5fdc2i8HKyd7kKDK0rPIvTH918OM5DWuoi3GL0Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=mail.schwarz; dmarc=pass action=none header.from=mail.schwarz; dkim=pass header.d=mail.schwarz; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mail.schwarz; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=j0t+TzQSvnW/X1fODy4QBKVaTaQ4EuRCxuFEbsiJeBw=; b=XL2mV4SPy4jFpn05iL3URm3PFAu5oj/skfojEE0TBYZlvwM2+/CXK8EcCJ9UdsI8ATGoRR+6y9SD7fi6t/I0Cf3F7WG268xewucOV7qYL4t5FoyM1pJ0LxzT5wgSA/EsV1Dn9PH29Z6/+fw+0Dum0Rp03d+FuaoXYH2ZiodFFdJWkgWHkbdhNNFfhW1+ob4Y4LWDhRRgtBe+74BYd6hpYQJ7Vj7F70nUad/dhEt+l03ye6PTeMm7hok6Lh4jftSCZMz+h58x4wptC2EMeAQbJd7y/vjaYEife9ssFyv64F9p6fTYQoMP+uBGLrW5h+hgVP/Fge0vbMdedEe7Kdb3cA== Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=mail.schwarz; Received: from PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:102:30d::9) by AS4PR10MB5272.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:20b:4b8::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.37; Wed, 12 Jun 2024 06:50:17 +0000 Received: from PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM ([fe80::f00d:feeb:e45e:54f8]) by PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM ([fe80::f00d:feeb:e45e:54f8%2]) with mapi id 15.20.7633.036; Wed, 12 Jun 2024 06:50:16 +0000 Date: Wed, 12 Jun 2024 08:50:14 +0200 To: dev@openvswitch.org Message-ID: <9d1431a90b587e2f56bb7be5ae8c90902a758b5d.1718174935.git.felix.huettner@mail.schwarz> Mail-Followup-To: dev@openvswitch.org References: Content-Disposition: inline In-Reply-To: X-ClientProxiedBy: FR3P281CA0107.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:a3::17) To PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:102:30d::9) MIME-Version: 1.0 X-MS-TrafficTypeDiagnostic: PAVPR10MB6914:EE_|AS4PR10MB5272:EE_|DU2PEPF00028D04:EE_|PA1PR10MB8585:EE_ X-MS-Office365-Filtering-Correlation-Id: b8c2c17e-00f4-4c07-ad32-08dc8aabed76 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230032|1800799016|376006|366008; X-Microsoft-Antispam-Message-Info-Original: Dhij8IXiyhv7yu63eITKNGLnTGE03/rEFMtQj4BDxQJqWx7OSQ2j24WAtcI7aSmpV/gKj/h5GNoJdfrXkYKQwQyd4RhRoLm7Owvqvf19IKOZYMX6q3lGalRjDky+OjG7010CirQVoE5Bb7VVG/jL2udV/85rS7uaG5naNVijWr0sXxiFIEK29N3gBHsQ3IEBlmp7R1KL37EeuduURn4KwfOW8qqMpZMAWCH8dByeVVyqbGybrFE0rDtft/DzkyuWK7a1yeHk0Qgd6NkvlJCtGWT5L1FpD3QBR5D64X4/E8h+1ruconhl4VVE/fmjRpzC/8sYY6F/F3YvN3Le+SZaMC+zsomlm2E4zMo1rw2XiqiUuXOVur67eEKeHH0b6FsTJibgTdlvNEJO/INveJg2mBbXZSlpnZiceRwG9HXWkGIMyaoHlCXaI7ic1nyCJyBVYwnxxlwQbvMzysPB3NDuGb/wCa3uZiprYkovoUo+dOGiZfZmh1pQIIXXzyxkQFaGn/JC3K2l/nsBdLlyZUg0K8hyUEUJ5w/Q82d8mIpw15eRwZbyobCYOlYse09yCTNUzV7TX/pGwEaK3pCGlyyxxKsfvEPY64iFE17kcLq39J7uhS936EfiIUrbRfosw+iEy7SRRAahj1J/J4wXmNkChk2RolbQvq2EhsosisE1150CMhA9/xjN/uFKYrPuOhP6B1zFpAfqQVG4qFYY7pyvYK4JAoLDUhP0PVa5EBK+2QnXnBVoCUT6uY1Y8Tc6tHY/J+Ds1MedFl+SBDgPXy4+mWB6Ud4F9OYLCvg8EIG0ylhPvdBmGuxHu7rLCq1IcKP+wlg3z9fxr0+HSAXBNPI1JYApKIEDE6isuD2Yu4Uz922LX5uBlzzIkfsz7F0n6CGADWHDCfsdRH5p2ld0SY5MitDes6w/re+K8Mreyld4tmC5xPlzdoxEEkWPytvUZaQlTJy35jdta88L+haGyWtfVKZdgCM1/ZbbgcU4CYkd9yt1FC0APMStxljUBbrTrWKBsMo5zr+JZUpZU74/aunqz6h+qfY8bWiYDlQb1ZgA6BzLXs10p+WERg6t+FHdk5xJKA0Mmrl+Q1sAFla55AylSApyI45bXPET+0wQ3933v6PjEdAt0tLESzgkaUWDOaO/78njDJxsTkVeQEO3XHNYw5j8ZBykSRWC64/9RpM6HrXbcG0gcCemXrNX8gX4DnfrQ2xoBWnpUZCYqse0tyUg3gFos7DTRGj2CnDm0Xs1fXigkwnFCQLcwkoT6PA2SAiovtX/qGIUdsmOZcQirdN++AMB1U17jXFOgvRhUaik3NmbvkjC5ZrXIvV/F6XtvC/k X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAVPR10MB6914.EURPRD10.PROD.OUTLOOK.COM; PTR:; CAT:NONE; SFS:(13230032)(1800799016)(376006)(366008); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4PR10MB5272 X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DU2PEPF00028D04.eurprd03.prod.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 7a9add45-7f93-4a39-8272-08dc8aabeab9 X-Microsoft-Antispam: BCL:0; ARA:13230032|35042699014|82310400018|36860700005|376006|1800799016; X-Microsoft-Antispam-Message-Info: bI0ymxd0AF7b5MT5HJH8AFfb+UV5GTGeLIybVn+v/IxebG1Kttyai5IynuFd+l5ufZvJHJuddCupynP7M5PvB/T/6VnQbF4MGlUbKY492s2KCQa5jYKJiRyu8dBbMDOstOcT2jJQ/Ro+k7duQMzxEWYrl/4ccLC6wXYmsaHMq3hetyWLACR/qkJJtsSrWwsYAhgZvFEfAqxyPeWpklEOIwrwmUK9W4w0qIsD3rqLMA0EeWGtAN1Vl4VewX14vSawQ1Ox3HToSllp0H0kZKJ324i70aoLCBtiSNn4j9BHT2LCiURHhyflAklkYmHABT62438Tw9GKyPQ0YYfHNrTdLHRC7BCs9yEpEaUez+PqeXGW5eMI8Sx84W5RqkZfRN+rByNHtDJq8T+Rxt7QdlxMiOvcNmOMOUV0J4LZXHLks2vPiTxOF7ZG5Sq0kZZuOfJ/4SjNUcAo2woHsFkcYcFU46tWkgQYZDw3OdhFxyXFvISA+91PEvFXoYr1IT+i51Ri/ZDTDBMAnQDzUafv0c/QeBifGUN0F4cT20i/j9mcca2iARGHPNldN8O4JsSXBlnWRwNEZiVAXvRkZwZUv536N63cJgRdtbCzRsCqm2Loc1Smcn+on7rEyKfxDA02sFVQ/v2xENJeUXzpZh34QCFVrwi/YIlJV/pwUsht3SJJi3TtB9kXOhOh2x0AB68H5IToWirf1DwsarKxnqf1qaPjSd66JiA9wWhxa1iO9+PIDkKiyadi5/Rnt8UGPWoeRbP+appn/AnPMvyGTM0xbxgcT7YiG3yfKEGCsxk4LD+K+wSv2uo7dhFm0OG3OfTmFedyXxSlhNerYZJUUy7F5PxKOeD/xb4/Uz1jNX6EJWPc9fDHCz3Eg80m/4kcxpxsVMQca9rHmkBvxRbPBAUgUCL7bepMqTYznINCvN597iFHu2wM3d4lw00hWoyy3Yh5As1ZhenzQzn2sqKmz3zL3rYXg9snfzlgFO6ouWSVM8MdbfEB0ZuTW1A1YNYSp5YDxaxT2WTfw9z+bkyYxaY20GpcgLgGFe5q/mkpcPXiAGGjAlyLGkTlz++YRueaFwesL5LrQ3NitVLCJr1wIkH5nsjd28L1W+bQnkpkVgk/Ae1SyclFZi2MgiyFL4H7OTRTYSgNIg0+2AEEcrMceZdFebowgP+h5tcRjCGXqtS9jyyzuTrZT1NoGWYS7qn7b3GOhhM/0KVawh6C3d9FRHWo3FIDB0d17CSVXh3JG5WusewM5SxTsxCSu0eX/1uO7lvpwWhAS82cpG7T/JaBHR64LoccbRMCipUZq678F2QZb2gEEum27AxQTlPSd6/odwQTkB6QQQcGZ7MFuD9p0twsIBvdsI1UMjPTHhwQYZigpzDxRHbpn0AQ6tMbwKVOHppIVrFu0taR+gk+Ik5Xe23OBZrR9w== X-Forefront-Antispam-Report: CIP:52.169.0.179; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:eu2.smtp.exclaimer.net; PTR:eu2.smtp.exclaimer.net; CAT:NONE; SFS:(13230032)(35042699014)(82310400018)(36860700005)(376006)(1800799016); DIR:OUT; SFP:1101; X-OriginatorOrg: mail.schwarz X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Jun 2024 06:50:19.7317 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b8c2c17e-00f4-4c07-ad32-08dc8aabed76 X-MS-Exchange-CrossTenant-Id: d04f4717-5a6e-4b98-b3f9-6918e0385f4c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=d04f4717-5a6e-4b98-b3f9-6918e0385f4c; Ip=[52.169.0.179]; Helo=[eu2.smtp.exclaimer.net] X-MS-Exchange-CrossTenant-AuthSource: DU2PEPF00028D04.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA1PR10MB8585 Subject: [ovs-dev] [PATCH ovn v5 2/2] pinctrl: Handle arp/nd for other address families. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Huettner via dev From: Felix Huettner Reply-To: Felix Huettner Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Previously we could only generate ARP requests from IPv4 packets and NS requests from IPv6 packets. This was the case because we rely on information in the packet to generate the ARP/NS requests. However in case of ARP/NS requests originating from the Logical_Router pipeline for nexthop lookups we overwrite the affected fields afterwards. This overwrite is done by the userdata openflow actions. Because of this we actually do not rely on any information of the IPv4/6 packets in these cases. Unfortunately we can not easily determine if we are actually later overwriting the affected fields. The approach now is to use the fields from the IP header if we have a matching IP version and default to some values otherwise. In case we overwrite this data afterwards we are generally good. If we do not overwrite this data because of some bug we will send out invalid ARP/NS requests. They will hopefully be dropped by the rest of the network. The alternative would have been to introduce new arp/nd_ns actions where we guarantee this overwrite. This would not suffer from the above limitations, but would require a coordination on upgrades between all ovn-controllers and northd. Signed-off-by: Felix Huettner --- v4->v5: rebase v4: newly added controller/pinctrl.c | 52 +++++++-- lib/actions.c | 4 +- northd/northd.c | 9 +- tests/ovn-northd.at | 8 +- tests/ovn.at | 268 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 320 insertions(+), 21 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index f2e382a44..4c520bd5e 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -1574,9 +1574,11 @@ pinctrl_handle_arp(struct rconn *swconn, const struct flow *ip_flow, const struct ofputil_packet_in *pin, struct ofpbuf *userdata, const struct ofpbuf *continuation) { - /* This action only works for IP packets, and the switch should only send - * us IP packets this way, but check here just to be sure. */ - if (ip_flow->dl_type != htons(ETH_TYPE_IP)) { + uint16_t dl_type = ntohs(ip_flow->dl_type); + + /* This action only works for IPv4 or IPv6 packets, and the switch should + * only send us IP packets this way, but check here just to be sure. */ + if (dl_type != ETH_TYPE_IP && dl_type != ETH_TYPE_IPV6) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_WARN_RL(&rl, "ARP action on non-IP packet (Ethertype %"PRIx16")", ntohs(ip_flow->dl_type)); @@ -1600,9 +1602,25 @@ pinctrl_handle_arp(struct rconn *swconn, const struct flow *ip_flow, struct arp_eth_header *arp = dp_packet_l3(&packet); arp->ar_op = htons(ARP_OP_REQUEST); arp->ar_sha = ip_flow->dl_src; - put_16aligned_be32(&arp->ar_spa, ip_flow->nw_src); arp->ar_tha = eth_addr_zero; - put_16aligned_be32(&arp->ar_tpa, ip_flow->nw_dst); + + /* We might be here without actually currently handling an IPv4 packet. + * This can happen in the case where we route IPv6 packets over an IPv4 + * link. + * In these cases we have no destination IPv4 address from the packet that + * we can reuse. But we receive the actual destination IPv4 address via + * userdata anyway, so what we set for now is irrelevant. + * This is just a hope since we do not parse the userdata. If we land here + * for whatever reason without being an IPv4 packet and without userdata we + * will send out a wrong packet. + */ + if (ip_flow->dl_type == htons(ETH_TYPE_IP)) { + put_16aligned_be32(&arp->ar_spa, ip_flow->nw_src); + put_16aligned_be32(&arp->ar_tpa, ip_flow->nw_dst); + } else { + put_16aligned_be32(&arp->ar_spa, 0); + put_16aligned_be32(&arp->ar_tpa, 0); + } if (ip_flow->vlans[0].tci & htons(VLAN_CFI)) { eth_push_vlan(&packet, htons(ETH_TYPE_VLAN_8021Q), @@ -6741,8 +6759,11 @@ pinctrl_handle_nd_ns(struct rconn *swconn, const struct flow *ip_flow, struct ofpbuf *userdata, const struct ofpbuf *continuation) { - /* This action only works for IPv6 packets. */ - if (get_dl_type(ip_flow) != htons(ETH_TYPE_IPV6)) { + uint16_t dl_type = ntohs(ip_flow->dl_type); + + /* This action only works for IPv4 or IPv6 packets, and the switch should + * only send us IP packets this way, but check here just to be sure. */ + if (dl_type != ETH_TYPE_IP && dl_type != ETH_TYPE_IPV6) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_WARN_RL(&rl, "NS action on non-IPv6 packet"); return; @@ -6758,8 +6779,23 @@ pinctrl_handle_nd_ns(struct rconn *swconn, const struct flow *ip_flow, dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); in6_generate_lla(ip_flow->dl_src, &ipv6_src); + + /* We might be here without actually currently handling an IPv6 packet. + * This can happen in the case where we route IPv4 packets over an IPv6 + * link. + * In these cases we have no destination IPv6 address from the packet that + * we can reuse. But we receive the actual destination IPv6 address via + * userdata anyway, so what we pass to compose_nd_ns is irrelevant. + * This is just a hope since we do not parse the userdata. If we land here + * for whatever reason without being an IPv6 packet and without userdata we + * will send out a wrong packet. + */ + struct in6_addr ipv6_dst = IN6ADDR_EXACT_INIT; + if (get_dl_type(ip_flow) == htons(ETH_TYPE_IPV6)) { + ipv6_dst = ip_flow->ipv6_dst; + } compose_nd_ns(&packet, ip_flow->dl_src, &ipv6_src, - &ip_flow->ipv6_dst); + &ipv6_dst); /* Reload previous packet metadata and set actions from userdata. */ set_actions_and_enqueue_msg(swconn, &packet, diff --git a/lib/actions.c b/lib/actions.c index e8cc0994d..c7c83a34c 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -1718,7 +1718,7 @@ parse_nested_action(struct action_context *ctx, enum ovnact_type type, static void parse_ARP(struct action_context *ctx) { - parse_nested_action(ctx, OVNACT_ARP, "ip4", ctx->scope); + parse_nested_action(ctx, OVNACT_ARP, "ip", ctx->scope); } static void @@ -1772,7 +1772,7 @@ parse_ND_NA_ROUTER(struct action_context *ctx) static void parse_ND_NS(struct action_context *ctx) { - parse_nested_action(ctx, OVNACT_ND_NS, "ip6", ctx->scope); + parse_nested_action(ctx, OVNACT_ND_NS, "ip", ctx->scope); } static void diff --git a/northd/northd.c b/northd/northd.c index e697973ce..970cdca6e 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -13549,7 +13549,8 @@ build_arp_request_flows_for_lrouter( ds_clear(match); ds_put_format(match, "eth.dst == 00:00:00:00:00:00 && " - "ip6 && " REG_NEXT_HOP_IPV6 " == %s", + REGBIT_NEXTHOP_IS_IPV4" == 0 && " + REG_NEXT_HOP_IPV6 " == %s", route->nexthop); struct in6_addr sn_addr; struct eth_addr eth_dst; @@ -13579,7 +13580,8 @@ build_arp_request_flows_for_lrouter( } ovn_lflow_metered(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100, - "eth.dst == 00:00:00:00:00:00 && ip4", + "eth.dst == 00:00:00:00:00:00 && " + REGBIT_NEXTHOP_IS_IPV4" == 1", "arp { " "eth.dst = ff:ff:ff:ff:ff:ff; " "arp.spa = " REG_SRC_IPV4 "; " @@ -13591,7 +13593,8 @@ build_arp_request_flows_for_lrouter( meter_groups), lflow_ref); ovn_lflow_metered(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100, - "eth.dst == 00:00:00:00:00:00 && ip6", + "eth.dst == 00:00:00:00:00:00 && " + REGBIT_NEXTHOP_IS_IPV4" == 0", "nd_ns { " "nd.target = " REG_NEXT_HOP_IPV6 "; " "output; " diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 41761ba96..a6aa66a0c 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -6796,10 +6796,10 @@ AT_CHECK([grep -e "lr_in_arp_resolve" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep -e "lr_in_arp_request" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_arp_request ), priority=0 , match=(1), action=(output;) - table=??(lr_in_arp_request ), priority=100 , match=(eth.dst == 00:00:00:00:00:00 && ip4), action=(arp { eth.dst = ff:ff:ff:ff:ff:ff; arp.spa = reg1; arp.tpa = reg0; arp.op = 1; output; }; output;) - table=??(lr_in_arp_request ), priority=100 , match=(eth.dst == 00:00:00:00:00:00 && ip6), action=(nd_ns { nd.target = xxreg0; output; }; output;) - table=??(lr_in_arp_request ), priority=200 , match=(eth.dst == 00:00:00:00:00:00 && ip6 && xxreg0 == 2001:db8::10), action=(nd_ns { eth.dst = 33:33:ff:00:00:10; ip6.dst = ff02::1:ff00:10; nd.target = 2001:db8::10; output; }; output;) - table=??(lr_in_arp_request ), priority=200 , match=(eth.dst == 00:00:00:00:00:00 && ip6 && xxreg0 == 2001:db8::20), action=(nd_ns { eth.dst = 33:33:ff:00:00:20; ip6.dst = ff02::1:ff00:20; nd.target = 2001:db8::20; output; }; output;) + table=??(lr_in_arp_request ), priority=100 , match=(eth.dst == 00:00:00:00:00:00 && reg9[[9]] == 0), action=(nd_ns { nd.target = xxreg0; output; }; output;) + table=??(lr_in_arp_request ), priority=100 , match=(eth.dst == 00:00:00:00:00:00 && reg9[[9]] == 1), action=(arp { eth.dst = ff:ff:ff:ff:ff:ff; arp.spa = reg1; arp.tpa = reg0; arp.op = 1; output; }; output;) + table=??(lr_in_arp_request ), priority=200 , match=(eth.dst == 00:00:00:00:00:00 && reg9[[9]] == 0 && xxreg0 == 2001:db8::10), action=(nd_ns { eth.dst = 33:33:ff:00:00:10; ip6.dst = ff02::1:ff00:10; nd.target = 2001:db8::10; output; }; output;) + table=??(lr_in_arp_request ), priority=200 , match=(eth.dst == 00:00:00:00:00:00 && reg9[[9]] == 0 && xxreg0 == 2001:db8::20), action=(nd_ns { eth.dst = 33:33:ff:00:00:20; ip6.dst = ff02::1:ff00:20; nd.target = 2001:db8::20; output; }; output;) ]) AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index 1f1a7963d..6894947d1 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1541,11 +1541,11 @@ clone { ip4.dst = 255.255.255.255; output; }; next; # arp arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output; encodes as controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.OFTABLE_SAVE_INPORT_HEX.00.00.00,pause),resubmit(,OFTABLE_SAVE_INPORT) - has prereqs ip4 + has prereqs ip arp { }; formats as arp { drop; }; encodes as controller(userdata=00.00.00.00.00.00.00.00,pause) - has prereqs ip4 + has prereqs ip # get_arp get_arp(outport, ip4.dst); @@ -1709,12 +1709,12 @@ reg9[[8]] = dhcp_relay_resp_chk(192.168.1, 172.16.1.1); # 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) - has prereqs ip6 + has prereqs ip nd_ns { }; formats as nd_ns { drop; }; encodes as controller(userdata=00.00.00.09.00.00.00.00,pause) - has prereqs ip6 + has prereqs ip # nd_na nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending out inport. */ output; }; @@ -38706,6 +38706,266 @@ OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD([ +AT_SETUP([2 HVs, 2 LS, 1 lport/LS, LRs connected via LS, IPv4 over IPv6, dynamic]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +# Logical network: +# Two LRs - R1 and R2 that are connected to ls-transfer in 2001:db8::/64 +# network. R1 has a switchs ls1 (192.168.1.0/24) connected to it. +# R2 has ls2 (172.16.1.0/24) connected to it. + +ls1_lp1_mac="f0:00:00:01:02:03" +rp_ls1_mac="00:00:00:01:02:03" +rp_ls2_mac="00:00:00:01:02:04" +ls2_lp1_mac="f0:00:00:01:02:04" + +ls1_lp1_ip="192.168.1.2" +ls2_lp1_ip="172.16.1.2" + +check ovn-nbctl lr-add R1 +check ovn-nbctl lr-add R2 + +check ovn-nbctl ls-add ls1 +check ovn-nbctl ls-add ls2 +check ovn-nbctl ls-add ls-transfer + +# Connect ls1 to R1 +check ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24 +check ovn-nbctl set Logical_Router R1 options:dynamic_neigh_routers=true + +check ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \ + options:router-port=ls1 addresses=\"$rp_ls1_mac\" + +# Connect ls2 to R2 +check ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24 +check ovn-nbctl set Logical_Router R2 options:dynamic_neigh_routers=true + +check ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \ + options:router-port=ls2 addresses=\"$rp_ls2_mac\" + +# Connect R1 to R2 +check ovn-nbctl lrp-add R1 R1_ls-transfer 00:00:00:02:03:04 2001:db8::1/64 +check ovn-nbctl lrp-add R2 R2_ls-transfer 00:00:00:02:03:05 2001:db8::2/64 + +check ovn-nbctl lsp-add ls-transfer ls-transfer_r1 -- \ + set Logical_Switch_Port ls-transfer_r1 type=router \ + options:router-port=R1_ls-transfer addresses=\"router\" +check ovn-nbctl lsp-add ls-transfer ls-transfer_r2 -- \ + set Logical_Switch_Port ls-transfer_r2 type=router \ + options:router-port=R2_ls-transfer addresses=\"router\" + +AT_CHECK([ovn-nbctl lr-route-add R1 "0.0.0.0/0" 2001:db8::2]) +AT_CHECK([ovn-nbctl lr-route-add R2 "0.0.0.0/0" 2001:db8::1]) + +# Create logical port ls1-lp1 in ls1 +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip" + +# Create logical port ls2-lp1 in ls2 +check ovn-nbctl lsp-add ls2 ls2-lp1 \ +-- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +check ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +# Allow some time for ovn-northd and ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +# Packet to send. +packet=$(fmt_pkt "Ether(dst='${rp_ls1_mac}', src='${ls1_lp1_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=64)/ \ + UDP(sport=53, dport=4369)") +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# Packet to Expect +# The TTL should be decremented by 2. +expected=$(fmt_pkt "Ether(dst='${ls2_lp1_mac}', src='${rp_ls2_mac}')/ \ + IP(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', ttl=62)/ \ + UDP(sport=53, dport=4369)") +echo ${expected} > expected +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [1 +]) + +# Disable the ls2-lp1 port. +check ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 172.16.1.2" | wc -l], [0], [0 +]) + +# Send the same packet again and it should not be delivered +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# The 2nd packet sent shound not be received. +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([2 HVs, 2 LS, 1 lport/LS, LRs connected via LS, IPv6 over IPv4, dynamic]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +# Logical network: +# Two LRs - R1 and R2 that are connected to ls-transfer in 10.0.0.0/24 +# network. R1 has a switchs ls1 (2001:db8:1::/64) connected to it. +# R2 has ls2 (2001:db8:2::/64) connected to it. + +ls1_lp1_mac="f0:00:00:01:02:03" +rp_ls1_mac="00:00:00:01:02:03" +rp_ls2_mac="00:00:00:01:02:04" +ls2_lp1_mac="f0:00:00:01:02:04" + +ls1_lp1_ip="2001:db8:1::2" +ls2_lp1_ip="2001:db8:2::2" + +check ovn-nbctl lr-add R1 +check ovn-nbctl lr-add R2 + +check ovn-nbctl ls-add ls1 +check ovn-nbctl ls-add ls2 +check ovn-nbctl ls-add ls-transfer + +# Connect ls1 to R1 +check ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 2001:db8:1::1/64 +check ovn-nbctl set Logical_Router R1 options:dynamic_neigh_routers=true + +check ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \ + options:router-port=ls1 addresses=\"$rp_ls1_mac\" + +# Connect ls2 to R2 +check ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 2001:db8:2::1/64 +check ovn-nbctl set Logical_Router R2 options:dynamic_neigh_routers=true + +check ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \ + options:router-port=ls2 addresses=\"$rp_ls2_mac\" + +# Connect R1 to R2 +check ovn-nbctl lrp-add R1 R1_ls-transfer 00:00:00:02:03:04 10.0.0.1/24 +check ovn-nbctl lrp-add R2 R2_ls-transfer 00:00:00:02:03:05 10.0.0.2/24 + +check ovn-nbctl lsp-add ls-transfer ls-transfer_r1 -- \ + set Logical_Switch_Port ls-transfer_r1 type=router \ + options:router-port=R1_ls-transfer addresses=\"router\" +check ovn-nbctl lsp-add ls-transfer ls-transfer_r2 -- \ + set Logical_Switch_Port ls-transfer_r2 type=router \ + options:router-port=R2_ls-transfer addresses=\"router\" + +AT_CHECK([ovn-nbctl lr-route-add R1 "::/0" 10.0.0.2]) +AT_CHECK([ovn-nbctl lr-route-add R2 "::/0" 10.0.0.1]) + +# Create logical port ls1-lp1 in ls1 +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip" + +# Create logical port ls2-lp1 in ls2 +check ovn-nbctl lsp-add ls2 ls2-lp1 \ +-- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +check ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +check ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +OVN_POPULATE_ARP + +# Allow some time for ovn-northd and ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +# Packet to send. +packet=$(fmt_pkt "Ether(dst='${rp_ls1_mac}', src='${ls1_lp1_mac}')/ \ + IPv6(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', hlim=64)/ \ + UDP(sport=53, dport=4369)") +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# Packet to Expect +# The TTL should be decremented by 2. +expected=$(fmt_pkt "Ether(dst='${ls2_lp1_mac}', src='${rp_ls2_mac}')/ \ + IPv6(src='${ls1_lp1_ip}', dst='${ls2_lp1_ip}', hlim=62)/ \ + UDP(sport=53, dport=4369)") +echo ${expected} > expected +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 2001:db8:2::2" | wc -l], [0], [1 +]) + +# Disable the ls2-lp1 port. +check ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false + +AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \ +grep "reg0 == 2001:db8:2::2" | wc -l], [0], [0 +]) + +# Send the same packet again and it should not be delivered +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 "$packet" + +# The 2nd packet sent shound not be received. +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP +]) + OVN_FOR_EACH_NORTHD([ AT_SETUP([2 HVs, 2 LS, 1 lport/LS, LRs connected via LS, IPv4 over IPv6, ECMP]) AT_SKIP_IF([test $HAVE_SCAPY = no])