> + if (!memcmp(name, "GTPC", sizeof("GTPC") - 1))
> + new_pctype =
> + i40e_find_personalized_pctype(pf,
> + I40E_PERSONALIZED_GTPC);
> + else if (!memcmp(name, "GTPU_IPV4",
> + sizeof("GTPU_IPV4") - 1))
Memcmp -> strcmp?
[......]
>
> +enum i40e_new_proto {
> + I40E_PERSONALIZED_GTPC = 0,
> + I40E_PERSONALIZED_GTPU_IPV4,
> + I40E_PERSONALIZED_GTPU_IPV6,
> + I40E_PERSONALIZED_GTPU,
> + I40E_PERSONALIZED_MAX,
> +};
> +
> +#define I40E_FILTER_PCTYPE_INVALID 0
> +struct i40e_personalized_pctype {
> + uint8_t index; /* Indicate which personalized pctype */
The index is I40E_PERSONALIZED_XXX right? Why not define it like
enum i40e_new_proto index? Or you can just use #define to define
personalized pctype instead of enum.
> + uint8_t pctype; /* New pctype value */
> + bool valid; /* Check if it's valid */
> +};
> +
> /*
> * Structure to store private data specific for PF instance.
> */
> @@ -786,6 +801,11 @@ struct i40e_pf {
> bool mpls_replace_flag; /* 1 - MPLS filter replace is done */
> bool qinq_replace_flag; /* QINQ filter replace is done */
> struct i40e_tm_conf tm_conf;
> +
> + /* Dynamic Device Personalization */
> + bool gtp_support; /* 1 - support GTP-C and GTP-U */
> + /* customer personalized pctype */
> + struct i40e_personalized_pctype new_pctype[I40E_PERSONALIZED_MAX];
> };
>
> enum pending_msg {
> @@ -1003,6 +1023,10 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr,
> uint32_t val);
> int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
> void i40e_tm_conf_init(struct rte_eth_dev *dev);
> void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
> +struct i40e_personalized_pctype*
> +i40e_find_personalized_pctype(struct i40e_pf *pf, uint8_t index);
> +void i40e_update_personalized_info(struct rte_eth_dev *dev, uint8_t *pkg,
> + uint32_t pkg_size);
>
> #define I40E_DEV_TO_PCI(eth_dev) \
> RTE_DEV_TO_PCI((eth_dev)->device)
> diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
> index 9f9c808..d1313f6 100644
> --- a/drivers/net/i40e/rte_pmd_i40e.c
> +++ b/drivers/net/i40e/rte_pmd_i40e.c
> @@ -1608,6 +1608,8 @@ rte_pmd_i40e_process_ddp_package(uint8_t port, uint8_t
> *buff,
> return -EINVAL;
> }
>
> + i40e_update_personalized_info(dev, buff, size);
> +
> /* Find metadata segment */
> metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
> pkg_hdr);
> @@ -2090,7 +2092,9 @@ static int check_invalid_pkt_type(uint32_t pkt_type)
> tnl != RTE_PTYPE_TUNNEL_VXLAN &&
> tnl != RTE_PTYPE_TUNNEL_NVGRE &&
> tnl != RTE_PTYPE_TUNNEL_GENEVE &&
> - tnl != RTE_PTYPE_TUNNEL_GRENAT)
> + tnl != RTE_PTYPE_TUNNEL_GRENAT &&
> + tnl != RTE_PTYPE_TUNNEL_GTPC &&
> + tnl != RTE_PTYPE_TUNNEL_GTPU)
> return -1;
>
> if (il2 &&
> --
> 2.5.5
@@ -65,6 +65,7 @@
#include "i40e_rxtx.h"
#include "i40e_pf.h"
#include "i40e_regs.h"
+#include "rte_pmd_i40e.h"
#define ETH_I40E_FLOATING_VEB_ARG "enable_floating_veb"
#define ETH_I40E_FLOATING_VEB_LIST_ARG "floating_veb_list"
@@ -1036,6 +1037,18 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
return ret;
}
+static void
+i40e_init_customer_pctype(struct i40e_pf *pf)
+{
+ int i;
+
+ for (i = I40E_PERSONALIZED_GTPC; i < I40E_PERSONALIZED_MAX; i++) {
+ pf->new_pctype[i].index = i;
+ pf->new_pctype[i].pctype = I40E_FILTER_PCTYPE_INVALID;
+ pf->new_pctype[i].valid = false;
+ }
+}
+
static int
eth_i40e_dev_init(struct rte_eth_dev *dev)
{
@@ -1301,6 +1314,8 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
/* initialize Traffic Manager configuration */
i40e_tm_conf_init(dev);
+ i40e_init_customer_pctype(pf);
+
ret = i40e_init_ethtype_filter_list(dev);
if (ret < 0)
goto err_init_ethtype_filter_list;
@@ -10893,6 +10908,303 @@ is_i40e_supported(struct rte_eth_dev *dev)
return is_device_supported(dev, &rte_i40e_pmd);
}
+struct i40e_personalized_pctype*
+i40e_find_personalized_pctype(struct i40e_pf *pf, uint8_t index)
+{
+ int i;
+
+ for (i = 0; i < I40E_PERSONALIZED_MAX; i++) {
+ if (pf->new_pctype[i].index == index)
+ return &pf->new_pctype[i];
+ }
+ return NULL;
+}
+
+static int
+i40e_update_personalized_pctype(struct rte_eth_dev *dev, uint8_t *pkg,
+ uint32_t pkg_size, uint32_t proto_num,
+ struct rte_pmd_i40e_proto_info *proto)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ uint32_t pctype_num;
+ struct rte_pmd_i40e_ptype_info *pctype;
+ struct i40e_personalized_pctype *new_pctype = NULL;
+ uint8_t proto_id;
+ uint8_t pctype_value;
+ char name[64];
+ uint32_t i, j, n;
+ int ret;
+
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&pctype_num, sizeof(pctype_num),
+ RTE_PMD_I40E_PKG_INFO_PCTYPE_NUM);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to get pctype number");
+ return -1;
+ }
+ if (!pctype_num) {
+ PMD_DRV_LOG(INFO, "No new pctype added");
+ return -1;
+ }
+
+ pctype = rte_zmalloc("new_pctype",
+ pctype_num * sizeof(struct rte_pmd_i40e_ptype_info),
+ 0);
+ if (!pctype) {
+ PMD_DRV_LOG(ERR, "Failed to allocate memory");
+ return -1;
+ }
+ /* get information about new pctype list */
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)pctype, pctype_num,
+ RTE_PMD_I40E_PKG_INFO_PCTYPE_LIST);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to get pctype list");
+ rte_free(pctype);
+ return -1;
+ }
+
+ /* Update personalized pctype. */
+ for (i = 0; i < pctype_num; i++) {
+ pctype_value = pctype[i].ptype_id;
+ memset(name, 0, sizeof(name));
+ for (j = 0; j < RTE_PMD_I40E_PROTO_NUM; j++) {
+ proto_id = pctype[i].protocols[j];
+ if (proto_id == RTE_PMD_I40E_PROTO_UNUSED)
+ continue;
+ for (n = 0; n < proto_num; n++) {
+ if (proto[n].proto_id != proto_id)
+ continue;
+ strcat(name, proto[n].name);
+ strcat(name, "_");
+ break;
+ }
+ }
+ if (!memcmp(name, "GTPC", sizeof("GTPC") - 1))
+ new_pctype =
+ i40e_find_personalized_pctype(pf,
+ I40E_PERSONALIZED_GTPC);
+ else if (!memcmp(name, "GTPU_IPV4",
+ sizeof("GTPU_IPV4") - 1))
+ new_pctype =
+ i40e_find_personalized_pctype(pf,
+ I40E_PERSONALIZED_GTPU_IPV4);
+ else if (!memcmp(name, "GTPU_IPV6",
+ sizeof("GTPU_IPV6") - 1))
+ new_pctype =
+ i40e_find_personalized_pctype(pf,
+ I40E_PERSONALIZED_GTPU_IPV6);
+ else if (!memcmp(name, "GTPU", sizeof("GTPU") - 1))
+ new_pctype =
+ i40e_find_personalized_pctype(pf,
+ I40E_PERSONALIZED_GTPU);
+ if (new_pctype) {
+ new_pctype->pctype = pctype_value;
+ new_pctype->valid = true;
+ }
+ }
+
+ rte_free(pctype);
+ return 0;
+}
+
+static int
+i40e_update_personalized_ptype(struct rte_eth_dev *dev, uint8_t *pkg,
+ uint32_t pkg_size, uint32_t proto_num,
+ struct rte_pmd_i40e_proto_info *proto)
+{
+ struct rte_pmd_i40e_ptype_mapping *ptype_mapping;
+ uint8_t port_id = dev->data->port_id;
+ uint32_t ptype_num;
+ struct rte_pmd_i40e_ptype_info *ptype;
+ uint8_t proto_id;
+ char name[16];
+ uint32_t i, j, n;
+ int ip_id = 0;
+ int ret;
+
+ /* get information about new ptype num */
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&ptype_num, sizeof(ptype_num),
+ RTE_PMD_I40E_PKG_INFO_PTYPE_NUM);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to get ptype number");
+ return -1;
+ }
+ if (!ptype_num) {
+ PMD_DRV_LOG(INFO, "No new ptype added");
+ return -1;
+ }
+ /* get information about new ptype list */
+ ptype = rte_zmalloc("new_ptype",
+ ptype_num * sizeof(struct rte_pmd_i40e_ptype_info),
+ 0);
+ if (!ptype) {
+ PMD_DRV_LOG(ERR, "Failed to allocate memory");
+ return -1;
+ }
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)ptype, ptype_num,
+ RTE_PMD_I40E_PKG_INFO_PTYPE_LIST);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to get ptype list");
+ rte_free(ptype);
+ return -1;
+ }
+
+ ptype_mapping = rte_zmalloc("ptype_mapping",
+ ptype_num *
+ sizeof(struct rte_pmd_i40e_ptype_mapping),
+ 0);
+ if (!ptype_mapping) {
+ PMD_DRV_LOG(ERR, "Failed to allocate memory");
+ rte_free(ptype);
+ return -1;
+ }
+
+ /* Update ptype mapping table. */
+ for (i = 0; i < ptype_num; i++) {
+ ptype_mapping[i].hw_ptype = ptype[i].ptype_id;
+ ptype_mapping[i].sw_ptype = 0;
+ ip_id = 0;
+ for (j = 0; j < RTE_PMD_I40E_PROTO_NUM; j++) {
+ proto_id = ptype[i].protocols[j];
+ if (proto_id == RTE_PMD_I40E_PROTO_UNUSED)
+ continue;
+ for (n = 0; n < proto_num; n++) {
+ if (proto[n].proto_id != proto_id)
+ continue;
+ memset(name, 0, sizeof(name));
+ strcpy(name, proto[n].name);
+ if (!memcmp(name, "IPV4", sizeof("IPV4") - 1)) {
+ if (ip_id == 0) {
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
+ ip_id++;
+ } else if (ip_id == 1) {
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_INNER_L3_IPV4;
+ ip_id++;
+ } else if (ip_id == 2)
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ } else if (!memcmp(name, "IPV6",
+ sizeof("IPV6") - 1)) {
+ if (ip_id == 0) {
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+ ip_id++;
+ } else if (ip_id == 1) {
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_INNER_L3_IPV6;
+ ip_id++;
+ } else if (ip_id == 2)
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_INNER_L4_FRAG;
+ } else if (!memcmp(name, "GTPC",
+ sizeof("GTPC")))
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_TUNNEL_GTPC;
+ else if (!memcmp(name, "GTPU", sizeof("GTPU")))
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_TUNNEL_GTPU;
+ else if (!memcmp(name, "UDP", sizeof("UDP")))
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_INNER_L4_UDP;
+ else if (!memcmp(name, "TCP", sizeof("TCP")))
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_INNER_L4_TCP;
+ else if (!memcmp(name, "SCTP", sizeof("SCTP")))
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_INNER_L4_SCTP;
+ else if (!memcmp(name, "ICMP",
+ sizeof("ICMP") - 1))
+ ptype_mapping[i].sw_ptype |=
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ break;
+ }
+ }
+ }
+
+ ret = rte_pmd_i40e_ptype_mapping_update(port_id, ptype_mapping,
+ ptype_num, 0);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to update mapping table.");
+ rte_free(ptype_mapping);
+ rte_free(ptype);
+ return -1;
+ }
+
+ rte_free(ptype_mapping);
+ rte_free(ptype);
+ return 0;
+}
+
+void
+i40e_update_personalized_info(struct rte_eth_dev *dev, uint8_t *pkg,
+ uint32_t pkg_size)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ uint32_t proto_num;
+ struct rte_pmd_i40e_proto_info *proto;
+ uint32_t i;
+ int ret;
+
+ /* get information about protocol number */
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&proto_num, sizeof(proto_num),
+ RTE_PMD_I40E_PKG_INFO_PROTOCOL_NUM);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to get protocol number");
+ return;
+ }
+ if (!proto_num) {
+ PMD_DRV_LOG(INFO, "No new protocol added");
+ return;
+ }
+
+ proto = rte_zmalloc("new_proto",
+ proto_num * sizeof(struct rte_pmd_i40e_proto_info),
+ 0);
+ if (!proto) {
+ PMD_DRV_LOG(ERR, "Failed to allocate memory");
+ return;
+ }
+
+ /* get information about protocol list */
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)proto, proto_num,
+ RTE_PMD_I40E_PKG_INFO_PROTOCOL_LIST);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to get protocol list");
+ rte_free(proto);
+ return;
+ }
+
+ /* Check if GTP is supported. */
+ for (i = 0; i < proto_num; i++) {
+ if (!memcmp(proto[i].name, "GTP", sizeof("GTP") - 1)) {
+ pf->gtp_support = true;
+ break;
+ }
+ }
+
+ /* Update pctype info */
+ ret = i40e_update_personalized_pctype(dev, pkg, pkg_size,
+ proto_num, proto);
+ if (ret)
+ PMD_DRV_LOG(INFO, "No pctype is updated.");
+
+ /* Update ptype info */
+ ret = i40e_update_personalized_ptype(dev, pkg, pkg_size,
+ proto_num, proto);
+ if (ret)
+ PMD_DRV_LOG(INFO, "No pctype is updated.");
+
+ rte_free(proto);
+}
+
/* Create a QinQ cloud filter
*
* The Fortville NIC has limited resources for tunnel filters,
@@ -722,6 +722,21 @@ struct i40e_tm_conf {
bool committed;
};
+enum i40e_new_proto {
+ I40E_PERSONALIZED_GTPC = 0,
+ I40E_PERSONALIZED_GTPU_IPV4,
+ I40E_PERSONALIZED_GTPU_IPV6,
+ I40E_PERSONALIZED_GTPU,
+ I40E_PERSONALIZED_MAX,
+};
+
+#define I40E_FILTER_PCTYPE_INVALID 0
+struct i40e_personalized_pctype {
+ uint8_t index; /* Indicate which personalized pctype */
+ uint8_t pctype; /* New pctype value */
+ bool valid; /* Check if it's valid */
+};
+
/*
* Structure to store private data specific for PF instance.
*/
@@ -786,6 +801,11 @@ struct i40e_pf {
bool mpls_replace_flag; /* 1 - MPLS filter replace is done */
bool qinq_replace_flag; /* QINQ filter replace is done */
struct i40e_tm_conf tm_conf;
+
+ /* Dynamic Device Personalization */
+ bool gtp_support; /* 1 - support GTP-C and GTP-U */
+ /* customer personalized pctype */
+ struct i40e_personalized_pctype new_pctype[I40E_PERSONALIZED_MAX];
};
enum pending_msg {
@@ -1003,6 +1023,10 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val);
int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
void i40e_tm_conf_init(struct rte_eth_dev *dev);
void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
+struct i40e_personalized_pctype*
+i40e_find_personalized_pctype(struct i40e_pf *pf, uint8_t index);
+void i40e_update_personalized_info(struct rte_eth_dev *dev, uint8_t *pkg,
+ uint32_t pkg_size);
#define I40E_DEV_TO_PCI(eth_dev) \
RTE_DEV_TO_PCI((eth_dev)->device)
@@ -1608,6 +1608,8 @@ rte_pmd_i40e_process_ddp_package(uint8_t port, uint8_t *buff,
return -EINVAL;
}
+ i40e_update_personalized_info(dev, buff, size);
+
/* Find metadata segment */
metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
pkg_hdr);
@@ -2090,7 +2092,9 @@ static int check_invalid_pkt_type(uint32_t pkt_type)
tnl != RTE_PTYPE_TUNNEL_VXLAN &&
tnl != RTE_PTYPE_TUNNEL_NVGRE &&
tnl != RTE_PTYPE_TUNNEL_GENEVE &&
- tnl != RTE_PTYPE_TUNNEL_GRENAT)
+ tnl != RTE_PTYPE_TUNNEL_GRENAT &&
+ tnl != RTE_PTYPE_TUNNEL_GTPC &&
+ tnl != RTE_PTYPE_TUNNEL_GTPU)
return -1;
if (il2 &&