本文共 3077 字,大约阅读时间需要 10 分钟。
dpdk版本:dpdk-stable-16.11.1
程序路径:example/vhost
启用dpdk的LRO
static struct rte_eth_conf default_port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, /**< hdr buf size */ .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .hw_vlan_strip = 0, /**< VLAN strip disabled. */ .hw_vlan_extend = 0, /**< Extended VLAN disabled. */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 1, /**< CRC stripped by hardware 这个也得打开*/ .enable_lro = 1, /*打开LRO功能*/ }, .rx_adv_conf = { .rss_conf = { .rss_key = default_rsskey_40bytes, .rss_key_len = 40, .rss_hf = ETH_RSS_PROTO_MASK, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, };
rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
通过上面代码,dpdk就使能了LRO功能
mbuf的默认长度是2048,当网卡收到大于2048的数据包时,会把数据包存入多个mbuf中,通过mbuf->next关联
但现在的dpdk代码虽然把数据包合并了,却没有计算合并后的数据包校验和,导致在vm中的数据直接丢掉。
vhost接口:
在virtio_enqueue_offload函数中设置VIRTIO_NET_HDR_F_DATA_VALID,可以使上层不检查数据包的校验和。
static voidvirtio_enqueue_offload(struct rte_mbuf *m_buf, struct virtio_net_hdr *net_hdr){ uint64_t csum_l4 = m_buf->ol_flags & PKT_TX_L4_MASK;ffload if (m_buf->ol_flags & PKT_TX_TCP_SEG) csum_l4 |= PKT_TX_TCP_CKSUM; net_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;#if 0 if (csum_l4) { net_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; net_hdr->csum_start = m_buf->l2_len + m_buf->l3_len; switch (csum_l4) { case PKT_TX_TCP_CKSUM: net_hdr->csum_offset = (offsetof(struct tcp_hdr, cksum)); break; case PKT_TX_UDP_CKSUM: net_hdr->csum_offset = (offsetof(struct udp_hdr, dgram_cksum)); break; case PKT_TX_SCTP_CKSUM: net_hdr->csum_offset = (offsetof(struct sctp_hdr, cksum));。。。。}
OVS中:
在netdev_dpdk_filter_packet_len函数里会检查数据包的长度,超过max_packet_len的数据都会被丢弃
static intnetdev_dpdk_filter_packet_len(struct netdev_dpdk *dev, struct rte_mbuf **pkts, int pkt_cnt){ int i = 0; int cnt = 0; struct rte_mbuf *pkt; for (i = 0; i < pkt_cnt; i++) { pkt = pkts[i]; if (OVS_UNLIKELY(pkt->pkt_len > dev->max_packet_len)) { VLOG_WARN_RL(&rl, "%s: Too big size %" PRIu32 " max_packet_len %d", dev->up.name, pkt->pkt_len, dev->max_packet_len); rte_pktmbuf_free(pkt); continue; pkt->data_len = 2044; } if (OVS_UNLIKELY(i != cnt)) { pkts[cnt] = pkt; } cnt++; } return cnt;}
转载地址:http://pbqci.baihongyu.com/