From patchwork Tue Sep 8 08:43:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1359603 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=JCKP2OxG; dkim-atps=neutral Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BlzFN1bXKz9sPB for ; Tue, 8 Sep 2020 18:43:20 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 73A11866F2; Tue, 8 Sep 2020 08:43:18 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hsGjZMwff1yx; Tue, 8 Sep 2020 08:43:16 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 2B01E866AD; Tue, 8 Sep 2020 08:43:16 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0329CC088B; Tue, 8 Sep 2020 08:43:16 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id CD5BDC0052 for ; Tue, 8 Sep 2020 08:43:14 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id C2349868B4 for ; Tue, 8 Sep 2020 08:43:14 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9U3LyEKbXofq for ; Tue, 8 Sep 2020 08:43:13 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by whitealder.osuosl.org (Postfix) with ESMTPS id 9EB0F868C5 for ; Tue, 8 Sep 2020 08:43:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1599554592; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:content-type:content-type; bh=aQDIMK8sUIiDJdBua+f7Aa3MKBPENCFNwIN4vgGyNk8=; b=JCKP2OxGoGFu/mzPqu6/7N+G3+oJ7eZYK6rfipyFFopvRrH8h8354OX3ccIcuk2+i3/O9m Gfk4hNPmY8jO1pD2+qb5yjVK2C5c9QlLLK4/ptq+D75AMPM65Ba3OUGT0TPKT930Sxe2My 86K+wpE6nu8kECc3Hqy6frqMyzpGf84= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-479-dXJJJ9uGMCCMnRLbayrOjg-1; Tue, 08 Sep 2020 04:43:08 -0400 X-MC-Unique: dXJJJ9uGMCCMnRLbayrOjg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5D0DE85C733 for ; Tue, 8 Sep 2020 08:43:07 +0000 (UTC) Received: from dceara.remote.csb (ovpn-114-191.ams2.redhat.com [10.36.114.191]) by smtp.corp.redhat.com (Postfix) with ESMTP id D1D4E27C29 for ; Tue, 8 Sep 2020 08:43:06 +0000 (UTC) From: Dumitru Ceara To: dev@openvswitch.org Date: Tue, 8 Sep 2020 10:43:03 +0200 Message-Id: <1599554583-1698-1-git-send-email-dceara@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=dceara@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn v2] ovn-northd: Drop IP packets destined to router owned IPs (after NAT). X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" OVN was dropping IP packets destined to IPs owned by logical routers but only if those IPs are not used for SNAT rules. However, if a packet doesn't match an existing NAT session and its destination is still a router owned IP, it can be safely dropped. Otherwise it will trigger an unnecessary packet-in in stage lr_in_arp_request. To achieve that we add flows that drop traffic to router owned IPs in table lr_in_arp_resolve. Reported-by: Tim Rozet Reported-at: https://bugzilla.redhat.com/1876174 Signed-off-by: Dumitru Ceara --- V2: - rebased changes. --- northd/ovn-northd.8.xml | 24 ++++++++++++ northd/ovn-northd.c | 48 ++++++++++++++++++++++++ tests/ovn.at | 98 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 168 insertions(+), 2 deletions(-) diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 989e364..b9170fc 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -2943,6 +2943,30 @@ outport = P;
  • + Traffic with IP destination an address owned by the router should be + dropped. Such traffic is normally dropped in ingress table + IP Input except for IPs that are also shared with SNAT + rules. However, if there was no unSNAT operation that happened + successfully until this point in the pipeline and the destination IP + of the packet is still a router owned IP, the packets can be safely + dropped. +

    + +

    + A priority-1 logical flow with match ip4.dst = {..} + matches on traffic destined to router owned IPv4 addresses and + has action drop;. +

    + +

    + A priority-1 logical flow with match ip6.dst = {..} + matches on traffic destined to router owned IPv4 addresses and + has action drop;. +

    +
  • + +
  • +

    Dynamic MAC bindings. These flows resolve MAC-to-IP bindings that have become known dynamically through ARP or neighbor discovery. (The ingress table ARP Request will diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 681c008..6e063ac 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -10588,6 +10588,54 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, } } + /* Drop IP traffic destined to router owned IPs. Part of it is dropped + * in stage "lr_in_ip_input" but traffic that could have been unSNATed + * but didn't match any existing session might still end up here. + */ + HMAP_FOR_EACH (op, key_node, ports) { + if (!op->nbrp) { + continue; + } + + if (op->lrp_networks.n_ipv4_addrs) { + ds_clear(&match); + ds_put_cstr(&match, "ip4.dst == {"); + + for (size_t i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) { + ds_put_format(&match, "%s, ", + op->lrp_networks.ipv4_addrs[i].addr_s); + } + + ds_chomp(&match, ' '); + ds_chomp(&match, ','); + ds_put_char(&match, '}'); + + /* Drop traffic with IP.dest == router-ip. */ + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ARP_RESOLVE, 1, + ds_cstr(&match), "drop;", + &op->nbrp->header_); + } + + if (op->lrp_networks.n_ipv6_addrs) { + ds_clear(&match); + ds_put_cstr(&match, "ip6.dst == {"); + + for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) { + ds_put_format(&match, "%s, ", + op->lrp_networks.ipv6_addrs[i].addr_s); + } + + ds_chomp(&match, ' '); + ds_chomp(&match, ','); + ds_put_char(&match, '}'); + + /* Drop traffic with IP.dest == router-ip. */ + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ARP_RESOLVE, 1, + ds_cstr(&match), "drop;", + &op->nbrp->header_); + } + } + HMAP_FOR_EACH (od, key_node, datapaths) { if (!od->nbr) { continue; diff --git a/tests/ovn.at b/tests/ovn.at index 1fe34b7..0e14dfa 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -21377,8 +21377,12 @@ OVN_POPULATE_ARP ovn-nbctl --wait=hv sync -AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.0.1], [1], []) -AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.0.2], [1], []) +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.0.1], [0], [dnl + table=13(lr_in_arp_resolve ), priority=1 , match=(ip4.dst == {10.0.0.1}), action=(drop;) +]) +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.0.2], [0], [dnl + table=13(lr_in_arp_resolve ), priority=1 , match=(ip4.dst == {10.0.0.2}), action=(drop;) +]) ip_to_hex() { printf "%02x%02x%02x%02x" "$@" @@ -21447,6 +21451,96 @@ OVS_WAIT_UNTIL([test x$(as hv1 ovn-appctl -t ovn-controller debug/status) = "xru OVN_CLEANUP([hv1]) AT_CLEANUP +# Test dropping traffic destined to router owned IPs. +AT_SETUP([ovn -- gateway router drop traffic for own IPs]) +ovn_start + +ovn-nbctl lr-add r1 -- set logical_router r1 options:chassis=hv1 +ovn-nbctl ls-add s1 + +# Connnect r1 to s1. +ovn-nbctl lrp-add r1 lrp-r1-s1 00:00:00:00:01:01 10.0.1.1/24 +ovn-nbctl lsp-add s1 lsp-s1-r1 -- set Logical_Switch_Port lsp-s1-r1 type=router \ + options:router-port=lrp-r1-s1 addresses=router + +# Create logical port p1 in s1 +ovn-nbctl lsp-add s1 p1 \ +-- lsp-set-addresses p1 "f0:00:00:00:01:02 10.0.1.2" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=p1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/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 + +ovn-nbctl --wait=hv sync + +sw_key=$(ovn-sbctl --bare --columns tunnel_key list datapath_binding r1) + +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.1.1], [0], [dnl + table=13(lr_in_arp_resolve ), priority=1 , match=(ip4.dst == {10.0.1.1}), action=(drop;) +]) + +ip_to_hex() { + printf "%02x%02x%02x%02x" "$@" +} + +# Send ip packets from p1 to lrp-r1-s1 +src_mac="f00000000102" +dst_mac="000000000101" +src_ip=`ip_to_hex 10 0 1 2` +dst_ip=`ip_to_hex 10 0 1 1` +packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet + +# No packet-ins should reach ovn-controller. +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep "actions=controller" | grep -v n_packets=0 -c], [1], [dnl +0 +]) + +# The packet should have been dropped in the lr_in_ip_input stage. +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=11, n_packets=1,.* priority=60,ip,metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl +1 +]) + +# Use the router IP as SNAT IP. +ovn-nbctl set logical_router r1 options:lb_force_snat_ip=10.0.1.1 +ovn-nbctl --wait=hv sync + +# Send ip packets from p1 to lrp-r1-s1 +src_mac="f00000000102" +dst_mac="000000000101" +src_ip=`ip_to_hex 10 0 1 2` +dst_ip=`ip_to_hex 10 0 1 1` +packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet + +# Even after configuring a router owned IP for SNAT, no packet-ins should +# reach ovn-controller. +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep "actions=controller" | grep -v n_packets=0 -c], [1], [dnl +0 +]) + +# The packet should've been dropped in the lr_in_arp_resolve stage. +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=21, n_packets=1,.* priority=1,ip,metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl +1 +]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP + AT_SETUP([ovn -- nb_cfg timestamp]) ovn_start