[dpdk-dev] doc: add basic howto for flow API

Message ID 1508396139-27687-1-git-send-email-orika@mellanox.com (mailing list archive)
State Changes Requested, archived
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Ori Kam Oct. 19, 2017, 6:55 a.m. UTC
  As the rte flow is a new complex module in the DPDK.
In order to ease developers in to using this feature
it was suggested to supply a simple howto doc.

Signed-off-by: Ori Kam <orika@mellanox.com>
---
 doc/guides/howto/index.rst    |    1 +
 doc/guides/howto/rte_flow.rst |  307 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 308 insertions(+), 0 deletions(-)
 create mode 100644 doc/guides/howto/rte_flow.rst
  

Comments

John McNamara Oct. 19, 2017, 10:05 a.m. UTC | #1
> -----Original Message-----
> From: Ori Kam [mailto:orika@mellanox.com]
> Sent: Thursday, October 19, 2017 7:56 AM
> To: adrien.mazarguil@6wind.com; Mcnamara, John <john.mcnamara@intel.com>
> Cc: dev@dpdk.org; orika@mellanox.com
> Subject: [PATCH] doc: add basic howto for flow API
> 
> As the rte flow is a new complex module in the DPDK.
> In order to ease developers in to using this feature it was suggested to
> supply a simple howto doc.
> 
> Signed-off-by: Ori Kam <orika@mellanox.com>

Hi Ori,

Thanks for useful and very doc. It is good to see additions to the How-to guides.
We should have more of those.

Some minor comments below.


>
> +  tpmd> flow create 0 ingress pattern eth / vlan / ipv4 dst is
> + 192.168.3.2 / end actions drop / end


The testpmd commands are very long and run off the page in the 
PDF and Html docs.

Something like the following would be better and just as clear:


In this example we will create a simple rule that drops packets whose IPv4
destination equals 192.168.3.2. This code is equivalent to the following
testpmd command (wrapped for clarity)::

  tpmd> flow create 0 ingress pattern eth / vlan /
                    ipv4 dst is 192.168.3.2 / end actions drop / end



> +  $scapy
> +  welcome to Scapy
> +  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'),
> + iface = <some interface>, count 1)  >>
> + sendp(Ether()/Dot1Q()/IP(src='176.80.50.5', dst='192.168.3.2'), iface
> + = <some interface>, count 1)
> +
> +terminal 1: output log::
> +
> +  received packet with src ip = 176.80.50.4  received packet with src
> + ip = 176.80.50.5
> +
> +terminal 1: running sample app flow rule enabled::
> +
> +  ./filter-program enabled
> +  [waiting for packets]
> +
> +terminal 2: running  scapy::
> +
> +  $scapy
> +  welcome to Scapy
> +  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'),
> + iface = <some interface>, count 1)  >>

There is a typo here and in the other scapy commands. It should be:

    count=1

Also <some interface> would be better as a string. And the line is also long
so something like this would be better:

Terminal 2: running  scapy::

  $scapy
  welcome to Scapy
  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'), \
           iface='some interface', count=1)
  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.5', dst='192.168.3.2'), \
           iface='some interface', count=1)

I have some other small comments/suggestions that I will send to you offline.

Thanks,

John
  
Ori Kam Oct. 21, 2017, 7:29 a.m. UTC | #2
Hi John,

Thanks for your comments and time.

Please see my comments inline.

