Hi Jianfeng, > -----Original Message----- > From: Tan, Jianfeng > Sent: Thursday, December 31, 2015 6:53 AM > To: dev at dpdk.org > Cc: Zhang, Helin; Ananyev, Konstantin; Tan, Jianfeng > Subject: [PATCH 12/12] examples/l3fwd: add option to parse ptype > > 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) {
I don't think either LPM or EM support packets with VLAN right now. So, probably there is no need to support it here. > + 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; Probably: m->packet_type |= packet_type; in case HW supports some other packet types. > +} > + > +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); Need to check return value. Konstantin > } > } > > -- > 2.1.4