[ovs-dev] SFC summary?

Ryan Moats rmoats at us.ibm.com
Mon Jun 27 15:46:20 UTC 2016


Inline in the front half of the message...

I'm wondering if it might be time to restart the thread
because the accumulated reply history in the message is
getting a bit unwieldy...

John McDowall <jmcdowall at paloaltonetworks.com> wrote on 06/27/2016 10:21:47
AM:

> From: John McDowall <jmcdowall at paloaltonetworks.com>
> To: Ryan Moats/Omaha/IBM at IBMUS
> Cc: "dev at openvswitch.org" <dev at openvswitch.org>
> Date: 06/27/2016 10:22 AM
> Subject: Re: [ovs-dev] SFC summary?
>
> Ryan,
>
> Getting clearer. Let me try to parse out a few more items.
>
> When you talk about M-T are you talking about have a VNF instance
> handle M-T or talking about the OVS/OVN service chaining infra-
> structure handling M-T? Just want to make sure we are talking about
> the same problem.

While I'm not sure I make a distinction, I'm talking about having
the infrastructure in place so that the VNF can be M-T.

> I have the multi-stage ppg coded, I just need to bring up another
> VNF to test it, I think it I will work as you suggested. ‘
>
> BTW: I am testing currently without Openstack – just ovs/ovn so the
> UUID’s do not have the Openstack naming conventions for the UUIDs.

Ah, ok, then nevermind my UUID statements ...

> My current table structure is:
>
>   PIPELINE_STAGE(SWITCH, IN,  PORT_SEC_L2,    0, "ls_in_port_sec_l2") \
>   PIPELINE_STAGE(SWITCH, IN,  PORT_SEC_IP,    1, "ls_in_port_sec_ip") \
>   PIPELINE_STAGE(SWITCH, IN,  PORT_SEC_ND,    2, "ls_in_port_sec_nd") \
>   PIPELINE_STAGE(SWITCH, IN,  PRE_ACL,        3, "ls_in_pre_acl") \
>   PIPELINE_STAGE(SWITCH, IN,  ACL,            4, "ls_in_acl") \
>   PIPELINE_STAGE(SWITCH, IN,  ARP_RSP,        5, "ls_in_arp_rsp") \
>   PIPELINE_STAGE(SWITCH, IN,  CHAIN,          6, "ls_in_chain") \
>   PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,        7, "ls_in_l2_lkup") \
> I thing you are suggesting that the FC rules go into the ACL table
> and we create a new action that sends the flows into the ls-in-chain
> table, I am a little fuzzy on how that would work.

Not exactly, I'm suggesting that the FC rules go into the ACL table and
rhr the action be that we record the first port pair group as metadata
so that we can use it in a table 6.

> I would like to try and focus on the following items first ( not
> that L2/L3 and load balancing are not important), I just have
> trouble juggling too many items at the same time :-).
> Agree on basic pipeline model/architecture
> Resolve how to implement the FC/ACL model and implement
> Resolve the M-T/S-T design
> Thoughts?

In my mind, this breaks up a little bit differently:
(1) pipeline model, load balancing, and FC/ACL go together
because they are (in my mind at least) very simple based on
what I'm proposing...

(2) M-T headaches in table 0 (for successive stages of a
multi PPG chain) and table 4 (for first stage of a multi
PPG chain)

I will agree that my points about L2 and L3 VNFs can be ignored
until later, I was just pointing to where I expect them to show up

Ryan

