5630257fcc
Signed-off-by: Ferruh Yigit <ferruh.yigit@intel.com> Acked-by: Bruce Richardson <bruce.richardson@intel.com>
416 lines
13 KiB
ReStructuredText
416 lines
13 KiB
ReStructuredText
.. SPDX-License-Identifier: BSD-3-Clause
|
|
Copyright(c) 2017 Intel Corporation.
|
|
|
|
Flow Classification Library
|
|
===========================
|
|
|
|
DPDK provides a Flow Classification library that provides the ability
|
|
to classify an input packet by matching it against a set of Flow rules.
|
|
|
|
The initial implementation supports counting of IPv4 5-tuple packets which match
|
|
a particular Flow rule only.
|
|
|
|
Please refer to the
|
|
:doc:`./rte_flow`
|
|
for more information.
|
|
|
|
The Flow Classification library uses the ``librte_table`` API for managing Flow
|
|
rules and matching packets against the Flow rules.
|
|
The library is table agnostic and can use the following tables:
|
|
``Access Control List``, ``Hash`` and ``Longest Prefix Match(LPM)``.
|
|
The ``Access Control List`` table is used in the initial implementation.
|
|
|
|
Please refer to the
|
|
:doc:`./packet_framework`
|
|
for more information.on ``librte_table``.
|
|
|
|
DPDK provides an Access Control List library that provides the ability to
|
|
classify an input packet based on a set of classification rules.
|
|
|
|
Please refer to the
|
|
:doc:`./packet_classif_access_ctrl`
|
|
library for more information on ``librte_acl``.
|
|
|
|
There is also a Flow Classify sample application which demonstrates the use of
|
|
the Flow Classification Library API's.
|
|
|
|
Please refer to the
|
|
:doc:`../sample_app_ug/flow_classify`
|
|
for more information on the ``flow_classify`` sample application.
|
|
|
|
Overview
|
|
--------
|
|
|
|
The library has the following API's
|
|
|
|
.. code-block:: c
|
|
|
|
/**
|
|
* Flow classifier create
|
|
*
|
|
* @param params
|
|
* Parameters for flow classifier creation
|
|
* @return
|
|
* Handle to flow classifier instance on success or NULL otherwise
|
|
*/
|
|
struct rte_flow_classifier *
|
|
rte_flow_classifier_create(struct rte_flow_classifier_params *params);
|
|
|
|
/**
|
|
* Flow classifier free
|
|
*
|
|
* @param cls
|
|
* Handle to flow classifier instance
|
|
* @return
|
|
* 0 on success, error code otherwise
|
|
*/
|
|
int
|
|
rte_flow_classifier_free(struct rte_flow_classifier *cls);
|
|
|
|
/**
|
|
* Flow classify table create
|
|
*
|
|
* @param cls
|
|
* Handle to flow classifier instance
|
|
* @param params
|
|
* Parameters for flow_classify table creation
|
|
* @return
|
|
* 0 on success, error code otherwise
|
|
*/
|
|
int
|
|
rte_flow_classify_table_create(struct rte_flow_classifier *cls,
|
|
struct rte_flow_classify_table_params *params);
|
|
|
|
/**
|
|
* Validate the flow classify rule
|
|
*
|
|
* @param[in] cls
|
|
* Handle to flow classifier instance
|
|
* @param[in] attr
|
|
* Flow rule attributes
|
|
* @param[in] pattern
|
|
* Pattern specification (list terminated by the END pattern item).
|
|
* @param[in] actions
|
|
* Associated actions (list terminated by the END pattern item).
|
|
* @param[out] error
|
|
* Perform verbose error reporting if not NULL. Structure
|
|
* initialised in case of error only.
|
|
* @return
|
|
* 0 on success, error code otherwise
|
|
*/
|
|
int
|
|
rte_flow_classify_validate(struct rte_flow_classifier *cls,
|
|
const struct rte_flow_attr *attr,
|
|
const struct rte_flow_item pattern[],
|
|
const struct rte_flow_action actions[],
|
|
struct rte_flow_error *error);
|
|
|
|
/**
|
|
* Add a flow classify rule to the flow_classifier table.
|
|
*
|
|
* @param[in] cls
|
|
* Flow classifier handle
|
|
* @param[in] attr
|
|
* Flow rule attributes
|
|
* @param[in] pattern
|
|
* Pattern specification (list terminated by the END pattern item).
|
|
* @param[in] actions
|
|
* Associated actions (list terminated by the END pattern item).
|
|
* @param[out] key_found
|
|
* returns 1 if rule present already, 0 otherwise.
|
|
* @param[out] error
|
|
* Perform verbose error reporting if not NULL. Structure
|
|
* initialised in case of error only.
|
|
* @return
|
|
* A valid handle in case of success, NULL otherwise.
|
|
*/
|
|
struct rte_flow_classify_rule *
|
|
rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
|
|
const struct rte_flow_attr *attr,
|
|
const struct rte_flow_item pattern[],
|
|
const struct rte_flow_action actions[],
|
|
int *key_found;
|
|
struct rte_flow_error *error);
|
|
|
|
/**
|
|
* Delete a flow classify rule from the flow_classifier table.
|
|
*
|
|
* @param[in] cls
|
|
* Flow classifier handle
|
|
* @param[in] rule
|
|
* Flow classify rule
|
|
* @return
|
|
* 0 on success, error code otherwise.
|
|
*/
|
|
int
|
|
rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
|
|
struct rte_flow_classify_rule *rule);
|
|
|
|
/**
|
|
* Query flow classifier for given rule.
|
|
*
|
|
* @param[in] cls
|
|
* Flow classifier handle
|
|
* @param[in] pkts
|
|
* Pointer to packets to process
|
|
* @param[in] nb_pkts
|
|
* Number of packets to process
|
|
* @param[in] rule
|
|
* Flow classify rule
|
|
* @param[in] stats
|
|
* Flow classify stats
|
|
*
|
|
* @return
|
|
* 0 on success, error code otherwise.
|
|
*/
|
|
int
|
|
rte_flow_classifier_query(struct rte_flow_classifier *cls,
|
|
struct rte_mbuf **pkts,
|
|
const uint16_t nb_pkts,
|
|
struct rte_flow_classify_rule *rule,
|
|
struct rte_flow_classify_stats *stats);
|
|
|
|
Classifier creation
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
The application creates the ``Classifier`` using the
|
|
``rte_flow_classifier_create`` API.
|
|
The ``rte_flow_classify_params`` structure must be initialised by the
|
|
application before calling the API.
|
|
|
|
.. code-block:: c
|
|
|
|
struct rte_flow_classifier_params {
|
|
/** flow classifier name */
|
|
const char *name;
|
|
|
|
/** CPU socket ID where memory for the flow classifier and its */
|
|
/** elements (tables) should be allocated */
|
|
int socket_id;
|
|
};
|
|
|
|
The ``Classifier`` has the following internal structures:
|
|
|
|
.. code-block:: c
|
|
|
|
struct rte_cls_table {
|
|
/* Input parameters */
|
|
struct rte_table_ops ops;
|
|
uint32_t entry_size;
|
|
enum rte_flow_classify_table_type type;
|
|
|
|
/* Handle to the low-level table object */
|
|
void *h_table;
|
|
};
|
|
|
|
#define RTE_FLOW_CLASSIFIER_MAX_NAME_SZ 256
|
|
|
|
struct rte_flow_classifier {
|
|
/* Input parameters */
|
|
char name[RTE_FLOW_CLASSIFIER_MAX_NAME_SZ];
|
|
int socket_id;
|
|
|
|
/* Internal */
|
|
/* ntuple_filter */
|
|
struct rte_eth_ntuple_filter ntuple_filter;
|
|
|
|
/* classifier tables */
|
|
struct rte_cls_table tables[RTE_FLOW_CLASSIFY_TABLE_MAX];
|
|
uint32_t table_mask;
|
|
uint32_t num_tables;
|
|
|
|
uint16_t nb_pkts;
|
|
struct rte_flow_classify_table_entry
|
|
*entries[RTE_PORT_IN_BURST_SIZE_MAX];
|
|
} __rte_cache_aligned;
|
|
|
|
Adding a table to the Classifier
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The application adds a table to the ``Classifier`` using the
|
|
``rte_flow_classify_table_create`` API.
|
|
The ``rte_flow_classify_table_params`` structure must be initialised by the
|
|
application before calling the API.
|
|
|
|
.. code-block:: c
|
|
|
|
struct rte_flow_classify_table_params {
|
|
/** Table operations (specific to each table type) */
|
|
struct rte_table_ops *ops;
|
|
|
|
/** Opaque param to be passed to the table create operation */
|
|
void *arg_create;
|
|
|
|
/** Classifier table type */
|
|
enum rte_flow_classify_table_type type;
|
|
};
|
|
|
|
To create an ACL table the ``rte_table_acl_params`` structure must be
|
|
initialised and assigned to ``arg_create`` in the
|
|
``rte_flow_classify_table_params`` structure.
|
|
|
|
.. code-block:: c
|
|
|
|
struct rte_table_acl_params {
|
|
/** Name */
|
|
const char *name;
|
|
|
|
/** Maximum number of ACL rules in the table */
|
|
uint32_t n_rules;
|
|
|
|
/** Number of fields in the ACL rule specification */
|
|
uint32_t n_rule_fields;
|
|
|
|
/** Format specification of the fields of the ACL rule */
|
|
struct rte_acl_field_def field_format[RTE_ACL_MAX_FIELDS];
|
|
};
|
|
|
|
The fields for the ACL rule must also be initialised by the application.
|
|
|
|
An ACL table can be added to the ``Classifier`` for each ACL rule, for example
|
|
another table could be added for the IPv6 5-tuple rule.
|
|
|
|
Flow Parsing
|
|
~~~~~~~~~~~~
|
|
|
|
The library currently supports three IPv4 5-tuple flow patterns, for UDP, TCP
|
|
and SCTP.
|
|
|
|
.. code-block:: c
|
|
|
|
/* Pattern for IPv4 5-tuple UDP filter */
|
|
static enum rte_flow_item_type pattern_ntuple_1[] = {
|
|
RTE_FLOW_ITEM_TYPE_ETH,
|
|
RTE_FLOW_ITEM_TYPE_IPV4,
|
|
RTE_FLOW_ITEM_TYPE_UDP,
|
|
RTE_FLOW_ITEM_TYPE_END,
|
|
};
|
|
|
|
/* Pattern for IPv4 5-tuple TCP filter */
|
|
static enum rte_flow_item_type pattern_ntuple_2[] = {
|
|
RTE_FLOW_ITEM_TYPE_ETH,
|
|
RTE_FLOW_ITEM_TYPE_IPV4,
|
|
RTE_FLOW_ITEM_TYPE_TCP,
|
|
RTE_FLOW_ITEM_TYPE_END,
|
|
};
|
|
|
|
/* Pattern for IPv4 5-tuple SCTP filter */
|
|
static enum rte_flow_item_type pattern_ntuple_3[] = {
|
|
RTE_FLOW_ITEM_TYPE_ETH,
|
|
RTE_FLOW_ITEM_TYPE_IPV4,
|
|
RTE_FLOW_ITEM_TYPE_SCTP,
|
|
RTE_FLOW_ITEM_TYPE_END,
|
|
};
|
|
|
|
The API function ``rte_flow_classify_validate`` parses the
|
|
IPv4 5-tuple pattern, attributes and actions and returns the 5-tuple data in the
|
|
``rte_eth_ntuple_filter`` structure.
|
|
|
|
.. code-block:: c
|
|
|
|
static int
|
|
rte_flow_classify_validate(struct rte_flow_classifier *cls,
|
|
const struct rte_flow_attr *attr,
|
|
const struct rte_flow_item pattern[],
|
|
const struct rte_flow_action actions[],
|
|
struct rte_flow_error *error)
|
|
|
|
Adding Flow Rules
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
The ``rte_flow_classify_table_entry_add`` API creates an
|
|
``rte_flow_classify`` object which contains the flow_classify id and type, the
|
|
action, a union of add and delete keys and a union of rules.
|
|
It uses the ``rte_flow_classify_validate`` API function for parsing the
|
|
flow parameters.
|
|
The 5-tuple ACL key data is obtained from the ``rte_eth_ntuple_filter``
|
|
structure populated by the ``classify_parse_ntuple_filter`` function which
|
|
parses the Flow rule.
|
|
|
|
.. code-block:: c
|
|
|
|
struct acl_keys {
|
|
struct rte_table_acl_rule_add_params key_add; /* add key */
|
|
struct rte_table_acl_rule_delete_params key_del; /* delete key */
|
|
};
|
|
|
|
struct classify_rules {
|
|
enum rte_flow_classify_rule_type type;
|
|
union {
|
|
struct rte_flow_classify_ipv4_5tuple ipv4_5tuple;
|
|
} u;
|
|
};
|
|
|
|
struct rte_flow_classify {
|
|
uint32_t id; /* unique ID of classify object */
|
|
enum rte_flow_classify_table_type tbl_type; /* rule table */
|
|
struct classify_rules rules; /* union of rules */
|
|
union {
|
|
struct acl_keys key;
|
|
} u;
|
|
int key_found; /* rule key found in table */
|
|
struct rte_flow_classify_table_entry entry; /* rule meta data */
|
|
void *entry_ptr; /* handle to the table entry for rule meta data */
|
|
};
|
|
|
|
It then calls the ``table.ops.f_add`` API to add the rule to the ACL
|
|
table.
|
|
|
|
Deleting Flow Rules
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
The ``rte_flow_classify_table_entry_delete`` API calls the
|
|
``table.ops.f_delete`` API to delete a rule from the ACL table.
|
|
|
|
Packet Matching
|
|
~~~~~~~~~~~~~~~
|
|
|
|
The ``rte_flow_classifier_query`` API is used to find packets which match a
|
|
given flow Flow rule in the table.
|
|
This API calls the flow_classify_run internal function which calls the
|
|
``table.ops.f_lookup`` API to see if any packets in a burst match any
|
|
of the Flow rules in the table.
|
|
The meta data for the highest priority rule matched for each packet is returned
|
|
in the entries array in the ``rte_flow_classify`` object.
|
|
The internal function ``action_apply`` implements the ``Count`` action which is
|
|
used to return data which matches a particular Flow rule.
|
|
|
|
The rte_flow_classifier_query API uses the following structures to return data
|
|
to the application.
|
|
|
|
.. code-block:: c
|
|
|
|
/** IPv4 5-tuple data */
|
|
struct rte_flow_classify_ipv4_5tuple {
|
|
uint32_t dst_ip; /**< Destination IP address in big endian. */
|
|
uint32_t dst_ip_mask; /**< Mask of destination IP address. */
|
|
uint32_t src_ip; /**< Source IP address in big endian. */
|
|
uint32_t src_ip_mask; /**< Mask of destination IP address. */
|
|
uint16_t dst_port; /**< Destination port in big endian. */
|
|
uint16_t dst_port_mask; /**< Mask of destination port. */
|
|
uint16_t src_port; /**< Source Port in big endian. */
|
|
uint16_t src_port_mask; /**< Mask of source port. */
|
|
uint8_t proto; /**< L4 protocol. */
|
|
uint8_t proto_mask; /**< Mask of L4 protocol. */
|
|
};
|
|
|
|
/**
|
|
* Flow stats
|
|
*
|
|
* For the count action, stats can be returned by the query API.
|
|
*
|
|
* Storage for stats is provided by the application.
|
|
*
|
|
*
|
|
*/
|
|
struct rte_flow_classify_stats {
|
|
void *stats;
|
|
};
|
|
|
|
struct rte_flow_classify_5tuple_stats {
|
|
/** count of packets that match IPv4 5tuple pattern */
|
|
uint64_t counter1;
|
|
/** IPv4 5tuple data */
|
|
struct rte_flow_classify_ipv4_5tuple ipv4_5tuple;
|
|
};
|