[dpdk-dev] [RFC]Generic flow filtering API Sample Application

Adrien Mazarguil adrien.mazarguil at 6wind.com
Wed Nov 2 16:47:44 CET 2016


Hi Wei,

On Wed, Nov 02, 2016 at 05:27:50AM +0000, Zhao1, Wei wrote:
> Hi  All,
> Now we are planning for an sample application for Generic flow 
> filtering API feature, and I have finished the RFC for this example app.
> Now  Adrien Mazarguil  has send v2 version of Generic flow 
> filtering API,  this sample application  RFC is based on that.
> 
> Thank you.

Thanks for your RFC, sorry for the late notice that I've been essentially
working on a similar implementation in testpmd in order to validate the API
before sending v1, which I concede is taking way longer than expected.

I have yet to submit my patches however this should happen soon, if you
haven't started working on your own implementation yet, please wait until my
implementation gets rejected to avoid any more duplicated effort in the
meantime.

BTW, I find a lot of similarities between our respective command-line
handling approaches, which is great! We're going in the same direction.

> Generic flow filtering API Sample Application
> ============================================
> 
> The application is a simple example of generic flow filtering API using the DPDK.
> The application performs flow director/filtering/classification in packet processing.
> 
> Overview
> --------
> 
> The application demonstrates the use of generic flow director/filtering/classification API 
> in the DPDK to implement packet forwarding.And this document focus on the guide line of writing rules configuration 
> files and prompt commands usage. It also supply the definition of the available EAL options arguments which is useful
> in DPDK packet forwarding processing.
> 
> 
> Compiling the Application
> -------------------------
> 
> To compile the application:
> 
> #.	Go to the sample application directory:
> 
> 	.. code-block:: console
> 
> 		export RTE_SDK=/path/to/rte_sdk
> 		cd ${RTE_SDK}/examples/gen_filter
> 
> #.	Set the target (a default target is used if not specified). For example:
> 
> 	.. code-block:: console
> 
> 		export RTE_TARGET=x86_64-native-linuxapp-gcc
> 
> 	See the *DPDK Getting Started Guide* for possible RTE_TARGET values.
> 
> #.	Build the application:
> 
> 	.. code-block:: console
> 
> 		make
> 
> Running the Application
> -----------------------
> The application has a number of EAL options::
> 
> 	./gen_filter [EAL options] -- <APP PARAMS>
> 
> EAL options:
> *	-c
> 	Codemask, set the hexadecimal bitmask of the cores to run on.
> 
> *	-n
> 	Num, set the number of memory channels to use.
> 
> APP PARAMS:
> 	The following are the application options parameters, they must be separated
> 	from the EAL options with a "--" separator.
> 
> *	-i
> 	Interactive, run this app in interactive mode. In this mode, the app starts with a prompt that can
> 	be used to start and stop forwarding, then manage generic filters rule configure in the application,
> 	reference to the following description for more details.In non-interactive mode, the application starts with the configuration specified on the
> 	command-line and immediately enters forwarding mode.
> 
> *	--portmask=0xXX
> 	Set the hexadecimal bitmask of the ports which can be used by the generic flow director test in packet forwarding.
> 	
> *	--coremask=0xXX
> 	Set the hexadecimal bitmask of the cores running the packet forwarding test. The master
> 	lcore is reserved for command line parsing only and cannot be masked on for packet forwarding.
> 
> *	--nb-ports=N 
> 	Set the number of forwarding ports, where 1 <= N <= "number of ports" on the board
> 	or CONFIG_RTE_MAX_ETHPORTS from the configuration file. The default value is the number of ports on the board.
> 
> *	--rxq=N
> 	Set the number of RX queues per port to N, where 1 <= N <= 65535. The default value is 1.
> 
> *	--txq=N
> 	Set the number of TX queues per port to N, where 1 <= N <= 65535. The default value is 1.
> 
> 
> ###this part need to complete later after decision of which EAL commands arguments need to be support in this application###
> 
> 
> Interactive mode
> ----------------
> *   when the gen_filter application is started in interactive mode, (-i|--interactive), it displays a prompt 
> 	that can be used to start and stop forwarding, and configure the application to set the Flow Director,
> 	display statistics, set the Flow Director and other tasks. The application has a number of commands line options:
> 
> 	gen_filter>[Commands]
> 
> *	There is a prompt "gen_filter> " before cursor, command can be enter after that position,
> 	also a space bar between configuration file name and command.
> 
> These are the commands that are currently working under the command line interface:
> 
> *	Control Commands
> 
> 	help: show the following commands which are currently available in this application and their usage
> 		gen_filter>help
>     
> 	quit: quits the application.
> 		gen_filter>quit
> 
> 	start: start the application, start packet forwarding
> 		gen_filter>start
> 
> 	stop: stop the application, stop packet forwarding
> 		gen_filter>stop
> 
> 	showcfg: print configuration infomation about EAL parameters, for example mapping of cores, rx queue, tx queues and so on.
> 		gen_filter>showcfg
> 
> *	General Commands to add/remove/query an filter rule:
> 		App will print reminder message for user about whether this rule command is SUCESS or FAIL after user type in the commmand.
> 
> 	add: add filter rules from configuration file
> 		gen_filter>add port_id filename.txt
> 		(port_id is the port index that user want to add filter rules, it can be any uint8_t integer.
> 		 filename.txt is the rule configuration file name from which app read and paser port rules)
> 
> 	del: remove filter rules from configuration file
> 		gen_filter>del port_id
> 		(port_id is the port index that user want to remove filter rules, it can be any uint8_t integer.)
> 
> 	query: query filter statistics of rules from configuration file and dump results output to log file or printf
> 		gen_filter>query port_id query_reset action_name
> 		(port_id is the port index that user want to query statistics, it can be any uint8_t integer. query_reset is used for reset counters after query action, 
> 		 it must be integer 1 if youwant to reset counters after query, else 0. action_name is abbreviation of rte_flow_action_type which user want to query)
> 
> 	display: display rules applying to that port
> 		gen_filter>display port_id
> 		(port_id is the port index that user want to add filter rules, it can be any uint8_t integer.)
> 	
> 	
> 
> The rule configuration file 
> ---------------------------
> 
> 1.There is a mapping between rte_flow_item_type and configuration item type abbreviation for the convenience of writing:
> 
> RTE_FLOW_ITEM_TYPE_END          end
> RTE_FLOW_ITEM_TYPE_VOID         void
> RTE_FLOW_ITEM_TYPE_INVERT       invert
> RTE_FLOW_ITEM_TYPE_ANY          any
> RTE_FLOW_ITEM_TYPE_PF           pf
> RTE_FLOW_ITEM_TYPE_VF           vf
> RTE_FLOW_ITEM_TYPE_PORT         port
> RTE_FLOW_ITEM_TYPE_RAW          raw
> RTE_FLOW_ITEM_TYPE_ETH          eth
> RTE_FLOW_ITEM_TYPE_IPV4         ipv4
> RTE_FLOW_ITEM_TYPE_IPV6         ipv6
> RTE_FLOW_ITEM_TYPE_ICMP         icmp
> RTE_FLOW_ITEM_TYPE_UDP          udp
> RTE_FLOW_ITEM_TYPE_TCP          tcp
> RTE_FLOW_ITEM_TYPE_SCTP         sctp
> RTE_FLOW_ITEM_TYPE_VXLAN        vxlan
> 
> 2.There is a mapping between rte_flow_action_type and configuration action type abbreviation for the convenience of writing:
> 
> RTE_FLOW_ACTION_TYPE_END       ac_end
> RTE_FLOW_ACTION_TYPE_VOID      ac_void
> RTE_FLOW_ACTION_TYPE_PASSTHRU  ac_passthru
> RTE_FLOW_ACTION_TYPE_MARK      ac_mark
> RTE_FLOW_ACTION_TYPE_FLAG      ac_flag
> RTE_FLOW_ACTION_TYPE_QUEUE     ac_queue
> RTE_FLOW_ACTION_TYPE_DROP      ac_drop
> RTE_FLOW_ACTION_TYPE_COUNT     ac_count
> RTE_FLOW_ACTION_TYPE_DUP       ac_dup
> RTE_FLOW_ACTION_TYPE_RSS       ac_rss
> RTE_FLOW_ACTION_TYPE_PF        ac_pf
> RTE_FLOW_ACTION_TYPE_VF        ac_vf
> 
> 3.There is a mapping between struct rte_flow_attr and abbreviation for that configuration of writing:
> 
> rte_flow_attr                  attr
> 
> 4.Writing format of configuration file
> 
> * write in one line for each rule
> 
> * writing a "#" at the beginnning of line shows that it is a comment line, for example:
>   ##########this is a comment line#########
> 
> * flow pattern item name and action name should be as abbreviation as above
> 
> * configuration file member has the same name as associated specification structure member, such as dst_addr/src_addr/type_of_service/time_to_live
>   struct members of ipv4_hdr in specification rte_flow_item_ipv4
> 
> * there should be a dash('/') between the structure member and its mask if it has a mask demand,
>   mask format is XX...XX (where X - is a hexadecimal or decimal digit, case insensitive), and the number of X is according to the length of structure member,
>   for example: rte_flow_item_ipv4 member time_to_live type is uint8_t, so its mask is also uint8_t such as time_to_live=20/0xf0, "f0" is its mask.
>   And the user had better to provide every byte of the mask, for example, for a uint16 mask, abbreviative 0xf0 is also ok for mask 0x00f0, 
>   but the user must write IPv4/IPV6/Ethernet address mask explicitly and not use abbreviative style.
> 
> * All these config element members such as time_to_live in rte_flow_item_ipv4, vtc_flow in rte_flow_item_ipv6 should be write in decimal or hexadecimal format,
>   except for IPv6 and eth address list below.And pay attention to that all mask is using  decimal or hexadecimal format. For example type_of_service=20/0xf0(or 0x14/0xf0) are both ok.
> 
> * there should be an space bar(' ') between item name or action name and its structure member
> 
> * there should be an equality sign('=') between structure member and assignment value, an space bar(' ') between two structure members
> 
> * there should be an comma(',') between item names or action names
> 
> * each IPv4 address input number should be decimal or hexadecimal in configuration file,
>    > IPv4 address expected format: 
>    > src_addr (or dst_addr)=<src_ipv4_addr>'/'<mask> <space> 
>    > src_ipv4_addr format is xxx.xxx.xxx.xxx (where x - is a decimal or hexadecimal digit)
>    > mask format is XX.XX.XX.XX (where X - is a decimal or hexadecimal digit, case insensitive)
>    > <mask> can be negligible, the default mask is 0xff.0xff.0xff.0xff or 255.255.255.255
>    such as IPv4 address 192.168.0.3(0xC0.0xA8.0.0x3), if there is a mask ffffff00 for that IPv4 address,there should be a dash before the mask,
>    for example: src_addr=192.168.0.3/0xff.0xff.0xff.0x00 or src_addr=0xC0.0xA8.0x0.0x3/0xff.0xff.0xff.0x00
> 
> * each IPv6 address input number should be hexadecimal in configuration file,
>    > IPv6 address expected format:
>    > src_addr (or dst_addr)=<src_ipv6_addr>'/'<mask> <space> 
>    > src_ipv6_addr and mask format is XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is hexadecimal digit, case insensitive).
>    > mask format is XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is a decimal or hexadecimal digit, case insensitive), it don't support the brief style of IPv6 address.
>    > <mask> can be negligible, the default mask is 0xffff:0xffff:0xffff:0xffff:0xffff:0xffff:0xffff:0xffff
>    such as IPv6 address 2001:0000:3238:DFE1:0063:0000:0000:FEFB,if there is a prefix length or mask for that IPv6 address, there should be a dash before the prefix length,
>    for example: src_addr=2001:0000:3238:DFE1:0063:0000:0000:FEFB/0x0000:0xFFFF:0xFFFF:0x0000:0x0000:0x0000:0x0000
> 
> * each ethernet address input number should be hexadecimal in configuration file,
>    > Ethernet address expected format:
>    > src (or dst)=<src_eth_addr>'/'<mask> <space> 
>    > src_eth_addr_addr and mask format is XX-XX-XX-XX-XX-XX (where X - is a hexadecimal digit, case insensitive).
>    > mask format is XX:XX:XX:XX:XX:XX (where X - is a decimal or hexadecimal digit, case insensitive)
>    > <mask> can be negligible, the default mask is 0xff:0xff:0xff:0xff:0xff:0xff
>    such as ethernet address a0:14:ff:36:95:b1, if there is a mask for that eth address, there should be a dash before the mask,
>    for example: src=a0:14:ff:36:95:b1/0xff:0xff:0x00:0x00:0x00:0xff
> 
> * item pattern or action structure containing array member need to assign each member of the array with the array name before value,
>   for example: rte_flow_item_raw has array member pattern[], if it has 3 elements which are 10 11 20,so the configuration expected format is pattern={10&11&20}
> 
> * item pattern or action structure containing structure array member or structure need to assign each member of the structure with the structure member
>   name before value, for example: rte_flow_item_eth has structure array member tag[], if it has 2 elements which are tag[0]={10, 11} tag[1]={20, 21}, 
>   so the configuration expected format is tag={{10&11}{20&21}}
> 
> * Flow rule attributes should be configured if necessary for this rule, writing key word "attr" at first, configuration file member has the same name 
>   as struct rte_flow_attr member, for example: attr group=1 priority=0 ingress=1 egress=0
> 
> 
> Take the following 6 rules configuration as example:
> (a)Assign an IPv4 flow with specific source and destination IP address to Queue 8: rte_flow_item_type is RTE_FLOW_ITEM_TYPE_IPV4, source address 192.168.100.15, subnet mask is 0xff.0xff.0xff.0x0, 
>    destination address 192.168.3.20, type_of_service is 20 with mask 0xf0, time_to_live 32, rte_flow_item_type is RTE_FLOW_ACTION_TYPE_QUEUE and queue index is 8, and Flow rule attributes is group in 1,
>    priority is 0, ingress is 1 and egress is 0(apply noly to inbound traffic but not outbound traffic). There are attribute description and 2 items in flow pattern and 1 flow action.
> 
>    attr group=1 priority=0 ingress=1 egress=0, void, ipv4 src_addr=192.168.0.3/0xff.0xff.0xff.0x0 dst_addr=192.168.0.4 type_of_service=20/0xf0 time_to_live=32, ac_queue queue=8
> 
> (b)Assign an IPv6 flow with the certain packet length from and to specific IP address to the certain vf: rte_flow_item_type is RTE_FLOW_ITEM_TYPE_IPV6,
>    source address is 2001:0000:3238:DFE1:0063:0000:0000:FEFB, the mask is 0x0000:0xFFFF:0xFFFF:0x0000:0x0000:0x0000:0x0000, destination address is 2001:0000:3238:DFE1:0063:0000:0000:0A23,
>    payload_len 1024,rte_flow_action_type is RTE_FLOW_ACTION_TYPE_VF and RTE_FLOW_ACTION_TYPE_COUNT, redirect the packet to a vf and enables counters for this rule, there is 1 item in flow pattern and 2 flow action.
> 
>    ipv6 src_addr=2001:0000:3238:DFE1:0063:0000:0000:FEFB/0x0000:0xFFFF:0xFFFF:0x0000:0x0000:0x0000:0x0000 dst_addr=2001:0000:3238:DFE1:0063:0000:0000:0A23 payload_len=1024 vtc_flow=255/0xff, ac_vf original=1 vf=2, ac_count
> 
> (c)A flow with RSS usage for specific MAC address Ethernet packets redirected to Queue 0 and 3: rte_flow_item_type is RTE_FLOW_ITEM_TYPE_ETH, source address is a0:14:ff:36:95:b1 and its mask is 0xff:0xff:0x00:0x00:0x00:0xff, 
>    destination address is b0:24:ff:36:95:f2 and its mask is default 0xff:0xff:0xff:0xff:0xff:0xff, 2 tag elements is tag[0]={10, 11} tag[1]={20, 21},
>    rte_flow_action_type is RTE_FLOW_ACTION_TYPE_RSS, queue index is 0 and 3
> 
>    eth src=a0:14:ff:36:95:b1/0xff:0xff:0x00:0x00:0x00:0xff dst=b0:24:ff:36:95:f2 tag={{10&11}{20&21}}, ac_rss queue={0&3}
> 
> (d)Add a 32 bit value to a VLAN packet to return with that mark: rte_flow_item_type is RTE_FLOW_ITEM_TYPE_VXLAN, VXLAN network identifier index is 11, flags is 0x8 and the 32 bit value is 0x1a2b3c4d
>    rte_flow_action_type is RTE_FLOW_ACTION_TYPE_MARK 
> 
>    vxlan flags=0x8 vni=11, ac_mark mark=0x1a2b3c4d
> 
> (e)Drop cerstain specific TCP packets: rte_flow_item_type is RTE_FLOW_ITEM_TYPE_TCP, src_port is 80, sent_seq is 726, tcp_flags is 2
>    rte_flow_action_type is RTE_FLOW_ACTION_TYPE_DROP
> 
>    tcp src_port=80 sent_seq=726 tcp_flags=2, ac_drop
> 
> (f)Redirect some UDP packets into a specific queue: rte_flow_item_type is RTE_FLOW_ITEM_TYPE_UDP, src_port is 21, dst_port is 21,
>    rte_flow_action_type is RTE_FLOW_ACTION_TYPE_QUEUE, queue index is 1
> 
>    udp src_port=21 dst_port=21, ac_queue queue=1
> 
> 
> Explanation
> -----------
> 
> The following sections provide an explanation of the main components of the app code:
> main function
> -------------
> * open configuration file and parser the simple rules, then call a few rule management functions in order to
>   fully manage flows. Each created flow rule is associated with an opaque, PMD-specific handle pointer.
>   The application is responsible for keeping it until the rule is destroyed.
> 
> packet forward function
> ----------------------- 
> * Forwards packets "as-is" in I/O mode. This is the fastest possible forwarding operation
>   as it does not access packets data. This is the default mode of this example.
> 
> rule management function
> ------------------------
> 
> * Check whether a flow rule can be created on a given port
> 
> * Create a flow rule on a given port.
> 
> * Query an existing flow rule on a given port.
> 
> * Destroy a flow rule on a given port.
> 
> * Destroy all flow rules associated with a port.

-- 
Adrien Mazarguil
6WIND


More information about the dev mailing list