> -----Original Message-----
> From: Mcnamara, John [mailto:john.mcnamara@intel.com]
> Sent: Thursday, October 19, 2017 1:06 PM
> To: Ori Kam <orika@mellanox.com>; Adrien Mazarguil
> <adrien.mazarguil@6wind.com>
> Cc: dev@dpdk.org
> Subject: RE: [PATCH] doc: add basic howto for flow API
> 
> 
> 
> > -----Original Message-----
> > From: Ori Kam [mailto:orika@mellanox.com]
> > Sent: Thursday, October 19, 2017 7:56 AM
> > To: adrien.mazarguil@6wind.com; Mcnamara, John
> > <john.mcnamara@intel.com>
> > Cc: dev@dpdk.org; orika@mellanox.com
> > Subject: [PATCH] doc: add basic howto for flow API
> >
> > As the rte flow is a new complex module in the DPDK.
> > In order to ease developers in to using this feature it was suggested
> > to supply a simple howto doc.
> >
> > Signed-off-by: Ori Kam <orika@mellanox.com>
> 
> Hi Ori,
> 
> Thanks for useful and very doc. It is good to see additions to the How-to
> guides.
> We should have more of those.
> 
> Some minor comments below.
> 
> 
> >
> > +  tpmd> flow create 0 ingress pattern eth / vlan / ipv4 dst is
> > + 192.168.3.2 / end actions drop / end
> 
> 
> The testpmd commands are very long and run off the page in the PDF and
> Html docs.
> 
> Something like the following would be better and just as clear:
> 
> 
> In this example we will create a simple rule that drops packets whose IPv4
> destination equals 192.168.3.2. This code is equivalent to the following
> testpmd command (wrapped for clarity)::
> 
>   tpmd> flow create 0 ingress pattern eth / vlan /
>                     ipv4 dst is 192.168.3.2 / end actions drop / end
> 
> 
> 

Will fix.

> > +  $scapy
> > +  welcome to Scapy
> > +  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'),
> > + iface = <some interface>, count 1)  >>
> > + sendp(Ether()/Dot1Q()/IP(src='176.80.50.5', dst='192.168.3.2'),
> > + iface = <some interface>, count 1)
> > +
> > +terminal 1: output log::
> > +
> > +  received packet with src ip = 176.80.50.4  received packet with src
> > + ip = 176.80.50.5
> > +
> > +terminal 1: running sample app flow rule enabled::
> > +
> > +  ./filter-program enabled
> > +  [waiting for packets]
> > +
> > +terminal 2: running  scapy::
> > +
> > +  $scapy
> > +  welcome to Scapy
> > +  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'),
> > + iface = <some interface>, count 1)  >>
> 
> There is a typo here and in the other scapy commands. It should be:
> 
>     count=1
>

Will be fixed.
 
> Also <some interface> would be better as a string. And the line is also long so
> something like this would be better:
> 
> Terminal 2: running  scapy::
> 
>   $scapy
>   welcome to Scapy
>   >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'), \
>            iface='some interface', count=1)
>   >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.5', dst='192.168.3.2'), \
>            iface='some interface', count=1)
> 

I agree will be changed.

> I have some other small comments/suggestions that I will send to you
> offline.
> 

I will read your comments from the offline mail, and will
send the new version based on the combination of the mails.

> Thanks,
> 
> John

Thanks,

Ori Kam
  

Patch

diff --git a/doc/guides/howto/index.rst b/doc/guides/howto/index.rst
index 468939b..0a22737 100644
--- a/doc/guides/howto/index.rst
+++ b/doc/guides/howto/index.rst
@@ -43,3 +43,4 @@  HowTo Guides
     virtio_user_for_container_networking
     virtio_user_as_exceptional_path
     packet_capture_framework
