Ben, Thanks for the thorough review, I will update the code and resubmit the patch. Any thoughts on the general approach to service chaining etc?
Regards John On 2/3/17, 2:10 PM, "Ben Pfaff" <b...@ovn.org> wrote: On Thu, Feb 02, 2017 at 03:22:56PM -0800, jmcdow...@paloaltonetworks.com wrote: > From: John McDowall <jmcdow...@paloaltonetworks.com> > > This patchset is the first round at having Service Function Chaining > functionality through OVN. The implementation is done entirely > on the northbound side of OVN. It is a bump on the wire implementation, > so no attempt is being made in keeping state while packets visit each > hop of the chain. ACLs are used as the classifiers, with the augmentation > of action SFC, as well as option column. Thanks for working on this! Sorry it's taken so long to review. cmp_port_pair_groups() treats two pair groups as equal if either one of them has no keys, but this violates transitivity (see https://urldefense.proofpoint.com/v2/url?u=https-3A__en.wikipedia.org_wiki_Comparison-5Fsort&d=DwIBAg&c=V9IgWpI5PvzTw83UyHGVSoW3Uc1MFWe5J8PTfkrzVSo&r=vZ6VUDaavDpfOdPQrz1ED54jEjvAE36A8TVJroVlrOQ&m=D8WTzjM4eBLAIUSaMpsuNQPXOo94n7zg2ZjpkjdkW64&s=BhGNi3da1UI7sRkk29-zyejanKHyZPF_ac-fm2Ctnis&e= ). Example: if 0 is a pair group with no keys and x and y are arbitrary pair groups, then this function will conclude that x <= 0 and 0 <= y. By transitivity, we would also have x <= y, but that's a contradiction because x and y are arbitrary. I suggest that empty pair groups should sort as less than nonempty ones, e.g.: @@ -2772,8 +2772,10 @@ cmp_port_pair_groups(const void *ppg1_, const void *ppg2_) const struct nbrec_logical_port_pair_group *ppg1 = *ppg1p; const struct nbrec_logical_port_pair_group *ppg2 = *ppg2p; - if (ppg1->n_sortkey == 0 || ppg2->n_sortkey == 0) { - return 0; + if (ppg1->n_sortkey == 0) { + return ppg2->n_sortkey == 0 ? -1 : 0; + } else if (ppg2->n_sortkey == 0) { + return 1; } const int64_t key1 = ppg1->sortkey[0]; ovn-northd.c has some new uses of VLOG without rate-limiters. These should probably be rate-limited, like most VLOG calls in ovn-northd. VLOG messages shouldn't include a new-line since VLOG takes care of that itself. The code has lots of lines longer than the coding style suggested limit of 79 columns. Comments should generally begin with a capital letter and end with a period. In build_chain_classifier_entry(), qsort() is a remarkably expensive way to find the smallest element in an array. In build_chain_classifier_entry(), it's strange to have "" in the middle of the string here: ds_put_format(ds_action, "outport = %s;"" output;", first_ovn_port->json_key); In build_chain(), please don't comment out code: //const uint16_t egress_inner_priority = 150; In build_chain(), a lot of debug logging has escaped as VLOG_INFO calls. In build_chain(), you can use xmemdup() instead of xmalloc() followed by memcpy(). In build_chain(), I don't know why there's a line-splicing \ here: VLOG_INFO("Warning: Currently lacking support for more than one port-pair %"PRIuSIZE"\n", \ lppg->n_port_pairs); Also, we'd usually just use VLOG_WARN instead of writing "Warning:". In build_chain(), please always put {} around a conditional statement, e.g. here: if (!input_port_array[j] || !output_port_array[j]) obtainedAllNeededInfo = false; Please wrap at 79 columns in ovn-architecture.7.xml as well. I spent some time with the documentation. I worked on getting rid of passive voice because it's often unclear, e.g. "something happens" doesn't tell the reader who does it, but "The CMS does something" does. I dropped a lot of the items from the life cycle that didn't seem really relevant to VNFs (it seemed like they were mostly cut-and-paste). Some of the introductory documentation confuses me though. The following paragraph mentions about the OVN northbound database but it seems to actually be about the southbound database. I don't think this is the right place to explain the logical flows that SFC puts into the southbound database; that should be in ovn-northd.8.xml instead. I deleted the following paragraph but presumably it should be adapted for ovn-nrothd.8.xml: <p> Service insertion is implemented by adding 4 new flow rules into the OVN northbound database for each VNF inserted. The rules are added into the last table in the ingress path (L2_LKUP). The service insertion rules have a higher priority than the standard forwarding rules. This means that they override the existing forwarding rules. There are four new rules added for each insertion. Two ingress and two egress, The first ingress rule sends all traffic destined for the application into the VNF ingress port and the second rule takes all traffic destined to the application from the VNF egress port to the application, the priorities are such that the second rule is always checked first. In the egress direction the rules are similar if the traffic is from the application it is sent to the VNF egress port and if if is from the application and is from the VNF ingress port it is delivered to the destination. <!-- Should this be a new table or is it a naturally part of the L2 lookup table ? --> </p> Also this paragraph is confusing because the patch doesn't add any new table named Service or Logical_Service or anything like that: <p> The steps in this example refer to the details of the OVN Northbound database schema. There is a new table in the OVN Northbound database to support service insertion called <code>Services</code>, which contains the required information for each new service inserted. The same service can be used for multiple applications, as there is typically an N:1 relationship between applications and VNFs. A single VNF may be part of several service insertions, but each one is logically separate. </p> The ovn-nb documentation for port_chains says, "It is an error for multiple logical switches to include the same logical port." Should this say "same port_chain" instead? The ovn-nb documentation for Logical_Switch does not explain port chains or port pairs. I think that it is necessary to give an overview of what they mean and how they should be defined; as is, I do not understand them. It might be reasonable to add a "Service Function Chaining" <group> with some introductory material and then document these two columns in there. The new ovn-nbctl commands need documentation. ovn-nbctl.c has a weird "#ifdef JED" block. I'm appending my suggested documentation updates. You can also find these on the "sfc" branch at https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_blp_ovs-2Dreviews_tree_sfc&d=DwIBAg&c=V9IgWpI5PvzTw83UyHGVSoW3Uc1MFWe5J8PTfkrzVSo&r=vZ6VUDaavDpfOdPQrz1ED54jEjvAE36A8TVJroVlrOQ&m=D8WTzjM4eBLAIUSaMpsuNQPXOo94n7zg2ZjpkjdkW64&s=v8Cu7uB_gPp7cLmM3W2xZ06uDb868ipoYf4qo3n0fhw&e= --8<--------------------------cut here-------------------------->8-- diff --git a/ovn/ovn-architecture.7.xml b/ovn/ovn-architecture.7.xml index ee69fed..4aa52f3 100644 --- a/ovn/ovn-architecture.7.xml +++ b/ovn/ovn-architecture.7.xml @@ -386,7 +386,7 @@ <dfn>Logical services</dfn> are logical references to virtual network functions (VNF). Adding a logical service requires adding steering rules to the OVN Northbound database. These are the only rules necessary to implement traffic steering for VNFs. - The section below "<code>Life Cycle of an inserted VNF</code>" provides more details. + See <code>Life Cycle of an inserted VNF</code>, below, for details. </li> <li> <p> @@ -572,181 +572,79 @@ </li> </ol> - <h2>Life Cycle of an inserted Virtual Network Function (VNF)</h2> + <h2>Life Cycle of an Inserted Virtual Network Function (VNF)</h2> <p> OVN provides an abstraction to enable the insertion of an arbitrary virtual network function (VNF) into the path of traffic to and from an application. A VNF is different - from an application VM in that it acts on traffic between applications, and im most - cases does not terminiate a flow. Proxy functions are an exception as they terminate the - flow from the src and create a new flow to the dst. Examples of VNF's are security functions, - load balancing, and traffic enhancement services, this is not a complete list. + from an application VM in that it acts on traffic between applications, and in most + cases does not terminate a flow. Proxy functions are an exception as they terminate the + flow from the source and create a new flow to the destination. Examples of VNFs are security functions + (e.g. intrusion detection systems), + load balancers, and traffic enhancement services. </p> <p> - The requirements on the VNF to be inserted are minimal, it must + The requirements on the VNF to be inserted are minimal: it must act as a <code>bump in the wire (BITW)</code> and can have one or two virtual network - ports for traffic. If it has two network ports traffic is directed into one and out the other, - if it has only one port, then traffic is bi-directional. The requirement for the VNF to act as - a BITW removes the need for the VNF to participate in L3/L2 networking which provides + ports for traffic. If it has two network ports, it accepts traffic on one port and + transmits it out the other; + if it has only one port, that port serves both purposes. The requirement for the VNF to act as + a BITW removes the need for the VNF to participate in L2/L3 networking, which provides improved agility and reduces the coupling between OVN and the VNF. </p> <p> - The service insertion is implemented by adding 4 new flow rules into the ovn-nb database for - each VNF inserted. The rules are added into the last table in the ingress path (L2_LKUP). - The service insertion rules have a higher priority than the standard forwarding rules. - This means that they override the existing forwarding rules. There are four - new rules added for each insertion. Two ingress and two egress, The first ingress - rule sends all traffic destined for the application into the VNF ingress port and the - second rule takes all traffic destined to the application from the VNF egress port - to the application, the priorities are such that the second rule is always checked - first. In the egress direction the rules are similar if the traffic is from the - application it is sent to the VNF egress port and if if is from the application - and is from the VNF ingress port it is delivered to the destination. - <!-- Should this be a new table or is it a naturally part of the L2 lookup table ? --> - </p> - <p> The steps in this example refer to the details of the OVN Northbound database schema. There is a new table in the OVN Northbound database to support service insertion - called <code>Services</code> this contains the required information for each new + called <code>Services</code>, which contains the required information for each new service inserted. The same service can be used for multiple applications, as - there is typically a n:1 relationship between applications and VNFs. A + there is typically an N:1 relationship between applications and VNFs. A single VNF may be part of several service insertions, but each one is logically separate. </p> <p> - The steps in this example refer often to details of the OVN and OVN - Northbound database schemas. Please see <code>ovn-sb</code>(5) and - <code>ovn-nb</code>(5), respectively, for the full story on these - databases. The ovn-nb database has specific schema enhancements for the service - insertion function. The ovn-sb database has no schema changes for the - service insertion function. - </p> - <p> The following steps are an overview to inserting a new VNF into the traffic path. The sections below go into each step in more detail. </p> <ol> <li> - The service insertion lifecycle begins when a CMS administrator creates a new - virtual network function <code>(VNF)</code> using the CMS user + The CMS administrator creates a new + virtual network function <code>(VNF)</code>, using the CMS user interface or API. The CMS administrator creates the logical ports (ingress and egress) - for the VNF. If the CMS is Openstack this will create a reusable port-pair defining the - interface to the VNF. There is also typically a seperate management port for the VNF, + for the VNF. If the CMS is OpenStack, this creates a reusable port-pair defining the + interface to the VNF. The administrator also typically creates a separate management port for the VNF, but that is not relevant to the service insertion workflow. A single VNF can participate with several applications, either as a security VM, protecting multiple - applications or as a load balancer VM, distributing load across multiple applications. + applications, or as a load balancer VM, distributing load across multiple applications. </li> <li> - The next step in the life cycle occurs when a CMS administrator creates a new application - with a VIF using the CMS user interface or API and adds it to a switch (one - implemented by OVN as a logical switch). Alternatively an already running application could - be used. - - The CMS can now attach the port pair to the VIF by defining the logical port in the - service function classifier. This will direct traffic to the VIF to go through - the VNF, applying the rules discussed earlier. + The CMS administrator creates a new application with a VIF using the CMS + user interface or API (or chooses a running application) and adds it to an + OVN logical switch. </li> <li> - While within CMS the service insertion may be broken down into multiple reusable steps - (as is the case with Openstack). Within OVN the creating of a new service insertion - is treated as an atomic operation. This enables the easy atomic insertion and deletion of - service insertions. This is important as it is envisioned that the number of serivce - insertions can easily number in the hundreds, all with separate lifecycles. For each new - service insertion operation a new row is added to the OVN Northbound Database. The new row is - only added to the ovn-nb when the VNF, application and network are enabled by the CMS. - - Once the serivce insertion is applied to the ovn-nb database, the ovn-nb controller will be - notified of a change and the rules will be pushed down to the specific OVS instances, using - the existing OVN mechanisms. It is important to note here that the logical abstraction of - OVN enables service insertion with minimal changes. + The CMS administrator attaches the VNF port pair to the VIF by defining + the logical port in the service function classifier. To do so, the CMS + inserts a row into the <code>ACL</code> table in the OVN northbound + database. The ACL's <code>type</code> is <code>sfc</code> and its + <code>options:sfc-port-chain</code> designates the VNF. This directs + traffic to the VIF to go through the VNF, applying the rules discussed + earlier. </li> <li> - When the application VM shuts down the classification rule should be removed, however as - no traffic will be destinated to the application there would be no issues. If the VM is - being moved and the new application VM port is used to update the service then the change - would be detected and the rules pushed down. - </li> - <li> - A VNF can be removed at any time and traffic flows will revert to the pre-VNF traffic - paths if it is removed from the ovn-nb database. OVN must detect that the VNF has been - shut-off as it must remove all the rules that are attached to that VNF. Otherwise - traffic loss will occur, if a failure in a VNF occurs that is not detected. - </li> - - <li> - On every hypervisor, <code>ovn-controller</code> receives the - <code>Logical_Service</code> table updates that <code>ovn-northd</code> made - in the previous step. As long as the VM that owns the VIF is powered - off, <code>ovn-controller</code> cannot do much; it cannot, for example, - arrange to send packets to or receive packets from the VIF, because the - VIF does not actually exist anywhere. In addition the VNF cannot be inserted - into the traffic path as it will have no source to forward traffic too. - <!-- If there is no VM then traffic cannot be sent to it therefore having the - rules inserted is probably not an issue? --> - </li> - - <li> - Some CMS systems, including OpenStack, fully start a VM only when its - networking is ready. To support this, <code>ovn-northd</code> notices - the <code>chassis</code> column updated for the row in - <code>Binding</code> table and pushes this upward by updating the - <ref column="up" table="Logical_Port" db="OVN_NB"/> column in the OVN - Northbound database's <ref table="Logical_Port" db="OVN_NB"/> table to - indicate that the VIF is now up. The CMS, if it uses this feature, can - then react by allowing the VM's execution to proceed. - - Traffic now flows into and out of the VM that has a VNF inserted in its - datapath. The rules are applied to direct traffic to the VNF on the way - into the VM and on the way out of the VM. - </li> - - <!-- Need a section on having multiple VM's using the same VNF - ( physcially or logically ). Different rule sets --> - <!-- Need a section on distributed cases - one section for each --> - <li> - On every hypervisor but the one where the VIF resides, - <code>ovn-controller</code> notices the completely populated row in the - <code>Binding</code> table. This provides <code>ovn-controller</code> - the physical location of the logical port, so each instance updates the - OpenFlow tables of its switch (based on logical datapath flows in the OVN - DB <code>Logical_Flow</code> table) so that packets to and from the VIF - can be properly handled via tunnels. - </li> - <!-- Current implementation is open on delete, i.e. when the VNF is removed - the datapath behaviour reverts to the pre-existing paths. Does this make sense? - - could argue that close on delete should be an option ? --> - - <li> - Eventually, a user removes the inserted service function from the ovn nb - database. The rules are then updated in the southbound database and pushed - down to the relevant ovs. No other SIF is impacted as the row in the ovn nb - is independant of all the other SIF. - <!-- This is really important in the case where many SIF are being added - and removed. Without both the independance of the enteries confusion would - exist. Also for debugging - possible to remove/add individual VNF's to - determine potentail problems. --> - </li> - - <li> - The CMS plugin removes the SIF from the OVN Northbound database, - by deleting its row in the <code>Logical_Service</code> table. - </li> - - <li> - <code>ovn-northd</code> receives the OVN Northbound update and in turn - updates the OVN Southbound database accordingly, by removing or updating - the rows from the OVN Southbound database <code>Logical_Service</code> table. - </li> + <p> + Eventually, the application VM shuts down and the CMS removes the + <code>sfc</code> ACL. (However, it is harmless if it remains, since no + traffic will be sent to the application.) + </p> - <li> - On every hypervisor, <code>ovn-controller</code> receives the - <code>Logical_Service</code> table updates that <code>ovn-northd</code> made - in the previous step. <code>ovn-controller</code> updates OpenFlow - tables to reflect the update. The datapath for the VM will now revert to - paths that existed before the VNF was inserted into the data path. + <p> + Alternatively, eventually the CMS administrator detaches the VIF from + the VNF. The CMS deletes the <code>sfc</code> ACL row, and traffic + reverts to the pre-VNF traffic paths. + </p> </li> </ol> diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml index e45c670..b952a46 100644 --- a/ovn/ovn-nb.xml +++ b/ovn/ovn-nb.xml @@ -994,9 +994,7 @@ <li> <code>sfc</code>: Forward the packet into a logical port chain. - The chain to be used -- as well as any other attributes that determine - the behavior of the packet while in the chain -- are provided - via <ref column="options"/>. + The <ref column="options"/> column provides details. </li> </ul> </column> @@ -1014,7 +1012,7 @@ </column> <group title="Options"> - <column name = "options"> + <column name="options"> This column provides key/value settings specific to the ACL <ref column="action"/>. The type-specific options are described individually below. _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev