Juergen,

> On Nov 1, 2017, at 5:52 PM, Juergen Schoenwaelder 
> <j.schoenwael...@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 <krist...@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                                k...@spritelink.net
>>> 
>>> _______________________________________________
>>> netmod mailing list
>>> netmod@ietf.org
>>> https://www.ietf.org/mailman/listinfo/netmod
>> 
>> Mahesh Jethanandani
>> mjethanand...@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
mjethanand...@gmail.com

_______________________________________________
netmod mailing list
netmod@ietf.org
https://www.ietf.org/mailman/listinfo/netmod

Reply via email to