X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest-pmd%2Fcsumonly.c;h=7e4f6620ad59e254ab51236abf4505f21ab82c19;hb=d4c18f0a1d5d03297a393b6bcda90e5acc27c710;hp=0a7af7989a9564f2f626552886b26a41ea07e9c0;hpb=08f661aca1178b4f000fdd50c2881df0f4156120;p=dpdk.git diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c index 0a7af7989a..7e4f6620ad 100644 --- a/app/test-pmd/csumonly.c +++ b/app/test-pmd/csumonly.c @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include @@ -79,6 +78,10 @@ #define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */ #define IP_VHL_DEF (IP_VERSION | IP_HDRLEN) +#define GRE_KEY_PRESENT 0x2000 +#define GRE_KEY_LEN 4 +#define GRE_SUPPORTED_FIELDS GRE_KEY_PRESENT + /* We cannot use rte_cpu_to_be_16() on a constant in a switch/case */ #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN #define _htons(x) ((uint16_t)((((x) & 0x00ffU) << 8) | (((x) & 0xff00U) >> 8))) @@ -101,11 +104,11 @@ struct testpmd_offload_info { uint16_t tso_segsz; }; -/* simplified GRE header (flags must be 0) */ +/* simplified GRE header */ struct simple_gre_hdr { uint16_t flags; uint16_t proto; -}; +} __attribute__((__packed__)); static uint16_t get_psd_sum(void *l3_hdr, uint16_t ethertype, uint64_t ol_flags) @@ -199,8 +202,9 @@ parse_ethernet(struct ether_hdr *eth_hdr, struct testpmd_offload_info *info) /* Parse a vxlan header */ static void -parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info, - uint64_t mbuf_olflags) +parse_vxlan(struct udp_hdr *udp_hdr, + struct testpmd_offload_info *info, + uint32_t pkt_type) { struct ether_hdr *eth_hdr; @@ -208,8 +212,7 @@ parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info, * (rfc7348) or that the rx offload flag is set (i40e only * currently) */ if (udp_hdr->dst_port != _htons(4789) && - (mbuf_olflags & (PKT_RX_TUNNEL_IPV4_HDR | - PKT_RX_TUNNEL_IPV6_HDR)) == 0) + RTE_ETH_IS_TUNNEL_PKT(pkt_type) == 0) return; info->is_tunnel = 1; @@ -233,11 +236,17 @@ parse_gre(struct simple_gre_hdr *gre_hdr, struct testpmd_offload_info *info) struct ether_hdr *eth_hdr; struct ipv4_hdr *ipv4_hdr; struct ipv6_hdr *ipv6_hdr; + uint8_t gre_len = 0; - /* if flags != 0; it's not supported */ - if (gre_hdr->flags != 0) + /* check which fields are supported */ + if ((gre_hdr->flags & _htons(~GRE_SUPPORTED_FIELDS)) != 0) return; + gre_len += sizeof(struct simple_gre_hdr); + + if (gre_hdr->flags & _htons(GRE_KEY_PRESENT)) + gre_len += GRE_KEY_LEN; + if (gre_hdr->proto == _htons(ETHER_TYPE_IPv4)) { info->is_tunnel = 1; info->outer_ethertype = info->ethertype; @@ -245,8 +254,7 @@ parse_gre(struct simple_gre_hdr *gre_hdr, struct testpmd_offload_info *info) info->outer_l3_len = info->l3_len; info->outer_l4_proto = info->l4_proto; - ipv4_hdr = (struct ipv4_hdr *)((char *)gre_hdr + - sizeof(struct simple_gre_hdr)); + ipv4_hdr = (struct ipv4_hdr *)((char *)gre_hdr + gre_len); parse_ipv4(ipv4_hdr, info); info->ethertype = _htons(ETHER_TYPE_IPv4); @@ -259,28 +267,26 @@ parse_gre(struct simple_gre_hdr *gre_hdr, struct testpmd_offload_info *info) info->outer_l3_len = info->l3_len; info->outer_l4_proto = info->l4_proto; - ipv6_hdr = (struct ipv6_hdr *)((char *)gre_hdr + - sizeof(struct simple_gre_hdr)); + ipv6_hdr = (struct ipv6_hdr *)((char *)gre_hdr + gre_len); info->ethertype = _htons(ETHER_TYPE_IPv6); parse_ipv6(ipv6_hdr, info); info->l2_len = 0; - } else if (gre_hdr->proto == _htons(0x6558)) { /* ETH_P_TEB in linux */ + } else if (gre_hdr->proto == _htons(ETHER_TYPE_TEB)) { info->is_tunnel = 1; info->outer_ethertype = info->ethertype; info->outer_l2_len = info->l2_len; info->outer_l3_len = info->l3_len; info->outer_l4_proto = info->l4_proto; - eth_hdr = (struct ether_hdr *)((char *)gre_hdr + - sizeof(struct simple_gre_hdr)); + eth_hdr = (struct ether_hdr *)((char *)gre_hdr + gre_len); parse_ethernet(eth_hdr, info); } else return; - info->l2_len += sizeof(struct simple_gre_hdr); + info->l2_len += gre_len; } @@ -450,6 +456,155 @@ process_outer_cksums(void *outer_l3_hdr, struct testpmd_offload_info *info, return ol_flags; } +/* + * Helper function. + * Performs actual copying. + * Returns number of segments in the destination mbuf on success, + * or negative error code on failure. + */ +static int +mbuf_copy_split(const struct rte_mbuf *ms, struct rte_mbuf *md[], + uint16_t seglen[], uint8_t nb_seg) +{ + uint32_t dlen, slen, tlen; + uint32_t i, len; + const struct rte_mbuf *m; + const uint8_t *src; + uint8_t *dst; + + dlen = 0; + slen = 0; + tlen = 0; + + dst = NULL; + src = NULL; + + m = ms; + i = 0; + while (ms != NULL && i != nb_seg) { + + if (slen == 0) { + slen = rte_pktmbuf_data_len(ms); + src = rte_pktmbuf_mtod(ms, const uint8_t *); + } + + if (dlen == 0) { + dlen = RTE_MIN(seglen[i], slen); + md[i]->data_len = dlen; + md[i]->next = (i + 1 == nb_seg) ? NULL : md[i + 1]; + dst = rte_pktmbuf_mtod(md[i], uint8_t *); + } + + len = RTE_MIN(slen, dlen); + memcpy(dst, src, len); + tlen += len; + slen -= len; + dlen -= len; + src += len; + dst += len; + + if (slen == 0) + ms = ms->next; + if (dlen == 0) + i++; + } + + if (ms != NULL) + return -ENOBUFS; + else if (tlen != m->pkt_len) + return -EINVAL; + + md[0]->nb_segs = nb_seg; + md[0]->pkt_len = tlen; + md[0]->vlan_tci = m->vlan_tci; + md[0]->vlan_tci_outer = m->vlan_tci_outer; + md[0]->ol_flags = m->ol_flags; + md[0]->tx_offload = m->tx_offload; + + return nb_seg; +} + +/* + * Allocate a new mbuf with up to tx_pkt_nb_segs segments. + * Copy packet contents and offload information into then new segmented mbuf. + */ +static struct rte_mbuf * +pkt_copy_split(const struct rte_mbuf *pkt) +{ + int32_t n, rc; + uint32_t i, len, nb_seg; + struct rte_mempool *mp; + uint16_t seglen[RTE_MAX_SEGS_PER_PKT]; + struct rte_mbuf *p, *md[RTE_MAX_SEGS_PER_PKT]; + + mp = current_fwd_lcore()->mbp; + + if (tx_pkt_split == TX_PKT_SPLIT_RND) + nb_seg = random() % tx_pkt_nb_segs + 1; + else + nb_seg = tx_pkt_nb_segs; + + memcpy(seglen, tx_pkt_seg_lengths, nb_seg * sizeof(seglen[0])); + + /* calculate number of segments to use and their length. */ + len = 0; + for (i = 0; i != nb_seg && len < pkt->pkt_len; i++) { + len += seglen[i]; + md[i] = NULL; + } + + n = pkt->pkt_len - len; + + /* update size of the last segment to fit rest of the packet */ + if (n >= 0) { + seglen[i - 1] += n; + len += n; + } + + nb_seg = i; + while (i != 0) { + p = rte_pktmbuf_alloc(mp); + if (p == NULL) { + RTE_LOG(ERR, USER1, + "failed to allocate %u-th of %u mbuf " + "from mempool: %s\n", + nb_seg - i, nb_seg, mp->name); + break; + } + + md[--i] = p; + if (rte_pktmbuf_tailroom(md[i]) < seglen[i]) { + RTE_LOG(ERR, USER1, "mempool %s, %u-th segment: " + "expected seglen: %u, " + "actual mbuf tailroom: %u\n", + mp->name, i, seglen[i], + rte_pktmbuf_tailroom(md[i])); + break; + } + } + + /* all mbufs successfully allocated, do copy */ + if (i == 0) { + rc = mbuf_copy_split(pkt, md, seglen, nb_seg); + if (rc < 0) + RTE_LOG(ERR, USER1, + "mbuf_copy_split for %p(len=%u, nb_seg=%hhu) " + "into %u segments failed with error code: %d\n", + pkt, pkt->pkt_len, pkt->nb_segs, nb_seg, rc); + + /* figure out how many mbufs to free. */ + i = RTE_MAX(rc, 0); + } + + /* free unused mbufs */ + for (; i != nb_seg; i++) { + rte_pktmbuf_free_seg(md[i]); + md[i] = NULL; + } + + return md[0]; +} + /* * Receive a burst of packets, and for each packet: * - parse packet, and try to recognize a supported packet type (1) @@ -480,7 +635,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_port *txp; - struct rte_mbuf *m; + struct rte_mbuf *m, *p; struct ether_hdr *eth_hdr; void *l3_hdr = NULL, *outer_l3_hdr = NULL; /* can be IPv4 or IPv6 */ uint16_t nb_rx; @@ -534,6 +689,10 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) * and inner headers */ eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); + ether_addr_copy(&peer_eth_addrs[fs->peer_addr], + ð_hdr->d_addr); + ether_addr_copy(&ports[fs->tx_port].eth_addr, + ð_hdr->s_addr); parse_ethernet(eth_hdr, &info); l3_hdr = (char *)eth_hdr + info.l2_len; @@ -543,7 +702,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) struct udp_hdr *udp_hdr; udp_hdr = (struct udp_hdr *)((char *)l3_hdr + info.l3_len); - parse_vxlan(udp_hdr, &info, m->ol_flags); + parse_vxlan(udp_hdr, &info, m->packet_type); } else if (info.l4_proto == IPPROTO_GRE) { struct simple_gre_hdr *gre_hdr; gre_hdr = (struct simple_gre_hdr *) @@ -617,6 +776,16 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) m->tso_segsz = info.tso_segsz; m->ol_flags = ol_flags; + /* Do split & copy for the packet. */ + if (tx_pkt_split != TX_PKT_SPLIT_OFF) { + p = pkt_copy_split(m); + if (p != NULL) { + rte_pktmbuf_free(m); + m = p; + pkts_burst[i] = m; + } + } + /* if verbose mode is enabled, dump debug info */ if (verbose_level > 0) { struct { @@ -638,6 +807,8 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) const char *name; printf("-----------------\n"); + printf("mbuf=%p, pkt_len=%u, nb_segs=%hhu:\n", + m, m->pkt_len, m->nb_segs); /* dump rx parsed packet info */ printf("rx: l2_len=%d ethertype=%x l3_len=%d " "l4_proto=%d l4_len=%d\n", @@ -700,4 +871,3 @@ struct fwd_engine csum_fwd_engine = { .port_fwd_end = NULL, .packet_fwd = pkt_burst_checksum_forward, }; -