> John
>
> From: Ryan Moats <rmoats at us.ibm.com>
> Date: Saturday, June 25, 2016 at 8:28 PM
> To: John McDowall <jmcdowall at paloaltonetworks.com>
> Cc: "dev at openvswitch.org" <dev at openvswitch.org>
> Subject: Re: [ovs-dev] SFC summary?
>
> "dev" <dev-bounces at openvswitch.org> wrote on 06/25/2016 08:38:09 PM:
>
> > From: John McDowall <jmcdowall at paloaltonetworks.com>
> > To: "dev at openvswitch.org" <dev at openvswitch.org>
> > Date: 06/25/2016 08:38 PM
> > Subject: Re: [ovs-dev] SFC summary?
> > Sent by: "dev" <dev-bounces at openvswitch.org>
> >
> > Ryan,
> >
> > Thanks for putting together the summary - I have a simple VNF case
> > working with a BiW VNF - very minimal testing. I have added the
> > logic to support multiple port-pairs but have not tested yet. I have
> > included a dump of the flows. The code is posted to https://
> > github.com/doonhammer/ovs there is conflict with ovn-northd.c that I
> > need to look at but apart from that it is sync'ed with main.
> >
> > I like the idea of using the ACL table/feature for the flow-
> > classifier and I think the networking-sfc team does too. I am just
> > not quite sure how to implement. I create a new table "ls_in_chain"
> > there I create four rule sets for each port-chain, 2 if the flow is
> > treated as uni-directional. The lowest priority rule just steers the
> > traffic into the port chain, using the flow-calssifer rules, the
> > highest priority rule steers traffic through the port chain. So the
> > first rule would live in the ACL table in your model and the action
> > would send it to the start of the port-chain rule - somehow - not
> > clear how to do that.
> >
> > I am struggling to understand how this breaks the pipeline model -
> > just my lack of understanding.  So any help/suggestions would be
> appreciated.
> >
> > The other big items IMHO are:
> > Load-balancing within port-pairs, in port-pair-groups
> > L2/L3 VNF Support
> >
> > As always suggestions/guidence is welcome.
> >
> > Regards
> >
> > John
> >
> > Snapshot of ovn-sbctl dump-flows:
>
> The reason I was concerned about breaking the pipeline model
> can be summed up in that I misunderstood the "output"
> statements in table 6 - I got the mistaken impression that
> the packets were being punted out to OF ports (skipping
> the egress pipeline and so I was trying to figure out how
> having VNFs on different chassis was going to work.  The
> good news is that looking at the below, I see I was operating
> under a misconception. My apologies.
>
> Now, having said the above, I do see some things that
> I want to address:
> 1. I think we want to break the SFC processing into two table
> on the ingress side (and I'll explain in more detail below).
> 2. I see some things done in places that I don't expect
> 3. There appears to be some pieces of the current pipeline
> missing.
> 4. The logical flow rules below are still single network
> and therefore single tenant. I'd like to see what a multi-tenant
> with a shared NFV would look like.
>
> So I'm going to walk through and put in what I am thinking
> of and hopefully that will explain how I propose to handle
> the ACLs, the selection of PPs from a PPG, and handle a
> multistage chain.
>
> > datapath: 6d684845-2a66-43e6-913e-f559ee66ade7  Pipeline: ingress
> >   table=0(ls_in_port_sec_l2), priority=  100, match=(eth.src[40]),
> > action=(drop;)
> >   table=0(ls_in_port_sec_l2), priority=  100, match=(vlan.present),
> > action=(drop;)
>
> For the next four, typically the networking-ovn mechanism driver
> creates a logical port in the NB DB that corresponds to the neutron
> port, so I'd expect to see four logical ports in the NB DB with
> external-ids set to things like: {"neutron:port_name"="sw1-lport1"}
> and then I'd expect to see the name of the nb logical port (which
> is typically an UUID) as the inport below. I also set the PPG of
> the next port pair group, to avoid needing an extra table later on.
>
> Now, for L2 VNFs, I'd expect additional information about vlans
> and MAC addresses in rules that are higher than priority 100.
> For L3 VNFs, I'd also expect to see rules about MAC addresses.
>
> This is also where I struggle to make multi-tenancy work
> as these rules identify the inport with the logical datapath.
> At this point, I've not worked out a way to make multi-tenancy work
> unless there is metadata passed to and from the VNF to indentify
> the correct logical datapath to use and in that case, these rules
> will need to add that metadata to the match criteria. If you have
> a counter-example, I'd be happy to see it.
>
> table=0(ls_in_port_sec_l2), priority=50,
> match=(inport == "<PP from first PPG>"),
> action=(ppg=<UUID of Second PPG in PC>; next;)
> ...
>
> >   table=0(ls_in_port_sec_l2), priority=   50, match=(inport == "sw1-
> > lportf1"), action=(next;)
> >   table=0(ls_in_port_sec_l2), priority=   50, match=(inport == "sw1-
> > lportf2"), action=(next;)
> >   table=0(ls_in_port_sec_l2), priority=   50, match=(inport == "sw1-
> > lport1"), action=(next;)
> >   table=0(ls_in_port_sec_l2), priority=   50, match=(inport == "sw1-
> > lport2"), action=(next;)
> >   table=0(ls_in_port_sec_l2), priority=   50, match=(inport == "sw1-
> > lportf1"), action=(next;)
> >   table=0(ls_in_port_sec_l2), priority=   50, match=(inport == "sw1-
> > lportf2"), action=(next;)
>
> For L3 VNFs, I'd expect some entries in table 1 about the IP address
> of the VNF - things like
>
> priority=90, match=(inport == \"<inport>\" && eth.src == <VNF MAC>
> && ip4.src == {<VNF IPaddr>}), action=(next;)
> priority=80, match=(inport == \"<inport>\" && eth.src == <VNF MAC>
> && ip4), action=(drop;)
>
> >   table=1(ls_in_port_sec_ip), priority=    0, match=(1), action=(next;)
>
> I also would expect to see some arp related items in table 2 for
> L2 and L3 VNFs like:
>
> priority=90, match=(inport == \"<inport>\" && eth.src == <VNF MAC>
> && arp.sha == <VNF_MAC> && (arp.spa == {<VNF IPaddr>})), action=(next;)
> priority=80, match=(inport == \"<inport>\" && (arp || nd)), action=
(drop;)
>
> >   table=2(ls_in_port_sec_nd), priority=    0, match=(1), action=(next;)
>
> For table 3, now that conntrack is part of the ACL processing, I would
> expect to see something like the following:
> priority=100, match=ip, action=(ct_next;)
>
> >   table=3(   ls_in_pre_acl), priority=    0, match=(1), action=(next;)
>
> Table 4 is where your ACL match comes in for traffic entering the first
> port of the port chain, and what I set here is the port_pair_group,
> because I want to put load balancing in the SFC table below.  I'm also
> going to change my idea, because looking at this some more, I can
> solve my metadata concern if I move the PPG/PP selection logic to the
> ingress pipeline. Now, I'd also expect to see a bunch of conntrack
> rules that I'm not cover, as I want to concentrate on the ones specific
> to SFC (in this example, I'm assuming an ACL based on a classifier
> for HTTP, and the details might need to be corrected)
>
> priority=2002, match=(ct.new && (tcp && dst.port=80)),
> action=(ppg=<UUID of First PPG in PC>; ct_commit; next;)
>
> >   table=4(       ls_in_acl), priority=    0, match=(1), action=(next;)
>
> I'm good with table 5 entries
>
> >   table=5(   ls_in_arp_rsp), priority=   50, match=(arp.tpa == 172.
> > 16.33.2 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 52:54:
> > 00:bd:04:28; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha
> > = 52:54:00:bd:04:28; arp.tpa = arp.spa; arp.spa = 172.16.33.2;
> > outport = inport; inport = ""; /* Allow sending out inport. */ output;)
> >   table=5(   ls_in_arp_rsp), priority=   50, match=(arp.tpa == 172.
> > 16.33.3 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 52:54:
> > 00:20:47:62; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha
> > = 52:54:00:20:47:62; arp.tpa = arp.spa; arp.spa = 172.16.33.3;
> > outport = inport; inport = ""; /* Allow sending out inport. */ output;)
> >   table=5(   ls_in_arp_rsp), priority=    0, match=(1), action=(next;)
>
> Table 6 (ls_sfc stage) is where I select the output port, either
> via a select group for load balancing or via a direct set if the
> PPG has only a single PP in it.
>
> table=6( ls_sfc), priority=150, match=(ppg=<UUID of First PPG in PC>),
> action=(group_id=1,type==select,
> bucket="outport=\"<inport of first PP in PPG>\", output,
> bucket="outport=\"<inport of second PP in PPG>\", output;
> ... [as many buckets as there are PPs in the first PPG])
> table=6( ls_sfc), priority=150, match=(ppg=<UUID of Second PPG in PC>),
> action=(group_id=2,type==select,
> bucket="outport=\"<inport of first PP in PPG>\", output,
> bucket="outport=\"<inport of second PP in PPG>\", output;
> ... [as many buckets as there are PPs in the second PPG])
> ... as many entries as there are PPGs
> table=6( ls_sfc) priority=150, match=(ppg=<UUID of Third PPG in PC>),
> action-(outport="<inport of PP in Third PPG>", output;)
> table=6( ls_sfc) priority=1, match=(1), action=(next;)
>
> >   table=6(     ls_in_chain), priority=  150, match=(ip4.dst == 172.
> > 16.33.3 && inport == "sw1-lportf1"), action=(outport = "sw1-
> lport1"; output;)
> >   table=6(     ls_in_chain), priority=  150, match=(ip4.src == 172.
> > 16.33.3 && inport == "sw1-lport1"), action=(outport = "sw1-
> lportf1"; output;)
> >   table=6(     ls_in_chain), priority=  100, match=(inport == "sw1-
> > lportf2" && ip4.dst == 172.16.33.2), action=(outport = "sw1-
> lport2"; output;)
> >   table=6(     ls_in_chain), priority=  100, match=(inport == "sw1-
> > lportf2" && ip4.dst == 172.16.33.3), action=(outport = "sw1-
> lport1"; output;)
> >   table=6(     ls_in_chain), priority=  100, match=(ip4.dst == 172.
> > 16.33.3), action=(outport = "sw1-lportf2"; output;)
> >   table=6(     ls_in_chain), priority=    0, match=(1), action=(next;)
>
> I think the below is ok.
>
> >   table=7(   ls_in_l2_lkup), priority=  100, match=(eth.mcast),
> > action=(outport = "_MC_flood"; output;)
> >   table=7(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 52:
> > 54:00:20:47:62), action=(outport = "sw1-lport1"; output;)
> >   table=7(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 52:
> > 54:00:a8:01:fa), action=(outport = "sw1-lportf2"; output;)
> >   table=7(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 52:
> > 54:00:af:74:f5), action=(outport = "sw1-lportf1"; output;)
> >   table=7(   ls_in_l2_lkup), priority=   50, match=(eth.dst == 52:
> > 54:00:bd:04:28), action=(outport = "sw1-lport2"; output;)
> > Datapath: 6d684845-2a66-43e6-913e-f559ee66ade7  Pipeline: egress
>
> Does that help or does it make things "clear as mud?"
>
> Ryan


More information about the dev mailing list