+    rte_flow
diff --git a/doc/guides/howto/rte_flow.rst b/doc/guides/howto/rte_flow.rst
new file mode 100644
index 0000000..02e944c
--- /dev/null
+++ b/doc/guides/howto/rte_flow.rst
@@ -0,0 +1,307 @@ 
+..  BSD LICENSE
+    Copyright(c) 2017 Mellanox Corporation. All rights reserved.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+    * Neither the name of Mellanox Corporation nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Generic flow API - examples
+===========================
+
+This document function is to supply some concrete examples for programming
+flow rules.
+
+* Detail API can be found in the following link: :ref:`Generic flow API <Generic_flow_API>` .
+
+* Detail TestPMD command to set the flow rules can be found in the
+  following link: :ref:`TestPMD Flow rules <testpmd_rte_flow>`
+
+Simple IPv4 drop
+----------------
+
+Description
+~~~~~~~~~~~
+
+In this example we will create a simple rule that drops packets that their IPv4
+destination equals 192.168.3.2
+This code implements the following testpmd command::
+
+  tpmd> flow create 0 ingress pattern eth / vlan / ipv4 dst is 192.168.3.2 / end actions drop / end
+
+Code
+~~~~
+
+.. code-block:: c
+
+  /* create the attribute structure */
+  struct rte_flow_attr attr = {.ingress = 1};
+  struct rte_flow_item pattern[MAX_PATTERN_IN_FLOW];
+  struct rte_flow_action actions[MAX_ACTIONS_IN_FLOW];
+  struct rte_flow_item_etc eth;
+  struct rte_flow_item_vlan vlan;
+  struct rte_flow_item_ipv4 ipv4;
+  struct rte_flow *flow;
+  struct rte_flow_error error;
+
+  /* setting the eth to pass all packets */
+  pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+  pattern[0].spec = &eth;
+
+  /* set the vlan to pas all packets */
+  pattern[1] = RTE_FLOW_ITEM_TYPE_VLAN;
+  pattern[1].spec = &vlan;
+
+  /* set the dst ipv4 packet to the required value */
+  ipv4.hdr.dst_addr = htonl(0xc0a80302);
+  pattern[2].type = RTE_FLOW_ITEM_TYPE_IPV4;
+  pattern[2].spec = &ipv4;
+
+  /* end the pattern array */
+  pattern[3].type = RTE_FLOW_ITEM)TYPE_END;
+
+  /* create the drop action */
+  actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
+  actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+  /* validate and create the flow rule */
+  if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)
+      flow = rte_flow_create(port_id, &attr, pattern, actions, &error)
+
+Outputs sample
+~~~~~~~~~~~~~~
+terminal 1: running sample app flow rule disabled::
+
+  ./filter-program disable
+  [waiting for packets]
+
+terminal 2: running  scapy::
+
+  $scapy
+  welcome to Scapy
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.5', dst='192.168.3.2'), iface = <some interface>, count 1)
+
+terminal 1: output log::
+
+  received packet with src ip = 176.80.50.4
+  received packet with src ip = 176.80.50.5
+
+terminal 1: running sample app flow rule enabled::
+
+  ./filter-program enabled
+  [waiting for packets]
+
+terminal 2: running  scapy::
+
+  $scapy
+  welcome to Scapy
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.5', dst ='192.168.3.2'), iface = <some interface>, count 1)
+
+terminal 1: output log::
+
+  received packet with src ip = 176.80.50.4
+
+Range IPv4 drop
+----------------
+
+Description
+~~~~~~~~~~~
+
+In this example we will create a simple rule that drops packets that their IPv4
+destination is in the range of  192.168.3.0 to 192.168.3.255 This is done using
+mask.
+
+This code implements the following testpmd command::
+
+  tpmd> flow create 0 ingress pattern eth / vlan / ipv4 dst spec 192.168.3.0 dst mask 255.255.255.0 / end actions drop / end
+
+Code
+~~~~
+
+.. code-block:: c
+
+  struct rte_flow_attr attr = {.ingress = 1};
+  struct rte_flow_item pattern[MAX_PATTERN_IN_FLOW];
+  struct rte_flow_action actions[MAX_ACTIONS_IN_FLOW];
+  struct rte_flow_item_etc eth;
+  struct rte_flow_item_vlan vlan;
+  struct rte_flow_item_ipv4 ipv4;
+  struct rte_flow_item_ipv4 ipv4_mask;
+  struct rte_flow *flow;
+  struct rte_flow_error error;
+
+  /* setting the eth to pass all packets */
+  pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+  pattern[0].spec = &eth;
+
+  /* set the vlan to pas all packets */
+  pattern[1] = RTE_FLOW_ITEM_TYPE_VLAN;
+  pattern[1].spec = &vlan;
+
+  /* set the dst ipv4 packet to the required value */
+  ipv4.hdr.dst_addr = htonl(0xc0a80300);
+  ipv4_mask.hdr.dst_addr = htonl(0xffffff00);
+  pattern[2].type = RTE_FLOW_ITEM_TYPE_IPV4;
+  pattern[2].spec = &ipv4;
+  pattern[2].mask = &ipv4_mask;
+
+  /* end the pattern array */
+  pattern[3].type = RTE_FLOW_ITEM)TYPE_END;
+
+  /* create the drop action */
+  actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
+  actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+  /* validate and create the flow rule */
+  if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)
+      flow = rte_flow_create(port_id, &attr, pattern, actions, &error)
+
+Outputs sample
+~~~~~~~~~~~~~~
+terminal 1: running sample app flow rule disabled::
+
+  ./filter-program disable
+  [waiting for packets]
+
+terminal 2: running  scapy::
+
+  $scapy
+  welcome to Scapy
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.5', dst='192.168.3.2'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.6', dst='192.168.5.2'), iface = <some interface>, count 1)
+
+terminal 1: output log::
+
+  received packet with src ip = 176.80.50.4
+  received packet with src ip = 176.80.50.5
+  received packet with src ip = 176.80.50.6
+
+terminal 1: running sample app flow rule enabled::
+
+  ./filter-program enabled
+  [waiting for packets]
+
+terminal 2: running  scapy::
+
+  $scapy
+  welcome to Scapy
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.4', dst='192.168.3.1'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.5', dst='192.168.3.2'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q()/IP(src='176.80.50.6', dst='192.168.5.2'), iface = <some interface>, count 1)
+
+terminal 1: output log::
+
+  received packet with src ip = 176.80.50.6
+
+Send vlan to queue
+------------------
+
+Description
+~~~~~~~~~~~
+
+In this example we will create a rule that routes all vlan id 123 to queue 3.
+
+This code implements the following testpmd command::
+
+  tpmd> flow create 0 ingress pattern eth / vlan vid spec 123 / end actions queue index 3 / end
+
+Code
+~~~~
+
+.. code-block:: c
+
+  struct rte_flow_attr attr = {.ingress = 1};
+  struct rte_flow_item pattern[MAX_PATTERN_IN_FLOW];
+  struct rte_flow_action actions[MAX_ACTIONS_IN_FLOW];
+  struct rte_flow_item_etc eth;
+  struct rte_flow_item_vlan vlan;
+  struct rte_flow_action_queue queue = { .index = 3 };
+  struct rte_flow *flow;
+  struct rte_flow_error error;
+
+  /* setting the eth to pass all packets */
+  pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+  pattern[0].spec = &eth;
+
+  /* set the vlan to pas all packets */
+  vlan.vid = 123;
+  pattern[1] = RTE_FLOW_ITEM_TYPE_VLAN;
+  pattern[1].spec = &vlan;
+
+  /* end the pattern array */
+  pattern[2].type = RTE_FLOW_ITEM)TYPE_END;
+
+  /* create the drop action */
+  actions[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+  actions[0].conf = &queue
+  actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+  /* validate and create the flow rule */
+  if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)
+      flow = rte_flow_create(port_id, &attr, pattern, actions, &error)
+
+Outputs sample
+~~~~~~~~~~~~~~
+terminal 1: running sample app flow rule disabled::
+
+  ./filter-program disable
+  [waiting for packets]
+
+terminal 2: running  scapy::
+
+  $scapy
+  welcome to Scapy
+  >> sendp(Ether()/Dot1Q(vlan=123)/IP(src='176.80.50.4', dst='192.168.3.1'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q(vlan=50)/IP(src='176.80.50.5', dst='192.168.3.2'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q(vlan=123)/IP(src='176.80.50.6', dst='192.168.5.2'), iface = <some interface>, count 1)
+
+terminal 1: output log::
+
+  received packet with src ip = 176.80.50.4 sent to queue 2
+  received packet with src ip = 176.80.50.5 sent to queue 1
+  received packet with src ip = 176.80.50.6 sent to queue 0
+
+terminal 1: running sample app flow rule enabled::
+
+  ./filter-program enabled
+  [waiting for packets]
+
+terminal 2: running  scapy::
+
+  $scapy
+  welcome to Scapy
+  >> sendp(Ether()/Dot1Q(vlan=123)/IP(src='176.80.50.4', dst='192.168.3.1'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q(vlan=50)/IP(src='176.80.50.5', dst='192.168.3.2'), iface = <some interface>, count 1)
+  >> sendp(Ether()/Dot1Q(vlan=123)/IP(src='176.80.50.6', dst='192.168.5.2'), iface = <some interface>, count 1)
+
+terminal 1: output log::
+
+  received packet with src ip = 176.80.50.4 sent to queue 3
+  received packet with src ip = 176.80.50.5 sent to queue 1
+  received packet with src ip = 176.80.50.6 sent to queue 3