Firstly, use rte_eth_dev_get_ptype_info() API to check if device will
parse needed packet type. If not, specifying the newly added option,
--parse-ptype to do it in the callback softly.

Signed-off-by: Jianfeng Tan <jianfeng.tan at intel.com>
---
 examples/l3fwd/main.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index 5b0c2dd..ccbdce3 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -174,6 +174,7 @@ static __m128i val_eth[RTE_MAX_ETHPORTS];
 static uint32_t enabled_port_mask = 0;
 static int promiscuous_on = 0; /**< Ports set in promiscuous mode off by 
default. */
 static int numa_on = 1; /**< NUMA is enabled by default. */
+static int parse_ptype = 0; /**< parse packet type using rx callback */

 #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
 static int ipv6 = 0; /**< ipv6 is false by default. */
@@ -2022,6 +2023,7 @@ parse_eth_dest(const char *optarg)
 #define CMD_LINE_OPT_IPV6 "ipv6"
 #define CMD_LINE_OPT_ENABLE_JUMBO "enable-jumbo"
 #define CMD_LINE_OPT_HASH_ENTRY_NUM "hash-entry-num"
+#define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype"

 /* Parse the argument given in the command line of the application */
 static int
@@ -2038,6 +2040,7 @@ parse_args(int argc, char **argv)
                {CMD_LINE_OPT_IPV6, 0, 0, 0},
                {CMD_LINE_OPT_ENABLE_JUMBO, 0, 0, 0},
                {CMD_LINE_OPT_HASH_ENTRY_NUM, 1, 0, 0},
+               {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0},
                {NULL, 0, 0, 0}
        };

@@ -2125,6 +2128,12 @@ parse_args(int argc, char **argv)
                                }
                        }
 #endif
+                       if (!strncmp(lgopts[option_index].name, 
CMD_LINE_OPT_PARSE_PTYPE,
+                               sizeof(CMD_LINE_OPT_PARSE_PTYPE))) {
+                               printf("soft parse-ptype is enabled \n");
+                               parse_ptype = 1;
+                       }
+
                        break;

                default:
@@ -2559,6 +2568,75 @@ check_all_ports_link_status(uint8_t port_num, uint32_t 
port_mask)
        }
 }

+static int
+check_packet_type_ok(int portid)
+{
+       int i;
+       int ret;
+       uint32_t ptypes[RTE_PTYPE_L3_MAX_NUM];
+       int ptype_l3_ipv4 = 0, ptype_l3_ipv6 = 0;
+
+       ret = rte_eth_dev_get_ptype_info(portid, RTE_PTYPE_L3_MASK, ptypes);
+       for (i = 0; i < ret; ++i) {
+               if (ptypes[i] & RTE_PTYPE_L3_IPV4)
+                       ptype_l3_ipv4 = 1;
+               if (ptypes[i] & RTE_PTYPE_L3_IPV6)
+                       ptype_l3_ipv6 = 1;
+       }
+
+       if (ptype_l3_ipv4 == 0)
+               printf("port %d cannot parse RTE_PTYPE_L3_IPV4\n", portid);
+
+       if (ptype_l3_ipv6 == 0)
+               printf("port %d cannot parse RTE_PTYPE_L3_IPV6\n", portid);
+
+       if (ptype_l3_ipv4 || ptype_l3_ipv6)
+               return 1;
+
+       return 0;
+}
+static inline void
+parse_packet_type(struct rte_mbuf *m)
+{
+       struct ether_hdr *eth_hdr;
+       struct vlan_hdr *vlan_hdr;
+       uint32_t packet_type = 0;
+       uint16_t ethertype;
+
+       eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+       ethertype = rte_be_to_cpu_16(eth_hdr->ether_type);
+       if (ethertype == ETHER_TYPE_VLAN) {
+               vlan_hdr = (struct vlan_hdr *)(eth_hdr + 1);
+               ethertype = rte_be_to_cpu_16(vlan_hdr->eth_proto);
+       }
+       switch (ethertype) {
+       case ETHER_TYPE_IPv4:
+               packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
+               break;
+       case ETHER_TYPE_IPv6:
+               packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+               break;
+       default:
+               break;
+       }
+
+       m->packet_type = packet_type;
+}
+
+static uint16_t
+cb_parse_packet_type(uint8_t port __rte_unused,
+               uint16_t queue __rte_unused,
+               struct rte_mbuf *pkts[],
+               uint16_t nb_pkts,
+               uint16_t max_pkts __rte_unused,
+               void *user_param __rte_unused)
+{
+       unsigned i;
+
+       for (i = 0; i < nb_pkts; ++i)
+               parse_packet_type(pkts[i]);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -2672,6 +2750,11 @@ main(int argc, char **argv)
                                rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: 
err=%d, "
                                        "port=%d\n", ret, portid);

+                       if (!check_packet_type_ok(portid) && !parse_ptype)
+                               rte_exit(EXIT_FAILURE,
+                                               "port %d cannot parse packet 
type, please add --%s\n",
+                                               portid, 
CMD_LINE_OPT_PARSE_PTYPE);
+
                        qconf = &lcore_conf[lcore_id];
                        qconf->tx_queue_id[portid] = queueid;
                        queueid++;
@@ -2705,6 +2788,9 @@ main(int argc, char **argv)
                        if (ret < 0)
                                rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: 
err=%d,"
                                                "port=%d\n", ret, portid);
+                       if (parse_ptype)
+                               rte_eth_add_rx_callback(portid, queueid,
+                                               cb_parse_packet_type, NULL);
                }
        }

-- 
2.1.4

Reply via email to