Re: [netmod] WG Last Call: draft-ietf-netmod-acl-model-14

Mahesh Jethanandani <mjethanandani@gmail.com> Wed, 01 November 2017 23:43 UTC

Return-Path: <mjethanandani@gmail.com>
X-Original-To: netmod@ietfa.amsl.com
Delivered-To: netmod@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 2C9EC13F7D5 for <netmod@ietfa.amsl.com>; Wed, 1 Nov 2017 16:43:15 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.998
X-Spam-Level:
X-Spam-Status: No, score=-1.998 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Z_t8Hk2DFFxP for <netmod@ietfa.amsl.com>; Wed, 1 Nov 2017 16:43:11 -0700 (PDT)
Received: from mail-pf0-x242.google.com (mail-pf0-x242.google.com [IPv6:2607:f8b0:400e:c00::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 334B6138BD6 for <netmod@ietf.org>; Wed, 1 Nov 2017 16:43:11 -0700 (PDT)
Received: by mail-pf0-x242.google.com with SMTP id b85so3130109pfj.13 for <netmod@ietf.org>; Wed, 01 Nov 2017 16:43:11 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:subject:from:in-reply-to:date:cc:message-id:references :to; bh=FgpnA02Jm/tj+279oEwwslFnWxFYFTPVTIQ2qJDTjac=; b=s+BXob94MXR9V4v0/WivxmGA/Mc0WyyinJA7zCPdP3TYD3RNFf++OoRyIzdV2358F7 3xM1m8qLn9fFjMC9FidTeYS01EoXhdrIrNWfdxerFB+Mcf857a6xvbsRAk0C9zvyFBFI 8Sqsv4u3M/i0xg4LVPJALP8BEd4W7V5hO0fKOuWxeDWJlWYSAN2Ra2Wv3lhbuyVBtpSC SOSz273AFhO7/RP/X2ZgpEUw9wvjBJFmqNYuqodBGn5l9oK48B55wzalNc/EeRM3ShFX d7qkLOtDeBwU74hvYc8roj7ssTdI/yzP16/MQj8J6smIml/KHmL1AbbPD0BFtmfgY/1a 7NrQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:subject:from:in-reply-to:date:cc :message-id:references:to; bh=FgpnA02Jm/tj+279oEwwslFnWxFYFTPVTIQ2qJDTjac=; b=lyKEH4ovnlwCQktfAnOhvYtJ2+9lNS55o0o6MS3/uPyW+r1GyrIbWD0bSXRr1LyD4u 7Fs93VviCEF70pT77K8LKvVv9QIT5g0xZqxMJQk36cLI7z6CaC/WLdancnPbcR6yPiYu dkp+ViuRXrQnuRv0Sx0bp3UDfxDWQ8adFafdv/HyqODCZK++2PPXwbacP1DT7anP5Sfw 8ntmTVqvG5eyYCyeTkKxKpDBV2+TzQVK3m/onS0csMGjxZm6GYoo3JmLdXMnnI2ADJ1c sRPCQovpfnA2/8kviZBIG0q8QSAX6yyiXB9Go48nMcD5D7USDMQ2nLaPNy1ZxSl7eS8c k8rw==
X-Gm-Message-State: AMCzsaX2BwVa/lGeYjx3wxEdepJekMXwzzc3vK3UT8y2+twKAQv+eVoK K4FPcf6qBv9+cuf3kQKaXgi0zQZ2
X-Google-Smtp-Source: ABhQp+S4p/Cb3k/k2LhdpiTTxZvE+huqB62l/ux/6WCH3zjoksYBme+mKFmHe6uNlmVQ4Hl0qwsoLA==
X-Received: by 10.101.64.198 with SMTP id u6mr1541003pgp.44.1509579790555; Wed, 01 Nov 2017 16:43:10 -0700 (PDT)
Received: from [192.168.99.103] ([103.42.216.254]) by smtp.gmail.com with ESMTPSA id 125sm2791758pff.14.2017.11.01.16.43.07 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 01 Nov 2017 16:43:08 -0700 (PDT)
Content-Type: multipart/alternative; boundary="Apple-Mail=_8C4B3D5E-D3BE-433A-AEA5-5DF21A62C3D2"
Mime-Version: 1.0 (Mac OS X Mail 9.3 \(3124\))
From: Mahesh Jethanandani <mjethanandani@gmail.com>
In-Reply-To: <20171101112249.wmq4ggx2ixgn4kqo@elstar.local>
Date: Thu, 02 Nov 2017 06:13:04 +0630
Cc: Kristian Larsson <kristian@spritelink.net>, "netmod@ietf.org" <netmod@ietf.org>
Message-Id: <A55809F6-23FA-404D-BC0F-74AF11F508BF@gmail.com>
References: <51DBEB86-2482-4D37-9F97-5EEE76B38285@juniper.net> <20171031102523.GB25608@spritelink.se> <CDEF081E-C5AA-459B-8DBB-770D5065FD26@gmail.com> <20171101112249.wmq4ggx2ixgn4kqo@elstar.local>
To: Juergen Schoenwaelder <j.schoenwaelder@jacobs-university.de>
X-Mailer: Apple Mail (2.3124)
Archived-At: <https://mailarchive.ietf.org/arch/msg/netmod/lhVBwA-NL452FLxU8gXXxYlXIT4>
Subject: Re: [netmod] WG Last Call: draft-ietf-netmod-acl-model-14
X-BeenThere: netmod@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: NETMOD WG list <netmod.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/netmod>, <mailto:netmod-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/netmod/>
List-Post: <mailto:netmod@ietf.org>
List-Help: <mailto:netmod-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/netmod>, <mailto:netmod-request@ietf.org?subject=subscribe>
X-List-Received-Date: Wed, 01 Nov 2017 23:43:15 -0000

Juergen,

> On Nov 1, 2017, at 5:52 PM, Juergen Schoenwaelder <j.schoenwaelder@jacobs-university.de> wrote:
> 
> Mahesh,
> 
> I think the question is why we need to have different match containers
> for each possible feature set combination instead of having a single
> match container with groups of leafs in it marked as features. This
> would seem to cut down the size of the module and the tree diagram
> significantly. I think this will also make clients simpler sicne they
> do not have to select a certain container based on the feature set
> announced. 

The current design of match containers was chosen to allow platforms to select one container that matched what the hardware supported from a l2, l3 and ipv{4,6} perspective. I would argue that even though the overall diagram is bigger with this design, once the platform selects the container of choice, the tree and the configuration itself would be a little simpler/smaller. 

Take the case where the desired selection is l2,-l3, ipv4 and ipv6. The current tree looks like this:

        |        |  +--rw l2-l3-ipv4-ipv6-acl {l2-l3-ipv4-ipv6-acl}?
        |        |  |  +--rw destination-mac-address?        yang:mac-address
        |        |  |  +--rw destination-mac-address-mask?   yang:mac-address
        |        |  |  +--rw source-mac-address?             yang:mac-address
        |        |  |  +--rw source-mac-address-mask?        yang:mac-address
        |        |  |  +--rw ethertype?                      eth:ethertype
        |        |  |  +--rw dscp?                           inet:dscp
        |        |  |  +--rw ecn?                            uint8
        |        |  |  +--rw length?                         uint16
        |        |  |  +--rw ttl?                            uint8
        |        |  |  +--rw protocol?                       uint8
        |        |  |  +--rw source-port-range!
        |        |  |  |  +--rw lower-port    inet:port-number
        |        |  |  |  +--rw upper-port?   inet:port-number
        |        |  |  |  +--rw operation?    operator
        |        |  |  +--rw destination-port-range!
        |        |  |  |  +--rw lower-port    inet:port-number
        |        |  |  |  +--rw upper-port?   inet:port-number
        |        |  |  |  +--rw operations?   operator
        |        |  |  +--rw ihl?                            uint8
        |        |  |  +--rw flags?                          bits
        |        |  |  +--rw offset?                         uint16
        |        |  |  +--rw identification?                 uint16
        |        |  |  +--rw destination-ipv4-network?       inet:ipv4-prefix
        |        |  |  +--rw source-ipv4-network?            inet:ipv4-prefix
        |        |  |  +--rw next-header?                    uint8
        |        |  |  +--rw destination-ipv6-network?       inet:ipv6-prefix
        |        |  |  +--rw source-ipv6-network?            inet:ipv6-prefix
        |        |  |  +--rw flow-label?
        |        |  |          inet:ipv6-flow-label


whereas, if the design went with one match container with each group of leafs in their own container (to support the if-feature statement for that container), the tree would look like this:

        |        |  +--rw l2-acl {l2-acl}?
        |        |  |  +--rw destination-mac-address?        yang:mac-address
        |        |  |  +--rw destination-mac-address-mask?   yang:mac-address
        |        |  |  +--rw source-mac-address?             yang:mac-address
        |        |  |  +--rw source-mac-address-mask?        yang:mac-address
        |        |  |  +--rw ethertype?                      eth:ethertype
        |        |  +--rw ipv4-acl {ipv4-acl}?
        |        |  |  +--rw dscp?                       inet:dscp
        |        |  |  +--rw ecn?                        uint8
        |        |  |  +--rw length?                     uint16
        |        |  |  +--rw ttl?                        uint8
        |        |  |  +--rw protocol?                   uint8
        |        |  |  +--rw source-port-range!
        |        |  |  |  +--rw lower-port    inet:port-number
        |        |  |  |  +--rw upper-port?   inet:port-number
        |        |  |  |  +--rw operation?    operator
        |        |  |  +--rw destination-port-range!
        |        |  |  |  +--rw lower-port    inet:port-number
        |        |  |  |  +--rw upper-port?   inet:port-number
        |        |  |  |  +--rw operations?   operator
        |        |  |  +--rw ihl?                        uint8
        |        |  |  +--rw flags?                      bits
        |        |  |  +--rw offset?                     uint16
        |        |  |  +--rw identification?             uint16
        |        |  |  +--rw destination-ipv4-network?   inet:ipv4-prefix
        |        |  |  +--rw source-ipv4-network?        inet:ipv4-prefix
        |        |  +--rw ipv6-acl {ipv6-acl}?
        |        |  |  +--rw dscp?                       inet:dscp
        |        |  |  +--rw ecn?                        uint8
        |        |  |  +--rw length?                     uint16
        |        |  |  +--rw ttl?                        uint8
        |        |  |  +--rw protocol?                   uint8
        |        |  |  +--rw source-port-range!
        |        |  |  |  +--rw lower-port    inet:port-number
        |        |  |  |  +--rw upper-port?   inet:port-number
        |        |  |  |  +--rw operation?    operator
        |        |  |  +--rw destination-port-range!
        |        |  |  |  +--rw lower-port    inet:port-number
        |        |  |  |  +--rw upper-port?   inet:port-number
        |        |  |  |  +--rw operations?   operator
        |        |  |  +--rw next-header?                uint8
        |        |  |  +--rw destination-ipv6-network?   inet:ipv6-prefix
        |        |  |  +--rw source-ipv6-network?        inet:ipv6-prefix
        |        |  |  +--rw flow-label?                 inet:ipv6-flow-label

The difference though is small and comes down to a preference. Select one feature statement and get one container with everything in it, or define multiple feature statements and assemble together the pieces to define the ACE entry.

> BTW, how do I filter on TCP flags in combination with
> a source IP address? There seem to be reasonable combinations of
> features not even covered.

If the platform has declared support for feature that includes ipv4 (and/or ipv6) and tcp-acl, for a given ACE entry, it should be able to define a match filter that includes both the source IP address and the TCP flags. Do you see something that prevents it?

Thanks.

> 
> /js
> 
> On Wed, Nov 01, 2017 at 05:13:18PM +0630, Mahesh Jethanandani wrote:
>> Kristian,
>> 
>> I think there is confusion in how the ACL model is going to be implemented by vendors and used by customers.
>> 
>> As Eliot alluded to, the model is trying to address the issue of the capabilities of each platform as they exist across the industry but also within each vendor. So the first thing an implementation would do is to pick which feature they do support. A low end platform that supports only layer 2 ACL will pick l2-acl as their feature, while a high end router capable of support l2 and l3, ipv4 and ipv6 ACL will declare l2-l3-ipv4-ipv6 as the feature they support. That pretty much takes out all the other containers in the matches container. The additional features they might want to choose include support for TCP, UDP and ICMP. For a high end router this boils down to having definitions for
>> 
>> - ethernet
>> - ipv4
>> - ipv6
>> - tcp
>> - udp
>> - icmp
>> 
>> which is the list you have in mind, but this time making sure that the platform is capable of supporting each one of the definitions. Imagine if the low end platform advertised a model for all the above capabilities only to reject them when you tried to configure a ipv6 address that it already knows it cannot support.
>> 
>> Similarly the condition on tcp/udp/icmp container is to make sure the platform is capable of supporting them. Only if the platform declares tcp-acl, udp-acl, and icmp-acl feature, will those containers be visible from a configuration perspective.
>> 
>> The acl-type is used as a check to make sure the user is aware what kind of ACL the platform supports and the ACL they are trying to configure matches the acl-type. If the platform declared the feature l2-acl and if the user tries to set the ACL type to l2-l3-ipv4-ipv6 then the configuration would be rejected. In the Linux/nftables case, the platform should declare the feature l2-l3-ipv4-ipv6, tcp-acl, udp-acl, and icmp-acl if that is what it wants to support. The interface attachment point has been defined but it is not mandatory that a configuration has to define it. So if in Linux, the ACL list is global, one would not define a attachment point, which implies it is a global list.
>> 
>> I will take a look at the remaining issues/comments you raise, but I wanted to make sure that the overall design of the model was clear, which from this email I can only guess could be made more clear.
>> 
>> Cheers.
>> 
>>> On Oct 31, 2017, at 4:55 PM, Kristian Larsson <kristian@spritelink.net> wrote:
>>> 
>>> On Fri, Oct 20, 2017 at 09:37:04PM +0000, Kent Watsen wrote:
>>>> 
>>>> All,
>>>> 
>>>> This starts a two-week working group last call on
>>>> draft-ietf-netmod-acl-model-14.
>>>> 
>>>> The working group last call ends on November 3.
>>>> Please send your comments to the netmod mailing list.
>>> 
>>> 
>>> I initially read this draft (or an older version) close to a year
>>> ago and meant to give feedback back then. I first wanted to read
>>> up on the list archive on any previous discussions (since the
>>> initial draft is reaaaally old) but ran out of time.
>>> 
>>> I have still not read all previous discussions (there are 687
>>> emails when searching for 'acl' in the archive) and therefore
>>> I'll apologise beforehand as I'm bound to reiterate questions or
>>> topics that have been brought up already. I'd be grateful if
>>> those with the history in memory can help me by providing
>>> references to the list archive.
>>> 
>>> Anyway, to the model. There's this concept of unified ACLs. I
>>> see two dimensions:
>>> * mixed layer ACLs, where we match on headers in different
>>>  layers in the OSI/TCP/IP model, like ethernet and ipv4
>>> * mixed family ACLs, where we in one ACL match on different
>>>  protocols in the same OSI model layer, like both IPv4 and
>>>  IPv6. However, within one ACE we always just match on one
>>>  protocol.
>>> 
>>> What I don't understand is why under the matches container there
>>> are these other containers, like l2-acl, ipv4-acl, ipv6-acl,
>>> l2-l3-ipv4-acl etc? Depending on the type I would input the
>>> ethernet matches in different places. That seems suboptimal.  If
>>> we wanted an ACL type per AFI then we could have just created a
>>> top level list per AFI instead of trying to pretend they are
>>> unified by putting them in one list and then splitting it up
>>> further down under the matches container. In that case, the
>>> attachment points would also have been made much simpler with
>>> just a single reference instead of having two leaves like the
>>> current model.
>>> 
>>> It seems to me that this can be modeled in a more elegant way by
>>> having the following containers under matches:
>>> * ethernet
>>> * ipv4
>>> * ipv6
>>> * tcp
>>> * udp
>>> * icmp
>>> 
>>> The ethernet containers presence is conditioned on the acl-type
>>> being one of l2-acl, l2-l3-ipv4-acl, l2-l3-ipv6-acl or
>>> l2-l3-ipv4-ipv6-acl.
>>> 
>>> The ipv4 container is conditioned on the acl-type being one of
>>> ipv4-acl, l2-l3-ipv4-acl, l2-l3-ipv4-ipv6-acl.
>>> 
>>> The ipv6 container is conditioned on the acl-type being one of
>>> ipv6-acl, l2-l3-ipv6-acl, l2-l3-ipv4-ipv6-acl.
>>> 
>>> In addition, there is a condition that prevents both the IPv4 and
>>> IPv6 container being present at the same time, since we can't
>>> match on both of them with the same ACE. Another ACE in the same
>>> ACL can however match on something else.
>>> 
>>> Similarly, there's a condition on tcp, udp and icmp preventing
>>> them all from being configured. Perhaps it should just look
>>> differently, like a choice? Or maybe a match on protocol=tcp/udp
>>> and then we have a container for tcp-flags etc.  We can delve
>>> into the details later, I just want to first understand why the
>>> current model is thought of as a good approach for expressing
>>> this data? IMHO it's awkward.
>>> 
>>> 
>>> This brings us to the acl-type. It seems to me that this is
>>> primarily for being able to do YANG validation when a device does
>>> NOT support a unified model. I.e. if Linux nftables was all we
>>> wanted to model, then we wouldn't need this and the only
>>> (implied) acl-type would be l2-l3-ipv4-acl. In reality though, we
>>> need acl-type because most current network devices out there have
>>> per-AFI types and we want to be able to say:
>>> * this interface attachment point can only do ipv4-acl
>>> And still be able to validate the data based on the YANG model.
>>> Is this correct? It seems like one hell of a design trade-off to
>>> be able to achieve that. Wouldn't we be better off with actually
>>> having different list of ACLs, again vastly simplifying the
>>> attachment points and making data validation much easier?
>>> 
>>> If all we want to do is limit so the source address can't be
>>> configured to be an IPv4 address when the destination address is
>>> IPv6 I think it's better to have a "family" leaf per ACE that
>>> defines ipv4 or ipv6, or just let the ipv4 and ipv6 containers be
>>> mutually exclusive through other means, as I eluded to
>>> previously.
>>> 
>>> 
>>> The current attachment points seem to be a list of interfaces
>>> using the interface-ref type from ietf-interfaces. I guess there
>>> was a reason we don't augment the ietf-interfaces module. What if
>>> the device is Linux with nftables? There's no attachment to an
>>> interface as it's a global rule list. I think this is
>>> conceptually the same as attaching the same ACL on all interfaces
>>> but that would be an awkward way of describing a global
>>> attachment point. Would it not be better to if-feature wrap this
>>> and allow a global attachment point which has a more direct
>>> mapping to nftables? The same is of course for any device type
>>> with a global table, like most firewalls.
>>> 
>>> 
>>> 
>>> Other issues / questions;
>>> * in 1. mentions it can be used in routing protocols - is
>>>  that really intended?
>>> * in 1. says "In ordet to apply an ACL to any attachment
>>>  point, vendors would have to augment the ACL YANG model", is
>>>  this really true? Surely we have standard attachment points.
>>> * in 1. the examples of use start with policy based
>>>  routing and then firewalls. ISTM that ACLs are primarily used for
>>>  "packet filters" so it's weird it's not even included.
>>>  Firewall often implies statefulness, which is not really what
>>>  we are dealing with here and PBR is not nearly as use as
>>>  packet filters. Maybe everyone knows this already, but then
>>>  why write anything at all?
>>> * in 1. "in case vendors supports it, metadata matches apply.." why
>>>  include a condition on if the vendors supports it? this is
>>>  true for anything, "in case the vendor supports it, the BGP
>>>  routing protocol works this way...". I think we can require
>>>  certain metadata matches in the model, or just do if-feature,
>>>  but constantly prefixing everything with a "in case vendor.."
>>>  is unnecessary IMHO
>>> * in 1. ISTM: s/networked devices/networking device/
>>> * in 3. "each ACE has a group of match criteria and a group of action
>>>  criteria" - no, it does not, actions are not a criteria!?
>>> * indent is mix of tabs and spaces
>>> * the icmp-off action leaf is IMHO weirdly modeled and it's a
>>>  weird option in itself - can you point to vendors implementing
>>>  similar options? this seems doable by just having an ACE match
>>>  on ICMP and action=drop
>>> * why eth-acl vs l2-acl. this is mixing apples and pears. L2 is
>>>  a layer in the TCP/IP model whereas ethernet is one
>>>  implementation of an L2 protocol. Why name the identify
>>>  eth-acl and the match container l2-acl?
>>> * why have the "acl-sets" container? why not just have the list
>>>  directly?
>>> * the leafrefs in the interface-acl grouping are relative making
>>>  it impossible to re-use the grouping at a different "depth"
>>> * letting the matched-packets be EITHER per-interface per-ACE OR
>>>  per-ACE across all interfaces seems insane. We have to know
>>>  what we are getting back. Better to have separate counters
>>>  then and let vendor fill in one or the other? Or declare
>>>  deviations? Curreny mode is not useful at all.
>>> 
>>> Again, apologies for my ignorance.
>>> 
>>> Kind regards,
>>>  Kristian.
>>> 
>>> 
>>> -- 
>>> Kristian Larsson                                        KLL-RIPE
>>> +46 704 264511                                kll@spritelink.net
>>> 
>>> _______________________________________________
>>> netmod mailing list
>>> netmod@ietf.org
>>> https://www.ietf.org/mailman/listinfo/netmod
>> 
>> Mahesh Jethanandani
>> mjethanandani@gmail.com
>> 
>> _______________________________________________
>> netmod mailing list
>> netmod@ietf.org
>> https://www.ietf.org/mailman/listinfo/netmod
> 
> -- 
> Juergen Schoenwaelder           Jacobs University Bremen gGmbH
> Phone: +49 421 200 3587         Campus Ring 1 | 28759 Bremen | Germany
> Fax:   +49 421 200 3103         <http://www.jacobs-university.de/>

Mahesh Jethanandani
mjethanandani@gmail.com