+/* Check L3 packet type detection capablity of the NIC port */
+static int
+check_ptype(int portid)
+{
+ int i, ret;
+ int ptype_l3_ipv4 = 0, ptype_l3_ipv6 = 0;
+ uint32_t ptype_mask = RTE_PTYPE_L3_MASK;
+
+ ret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, NULL, 0);
+ if (ret <= 0)
+ return 0;
+
+ uint32_t ptypes[ret];
+
+ ret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, ptypes, ret);
+ 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;
+
+}
+
+/* Parse packet type of a packet by SW */
+static inline void
+parse_ptype(struct rte_mbuf *m)
+{
+ struct ether_hdr *eth_hdr;
+ uint32_t packet_type = RTE_PTYPE_UNKNOWN;
+ uint16_t ether_type;
+
+ eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+ ether_type = eth_hdr->ether_type;
+ if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4))
+ packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
+ else if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv6))
+ packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+
+ m->packet_type = packet_type;
+}
+
+/* callback function to detect packet type for a queue of a port */
+static uint16_t
+cb_parse_ptype(uint16_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)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_pkts; ++i)
+ parse_ptype(pkts[i]);
+
+ return nb_pkts;
+}
+
+static int
+init_routing_table(void)
+{
+ struct rte_lpm *lpm;
+ struct rte_lpm6 *lpm6;
+ int socket, ret;
+ unsigned i;
+
+ for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) {
+ if (socket_lpm[socket]) {
+ lpm = socket_lpm[socket];
+ /* populate the LPM table */
+ for (i = 0; i < RTE_DIM(l3fwd_ipv4_route_array); i++) {
+ ret = rte_lpm_add(lpm,
+ l3fwd_ipv4_route_array[i].ip,
+ l3fwd_ipv4_route_array[i].depth,
+ l3fwd_ipv4_route_array[i].if_out);
+
+ if (ret < 0) {
+ RTE_LOG(ERR, IP_FRAG, "Unable to add entry %i to the l3fwd "
+ "LPM table\n", i);
+ return -1;
+ }
+
+ RTE_LOG(INFO, IP_FRAG, "Socket %i: adding route " IPv4_BYTES_FMT
+ "/%d (port %d)\n",
+ socket,
+ IPv4_BYTES(l3fwd_ipv4_route_array[i].ip),
+ l3fwd_ipv4_route_array[i].depth,
+ l3fwd_ipv4_route_array[i].if_out);
+ }
+ }
+
+ if (socket_lpm6[socket]) {
+ lpm6 = socket_lpm6[socket];
+ /* populate the LPM6 table */
+ for (i = 0; i < RTE_DIM(l3fwd_ipv6_route_array); i++) {
+ ret = rte_lpm6_add(lpm6,
+ l3fwd_ipv6_route_array[i].ip,
+ l3fwd_ipv6_route_array[i].depth,
+ l3fwd_ipv6_route_array[i].if_out);
+
+ if (ret < 0) {
+ RTE_LOG(ERR, IP_FRAG, "Unable to add entry %i to the l3fwd "
+ "LPM6 table\n", i);
+ return -1;
+ }
+
+ RTE_LOG(INFO, IP_FRAG, "Socket %i: adding route " IPv6_BYTES_FMT
+ "/%d (port %d)\n",
+ socket,
+ IPv6_BYTES(l3fwd_ipv6_route_array[i].ip),
+ l3fwd_ipv6_route_array[i].depth,
+ l3fwd_ipv6_route_array[i].if_out);
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+init_mem(void)
+{
+ char buf[PATH_MAX];
+ struct rte_mempool *mp;
+ struct rte_lpm *lpm;
+ struct rte_lpm6 *lpm6;
+ struct rte_lpm_config lpm_config;
+ int socket;
+ unsigned lcore_id;
+
+ /* traverse through lcores and initialize structures on each socket */
+
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+
+ if (rte_lcore_is_enabled(lcore_id) == 0)
+ continue;
+
+ socket = rte_lcore_to_socket_id(lcore_id);
+
+ if (socket == SOCKET_ID_ANY)
+ socket = 0;
+
+ if (socket_direct_pool[socket] == NULL) {
+ RTE_LOG(INFO, IP_FRAG, "Creating direct mempool on socket %i\n",
+ socket);
+ snprintf(buf, sizeof(buf), "pool_direct_%i", socket);
+
+ mp = rte_pktmbuf_pool_create(buf, NB_MBUF, 32,
+ 0, RTE_MBUF_DEFAULT_BUF_SIZE, socket);
+ if (mp == NULL) {
+ RTE_LOG(ERR, IP_FRAG, "Cannot create direct mempool\n");
+ return -1;
+ }
+ socket_direct_pool[socket] = mp;
+ }
+
+ if (socket_indirect_pool[socket] == NULL) {
+ RTE_LOG(INFO, IP_FRAG, "Creating indirect mempool on socket %i\n",
+ socket);
+ snprintf(buf, sizeof(buf), "pool_indirect_%i", socket);
+
+ mp = rte_pktmbuf_pool_create(buf, NB_MBUF, 32, 0, 0,
+ socket);
+ if (mp == NULL) {
+ RTE_LOG(ERR, IP_FRAG, "Cannot create indirect mempool\n");
+ return -1;
+ }
+ socket_indirect_pool[socket] = mp;
+ }
+
+ if (socket_lpm[socket] == NULL) {
+ RTE_LOG(INFO, IP_FRAG, "Creating LPM table on socket %i\n", socket);
+ snprintf(buf, sizeof(buf), "IP_FRAG_LPM_%i", socket);
+
+ lpm_config.max_rules = LPM_MAX_RULES;
+ lpm_config.number_tbl8s = 256;
+ lpm_config.flags = 0;
+
+ lpm = rte_lpm_create(buf, socket, &lpm_config);
+ if (lpm == NULL) {
+ RTE_LOG(ERR, IP_FRAG, "Cannot create LPM table\n");
+ return -1;
+ }
+ socket_lpm[socket] = lpm;
+ }
+
+ if (socket_lpm6[socket] == NULL) {
+ RTE_LOG(INFO, IP_FRAG, "Creating LPM6 table on socket %i\n", socket);
+ snprintf(buf, sizeof(buf), "IP_FRAG_LPM_%i", socket);
+
+ lpm6 = rte_lpm6_create(buf, socket, &lpm6_config);
+ if (lpm6 == NULL) {
+ RTE_LOG(ERR, IP_FRAG, "Cannot create LPM table\n");
+ return -1;
+ }
+ socket_lpm6[socket] = lpm6;
+ }
+ }
+
+ return 0;
+}
+