net/eth: Introduce EthL4HdrProto

igb, a new network device emulation, will need SCTP checksum offloading.
Currently eth_get_protocols() has a bool parameter for each protocol
currently it supports, but there will be a bit too many parameters if
we add yet another protocol.

Introduce an enum type, EthL4HdrProto to represent all L4 protocols
eth_get_protocols() support with one parameter.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
Akihiko Odaki 2023-02-23 19:50:49 +09:00 committed by Jason Wang
parent 5fb7d14995
commit 65f474bbae
8 changed files with 147 additions and 99 deletions

View file

@ -497,18 +497,20 @@ typedef struct E1000E_RSSInfo_st {
static uint32_t static uint32_t
e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt) e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt)
{ {
bool hasip4, hasip6, hasudp, hastcp; bool hasip4, hasip6;
EthL4HdrProto l4hdr_proto;
assert(e1000e_rss_enabled(core)); assert(e1000e_rss_enabled(core));
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp); net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
if (hasip4) { if (hasip4) {
trace_e1000e_rx_rss_ip4(hastcp, core->mac[MRQC], trace_e1000e_rx_rss_ip4(l4hdr_proto, core->mac[MRQC],
E1000_MRQC_EN_TCPIPV4(core->mac[MRQC]), E1000_MRQC_EN_TCPIPV4(core->mac[MRQC]),
E1000_MRQC_EN_IPV4(core->mac[MRQC])); E1000_MRQC_EN_IPV4(core->mac[MRQC]));
if (hastcp && E1000_MRQC_EN_TCPIPV4(core->mac[MRQC])) { if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP &&
E1000_MRQC_EN_TCPIPV4(core->mac[MRQC])) {
return E1000_MRQ_RSS_TYPE_IPV4TCP; return E1000_MRQ_RSS_TYPE_IPV4TCP;
} }
@ -529,7 +531,7 @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt)
* backends like these. * backends like these.
*/ */
trace_e1000e_rx_rss_ip6_rfctl(core->mac[RFCTL]); trace_e1000e_rx_rss_ip6_rfctl(core->mac[RFCTL]);
trace_e1000e_rx_rss_ip6(ex_dis, new_ex_dis, hastcp, trace_e1000e_rx_rss_ip6(ex_dis, new_ex_dis, l4hdr_proto,
ip6info->has_ext_hdrs, ip6info->has_ext_hdrs,
ip6info->rss_ex_dst_valid, ip6info->rss_ex_dst_valid,
ip6info->rss_ex_src_valid, ip6info->rss_ex_src_valid,
@ -542,7 +544,8 @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt)
(!new_ex_dis || !(ip6info->rss_ex_dst_valid || (!new_ex_dis || !(ip6info->rss_ex_dst_valid ||
ip6info->rss_ex_src_valid))) { ip6info->rss_ex_src_valid))) {
if (hastcp && E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) { if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP &&
E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) {
return E1000_MRQ_RSS_TYPE_IPV6TCP; return E1000_MRQ_RSS_TYPE_IPV6TCP;
} }
@ -1124,7 +1127,7 @@ static void
e1000e_verify_csum_in_sw(E1000ECore *core, e1000e_verify_csum_in_sw(E1000ECore *core,
struct NetRxPkt *pkt, struct NetRxPkt *pkt,
uint32_t *status_flags, uint32_t *status_flags,
bool hastcp, bool hasudp) EthL4HdrProto l4hdr_proto)
{ {
bool csum_valid; bool csum_valid;
uint32_t csum_error; uint32_t csum_error;
@ -1151,14 +1154,10 @@ e1000e_verify_csum_in_sw(E1000ECore *core,
} }
csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_TCPE; csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_TCPE;
*status_flags |= E1000_RXD_STAT_TCPCS | csum_error;
if (hastcp) { if (l4hdr_proto == ETH_L4_HDR_PROTO_UDP) {
*status_flags |= E1000_RXD_STAT_TCPCS | *status_flags |= E1000_RXD_STAT_UDPCS;
csum_error;
} else if (hasudp) {
*status_flags |= E1000_RXD_STAT_TCPCS |
E1000_RXD_STAT_UDPCS |
csum_error;
} }
} }
@ -1187,7 +1186,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
uint16_t *vlan_tag) uint16_t *vlan_tag)
{ {
struct virtio_net_hdr *vhdr; struct virtio_net_hdr *vhdr;
bool hasip4, hasip6, hastcp, hasudp; bool hasip4, hasip6;
EthL4HdrProto l4hdr_proto;
uint32_t pkt_type; uint32_t pkt_type;
*status_flags = E1000_RXD_STAT_DD; *status_flags = E1000_RXD_STAT_DD;
@ -1199,8 +1199,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
*status_flags |= E1000_RXD_STAT_EOP; *status_flags |= E1000_RXD_STAT_EOP;
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp); net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
trace_e1000e_rx_metadata_protocols(hasip4, hasip6, hasudp, hastcp); trace_e1000e_rx_metadata_protocols(hasip4, hasip6, l4hdr_proto);
/* VLAN state */ /* VLAN state */
if (net_rx_pkt_is_vlan_stripped(pkt)) { if (net_rx_pkt_is_vlan_stripped(pkt)) {
@ -1222,7 +1222,7 @@ e1000e_build_rx_metadata(E1000ECore *core,
trace_e1000e_rx_metadata_ip_id(*ip_id); trace_e1000e_rx_metadata_ip_id(*ip_id);
} }
if (hastcp && e1000e_is_tcp_ack(core, pkt)) { if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP && e1000e_is_tcp_ack(core, pkt)) {
*status_flags |= E1000_RXD_STAT_ACK; *status_flags |= E1000_RXD_STAT_ACK;
trace_e1000e_rx_metadata_ack(); trace_e1000e_rx_metadata_ack();
} }
@ -1230,7 +1230,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
if (hasip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_DIS)) { if (hasip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_DIS)) {
trace_e1000e_rx_metadata_ipv6_filtering_disabled(); trace_e1000e_rx_metadata_ipv6_filtering_disabled();
pkt_type = E1000_RXD_PKT_MAC; pkt_type = E1000_RXD_PKT_MAC;
} else if (hastcp || hasudp) { } else if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP ||
l4hdr_proto == ETH_L4_HDR_PROTO_UDP) {
pkt_type = hasip4 ? E1000_RXD_PKT_IP4_XDP : E1000_RXD_PKT_IP6_XDP; pkt_type = hasip4 ? E1000_RXD_PKT_IP4_XDP : E1000_RXD_PKT_IP6_XDP;
} else if (hasip4 || hasip6) { } else if (hasip4 || hasip6) {
pkt_type = hasip4 ? E1000_RXD_PKT_IP4 : E1000_RXD_PKT_IP6; pkt_type = hasip4 ? E1000_RXD_PKT_IP4 : E1000_RXD_PKT_IP6;
@ -1252,7 +1253,7 @@ e1000e_build_rx_metadata(E1000ECore *core,
if (!(vhdr->flags & VIRTIO_NET_HDR_F_DATA_VALID) && if (!(vhdr->flags & VIRTIO_NET_HDR_F_DATA_VALID) &&
!(vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM)) { !(vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
trace_e1000e_rx_metadata_virthdr_no_csum_info(); trace_e1000e_rx_metadata_virthdr_no_csum_info();
e1000e_verify_csum_in_sw(core, pkt, status_flags, hastcp, hasudp); e1000e_verify_csum_in_sw(core, pkt, status_flags, l4hdr_proto);
goto func_exit; goto func_exit;
} }
@ -1263,10 +1264,17 @@ e1000e_build_rx_metadata(E1000ECore *core,
} }
if (e1000e_rx_l4_cso_enabled(core)) { if (e1000e_rx_l4_cso_enabled(core)) {
if (hastcp) { switch (l4hdr_proto) {
case ETH_L4_HDR_PROTO_TCP:
*status_flags |= E1000_RXD_STAT_TCPCS; *status_flags |= E1000_RXD_STAT_TCPCS;
} else if (hasudp) { break;
case ETH_L4_HDR_PROTO_UDP:
*status_flags |= E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS; *status_flags |= E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS;
break;
default:
break;
} }
} else { } else {
trace_e1000e_rx_metadata_l4_cso_disabled(); trace_e1000e_rx_metadata_l4_cso_disabled();
@ -1509,14 +1517,15 @@ e1000e_rx_descr_threshold_hit(E1000ECore *core, const E1000E_RingInfo *rxi)
static bool static bool
e1000e_do_ps(E1000ECore *core, struct NetRxPkt *pkt, size_t *hdr_len) e1000e_do_ps(E1000ECore *core, struct NetRxPkt *pkt, size_t *hdr_len)
{ {
bool hasip4, hasip6, hasudp, hastcp; bool hasip4, hasip6;
EthL4HdrProto l4hdr_proto;
bool fragment; bool fragment;
if (!e1000e_rx_use_ps_descriptor(core)) { if (!e1000e_rx_use_ps_descriptor(core)) {
return false; return false;
} }
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp); net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
if (hasip4) { if (hasip4) {
fragment = net_rx_pkt_get_ip4_info(pkt)->fragment; fragment = net_rx_pkt_get_ip4_info(pkt)->fragment;
@ -1530,7 +1539,8 @@ e1000e_do_ps(E1000ECore *core, struct NetRxPkt *pkt, size_t *hdr_len)
return false; return false;
} }
if (hasudp || hastcp) { if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP ||
l4hdr_proto == ETH_L4_HDR_PROTO_UDP) {
*hdr_len = net_rx_pkt_get_l5_hdr_offset(pkt); *hdr_len = net_rx_pkt_get_l5_hdr_offset(pkt);
} else { } else {
*hdr_len = net_rx_pkt_get_l4_hdr_offset(pkt); *hdr_len = net_rx_pkt_get_l4_hdr_offset(pkt);

View file

@ -35,8 +35,6 @@ struct NetRxPkt {
/* Analysis results */ /* Analysis results */
bool hasip4; bool hasip4;
bool hasip6; bool hasip6;
bool hasudp;
bool hastcp;
size_t l3hdr_off; size_t l3hdr_off;
size_t l4hdr_off; size_t l4hdr_off;
@ -106,11 +104,10 @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
} }
eth_get_protocols(pkt->vec, pkt->vec_len, &pkt->hasip4, &pkt->hasip6, eth_get_protocols(pkt->vec, pkt->vec_len, &pkt->hasip4, &pkt->hasip6,
&pkt->hasudp, &pkt->hastcp,
&pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off, &pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off,
&pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info); &pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info);
trace_net_rx_pkt_parsed(pkt->hasip4, pkt->hasip6, pkt->hasudp, pkt->hastcp, trace_net_rx_pkt_parsed(pkt->hasip4, pkt->hasip6, pkt->l4hdr_info.proto,
pkt->l3hdr_off, pkt->l4hdr_off, pkt->l5hdr_off); pkt->l3hdr_off, pkt->l4hdr_off, pkt->l5hdr_off);
} }
@ -200,21 +197,19 @@ void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data,
assert(pkt); assert(pkt);
eth_get_protocols(&iov, 1, &pkt->hasip4, &pkt->hasip6, eth_get_protocols(&iov, 1, &pkt->hasip4, &pkt->hasip6,
&pkt->hasudp, &pkt->hastcp,
&pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off, &pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off,
&pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info); &pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info);
} }
void net_rx_pkt_get_protocols(struct NetRxPkt *pkt, void net_rx_pkt_get_protocols(struct NetRxPkt *pkt,
bool *hasip4, bool *hasip6, bool *hasip4, bool *hasip6,
bool *hasudp, bool *hastcp) EthL4HdrProto *l4hdr_proto)
{ {
assert(pkt); assert(pkt);
*hasip4 = pkt->hasip4; *hasip4 = pkt->hasip4;
*hasip6 = pkt->hasip6; *hasip6 = pkt->hasip6;
*hasudp = pkt->hasudp; *l4hdr_proto = pkt->l4hdr_info.proto;
*hastcp = pkt->hastcp;
} }
size_t net_rx_pkt_get_l3_hdr_offset(struct NetRxPkt *pkt) size_t net_rx_pkt_get_l3_hdr_offset(struct NetRxPkt *pkt)
@ -337,14 +332,14 @@ net_rx_pkt_calc_rss_hash(struct NetRxPkt *pkt,
break; break;
case NetPktRssIpV4Tcp: case NetPktRssIpV4Tcp:
assert(pkt->hasip4); assert(pkt->hasip4);
assert(pkt->hastcp); assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP);
trace_net_rx_pkt_rss_ip4_tcp(); trace_net_rx_pkt_rss_ip4_tcp();
_net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length); _net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length);
_net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length); _net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length);
break; break;
case NetPktRssIpV6Tcp: case NetPktRssIpV6Tcp:
assert(pkt->hasip6); assert(pkt->hasip6);
assert(pkt->hastcp); assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP);
trace_net_rx_pkt_rss_ip6_tcp(); trace_net_rx_pkt_rss_ip6_tcp();
_net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length); _net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length);
_net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length); _net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length);
@ -361,28 +356,28 @@ net_rx_pkt_calc_rss_hash(struct NetRxPkt *pkt,
break; break;
case NetPktRssIpV6TcpEx: case NetPktRssIpV6TcpEx:
assert(pkt->hasip6); assert(pkt->hasip6);
assert(pkt->hastcp); assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP);
trace_net_rx_pkt_rss_ip6_ex_tcp(); trace_net_rx_pkt_rss_ip6_ex_tcp();
_net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length); _net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length);
_net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length); _net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length);
break; break;
case NetPktRssIpV4Udp: case NetPktRssIpV4Udp:
assert(pkt->hasip4); assert(pkt->hasip4);
assert(pkt->hasudp); assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP);
trace_net_rx_pkt_rss_ip4_udp(); trace_net_rx_pkt_rss_ip4_udp();
_net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length); _net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length);
_net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length); _net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length);
break; break;
case NetPktRssIpV6Udp: case NetPktRssIpV6Udp:
assert(pkt->hasip6); assert(pkt->hasip6);
assert(pkt->hasudp); assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP);
trace_net_rx_pkt_rss_ip6_udp(); trace_net_rx_pkt_rss_ip6_udp();
_net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length); _net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length);
_net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length); _net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length);
break; break;
case NetPktRssIpV6UdpEx: case NetPktRssIpV6UdpEx:
assert(pkt->hasip6); assert(pkt->hasip6);
assert(pkt->hasudp); assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP);
trace_net_rx_pkt_rss_ip6_ex_udp(); trace_net_rx_pkt_rss_ip6_ex_udp();
_net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length); _net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length);
_net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length); _net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length);
@ -415,7 +410,7 @@ bool net_rx_pkt_is_tcp_ack(struct NetRxPkt *pkt)
{ {
assert(pkt); assert(pkt);
if (pkt->hastcp) { if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP) {
return TCP_HEADER_FLAGS(&pkt->l4hdr_info.hdr.tcp) & TCP_FLAG_ACK; return TCP_HEADER_FLAGS(&pkt->l4hdr_info.hdr.tcp) & TCP_FLAG_ACK;
} }
@ -426,7 +421,7 @@ bool net_rx_pkt_has_tcp_data(struct NetRxPkt *pkt)
{ {
assert(pkt); assert(pkt);
if (pkt->hastcp) { if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP) {
return pkt->l4hdr_info.has_tcp_data; return pkt->l4hdr_info.has_tcp_data;
} }
@ -524,7 +519,7 @@ _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt)
trace_net_rx_pkt_l4_csum_calc_entry(); trace_net_rx_pkt_l4_csum_calc_entry();
if (pkt->hasip4) { if (pkt->hasip4) {
if (pkt->hasudp) { if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP) {
csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen); csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen);
trace_net_rx_pkt_l4_csum_calc_ip4_udp(); trace_net_rx_pkt_l4_csum_calc_ip4_udp();
} else { } else {
@ -537,7 +532,7 @@ _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt)
csl, &cso); csl, &cso);
trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl); trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl);
} else { } else {
if (pkt->hasudp) { if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP) {
csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen); csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen);
trace_net_rx_pkt_l4_csum_calc_ip6_udp(); trace_net_rx_pkt_l4_csum_calc_ip6_udp();
} else { } else {
@ -571,12 +566,14 @@ bool net_rx_pkt_validate_l4_csum(struct NetRxPkt *pkt, bool *csum_valid)
trace_net_rx_pkt_l4_csum_validate_entry(); trace_net_rx_pkt_l4_csum_validate_entry();
if (!pkt->hastcp && !pkt->hasudp) { if (pkt->l4hdr_info.proto != ETH_L4_HDR_PROTO_TCP &&
pkt->l4hdr_info.proto != ETH_L4_HDR_PROTO_UDP) {
trace_net_rx_pkt_l4_csum_validate_not_xxp(); trace_net_rx_pkt_l4_csum_validate_not_xxp();
return false; return false;
} }
if (pkt->hasudp && (pkt->l4hdr_info.hdr.udp.uh_sum == 0)) { if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP &&
pkt->l4hdr_info.hdr.udp.uh_sum == 0) {
trace_net_rx_pkt_l4_csum_validate_udp_with_no_checksum(); trace_net_rx_pkt_l4_csum_validate_udp_with_no_checksum();
return false; return false;
} }
@ -602,17 +599,22 @@ bool net_rx_pkt_fix_l4_csum(struct NetRxPkt *pkt)
trace_net_rx_pkt_l4_csum_fix_entry(); trace_net_rx_pkt_l4_csum_fix_entry();
if (pkt->hastcp) { switch (pkt->l4hdr_info.proto) {
case ETH_L4_HDR_PROTO_TCP:
l4_cso = offsetof(struct tcp_header, th_sum); l4_cso = offsetof(struct tcp_header, th_sum);
trace_net_rx_pkt_l4_csum_fix_tcp(l4_cso); trace_net_rx_pkt_l4_csum_fix_tcp(l4_cso);
} else if (pkt->hasudp) { break;
case ETH_L4_HDR_PROTO_UDP:
if (pkt->l4hdr_info.hdr.udp.uh_sum == 0) { if (pkt->l4hdr_info.hdr.udp.uh_sum == 0) {
trace_net_rx_pkt_l4_csum_fix_udp_with_no_checksum(); trace_net_rx_pkt_l4_csum_fix_udp_with_no_checksum();
return false; return false;
} }
l4_cso = offsetof(struct udp_header, uh_sum); l4_cso = offsetof(struct udp_header, uh_sum);
trace_net_rx_pkt_l4_csum_fix_udp(l4_cso); trace_net_rx_pkt_l4_csum_fix_udp(l4_cso);
} else { break;
default:
trace_net_rx_pkt_l4_csum_fix_not_xxp(); trace_net_rx_pkt_l4_csum_fix_not_xxp();
return false; return false;
} }

View file

@ -68,13 +68,12 @@ void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data,
* @pkt: packet * @pkt: packet
* @hasip4: whether the packet has an IPv4 header * @hasip4: whether the packet has an IPv4 header
* @hasip6: whether the packet has an IPv6 header * @hasip6: whether the packet has an IPv6 header
* @hasudp: whether the packet has a UDP header * @l4hdr_proto: protocol of L4 header
* @hastcp: whether the packet has a TCP header
* *
*/ */
void net_rx_pkt_get_protocols(struct NetRxPkt *pkt, void net_rx_pkt_get_protocols(struct NetRxPkt *pkt,
bool *hasip4, bool *hasip6, bool *hasip4, bool *hasip6,
bool *hasudp, bool *hastcp); EthL4HdrProto *l4hdr_proto);
/** /**
* fetches L3 header offset * fetches L3 header offset

View file

@ -61,7 +61,7 @@ pcnet_ioport_read(void *opaque, uint64_t addr, unsigned size) "opaque=%p addr=0x
pcnet_ioport_write(void *opaque, uint64_t addr, uint64_t data, unsigned size) "opaque=%p addr=0x%"PRIx64" data=0x%"PRIx64" size=%d" pcnet_ioport_write(void *opaque, uint64_t addr, uint64_t data, unsigned size) "opaque=%p addr=0x%"PRIx64" data=0x%"PRIx64" size=%d"
# net_rx_pkt.c # net_rx_pkt.c
net_rx_pkt_parsed(bool ip4, bool ip6, bool udp, bool tcp, size_t l3o, size_t l4o, size_t l5o) "RX packet parsed: ip4: %d, ip6: %d, udp: %d, tcp: %d, l3 offset: %zu, l4 offset: %zu, l5 offset: %zu" net_rx_pkt_parsed(bool ip4, bool ip6, int l4proto, size_t l3o, size_t l4o, size_t l5o) "RX packet parsed: ip4: %d, ip6: %d, l4 protocol: %d, l3 offset: %zu, l4 offset: %zu, l5 offset: %zu"
net_rx_pkt_l4_csum_validate_entry(void) "Starting L4 checksum validation" net_rx_pkt_l4_csum_validate_entry(void) "Starting L4 checksum validation"
net_rx_pkt_l4_csum_validate_not_xxp(void) "Not a TCP/UDP packet" net_rx_pkt_l4_csum_validate_not_xxp(void) "Not a TCP/UDP packet"
net_rx_pkt_l4_csum_validate_udp_with_no_checksum(void) "UDP packet without checksum" net_rx_pkt_l4_csum_validate_udp_with_no_checksum(void) "UDP packet without checksum"
@ -177,11 +177,11 @@ e1000e_rx_start_recv(void)
e1000e_rx_rss_started(void) "Starting RSS processing" e1000e_rx_rss_started(void) "Starting RSS processing"
e1000e_rx_rss_disabled(void) "RSS is disabled" e1000e_rx_rss_disabled(void) "RSS is disabled"
e1000e_rx_rss_type(uint32_t type) "RSS type is %u" e1000e_rx_rss_type(uint32_t type) "RSS type is %u"
e1000e_rx_rss_ip4(bool hastcp, uint32_t mrqc, bool tcpipv4_enabled, bool ipv4_enabled) "RSS IPv4: tcp %d, mrqc 0x%X, tcpipv4 enabled %d, ipv4 enabled %d" e1000e_rx_rss_ip4(int l4hdr_proto, uint32_t mrqc, bool tcpipv4_enabled, bool ipv4_enabled) "RSS IPv4: L4 header protocol %d, mrqc 0x%X, tcpipv4 enabled %d, ipv4 enabled %d"
e1000e_rx_rss_ip6_rfctl(uint32_t rfctl) "RSS IPv6: rfctl 0x%X" e1000e_rx_rss_ip6_rfctl(uint32_t rfctl) "RSS IPv6: rfctl 0x%X"
e1000e_rx_rss_ip6(bool ex_dis, bool new_ex_dis, bool hastcp, bool has_ext_headers, bool ex_dst_valid, bool ex_src_valid, uint32_t mrqc, bool tcpipv6_enabled, bool ipv6ex_enabled, bool ipv6_enabled) "RSS IPv6: ex_dis: %d, new_ex_dis: %d, tcp %d, has_ext_headers %d, ex_dst_valid %d, ex_src_valid %d, mrqc 0x%X, tcpipv6 enabled %d, ipv6ex enabled %d, ipv6 enabled %d" e1000e_rx_rss_ip6(bool ex_dis, bool new_ex_dis, int l4hdr_proto, bool has_ext_headers, bool ex_dst_valid, bool ex_src_valid, uint32_t mrqc, bool tcpipv6_enabled, bool ipv6ex_enabled, bool ipv6_enabled) "RSS IPv6: ex_dis: %d, new_ex_dis: %d, L4 header protocol %d, has_ext_headers %d, ex_dst_valid %d, ex_src_valid %d, mrqc 0x%X, tcpipv6 enabled %d, ipv6ex enabled %d, ipv6 enabled %d"
e1000e_rx_metadata_protocols(bool hasip4, bool hasip6, bool hasudp, bool hastcp) "protocols: ip4: %d, ip6: %d, udp: %d, tcp: %d" e1000e_rx_metadata_protocols(bool hasip4, bool hasip6, int l4hdr_protocol) "protocols: ip4: %d, ip6: %d, l4hdr: %d"
e1000e_rx_metadata_vlan(uint16_t vlan_tag) "VLAN tag is 0x%X" e1000e_rx_metadata_vlan(uint16_t vlan_tag) "VLAN tag is 0x%X"
e1000e_rx_metadata_rss(uint32_t rss, uint32_t mrq) "RSS data: rss: 0x%X, mrq: 0x%X" e1000e_rx_metadata_rss(uint32_t rss, uint32_t mrq) "RSS data: rss: 0x%X, mrq: 0x%X"
e1000e_rx_metadata_ip_id(uint16_t ip_id) "the IPv4 ID is 0x%X" e1000e_rx_metadata_ip_id(uint16_t ip_id) "the IPv4 ID is 0x%X"

View file

@ -1748,37 +1748,59 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
static uint8_t virtio_net_get_hash_type(bool hasip4, static uint8_t virtio_net_get_hash_type(bool hasip4,
bool hasip6, bool hasip6,
bool hasudp, EthL4HdrProto l4hdr_proto,
bool hastcp,
uint32_t types) uint32_t types)
{ {
if (hasip4) { if (hasip4) {
if (hastcp && (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) { switch (l4hdr_proto) {
case ETH_L4_HDR_PROTO_TCP:
if (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4) {
return NetPktRssIpV4Tcp; return NetPktRssIpV4Tcp;
} }
if (hasudp && (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) { break;
case ETH_L4_HDR_PROTO_UDP:
if (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4) {
return NetPktRssIpV4Udp; return NetPktRssIpV4Udp;
} }
break;
default:
break;
}
if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) { if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) {
return NetPktRssIpV4; return NetPktRssIpV4;
} }
} else if (hasip6) { } else if (hasip6) {
uint32_t mask = VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | switch (l4hdr_proto) {
VIRTIO_NET_RSS_HASH_TYPE_TCPv6; case ETH_L4_HDR_PROTO_TCP:
if (types & VIRTIO_NET_RSS_HASH_TYPE_TCP_EX) {
return NetPktRssIpV6TcpEx;
}
if (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv6) {
return NetPktRssIpV6Tcp;
}
break;
if (hastcp && (types & mask)) { case ETH_L4_HDR_PROTO_UDP:
return (types & VIRTIO_NET_RSS_HASH_TYPE_TCP_EX) ? if (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) {
NetPktRssIpV6TcpEx : NetPktRssIpV6Tcp; return NetPktRssIpV6UdpEx;
} }
mask = VIRTIO_NET_RSS_HASH_TYPE_UDP_EX | VIRTIO_NET_RSS_HASH_TYPE_UDPv6; if (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv6) {
if (hasudp && (types & mask)) { return NetPktRssIpV6Udp;
return (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) ?
NetPktRssIpV6UdpEx : NetPktRssIpV6Udp;
} }
mask = VIRTIO_NET_RSS_HASH_TYPE_IP_EX | VIRTIO_NET_RSS_HASH_TYPE_IPv6; break;
if (types & mask) {
return (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) ? default:
NetPktRssIpV6Ex : NetPktRssIpV6; break;
}
if (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) {
return NetPktRssIpV6Ex;
}
if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv6) {
return NetPktRssIpV6;
} }
} }
return 0xff; return 0xff;
@ -1800,7 +1822,8 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
struct NetRxPkt *pkt = n->rx_pkt; struct NetRxPkt *pkt = n->rx_pkt;
uint8_t net_hash_type; uint8_t net_hash_type;
uint32_t hash; uint32_t hash;
bool hasip4, hasip6, hasudp, hastcp; bool hasip4, hasip6;
EthL4HdrProto l4hdr_proto;
static const uint8_t reports[NetPktRssIpV6UdpEx + 1] = { static const uint8_t reports[NetPktRssIpV6UdpEx + 1] = {
VIRTIO_NET_HASH_REPORT_IPv4, VIRTIO_NET_HASH_REPORT_IPv4,
VIRTIO_NET_HASH_REPORT_TCPv4, VIRTIO_NET_HASH_REPORT_TCPv4,
@ -1815,8 +1838,8 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len, net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len,
size - n->host_hdr_len); size - n->host_hdr_len);
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp); net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
net_hash_type = virtio_net_get_hash_type(hasip4, hasip6, hasudp, hastcp, net_hash_type = virtio_net_get_hash_type(hasip4, hasip6, l4hdr_proto,
n->rss_data.hash_types); n->rss_data.hash_types);
if (net_hash_type > NetPktRssIpV6UdpEx) { if (net_hash_type > NetPktRssIpV6UdpEx) {
if (n->rss_data.populate_hash) { if (n->rss_data.populate_hash) {

View file

@ -847,7 +847,8 @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
size_t pkt_len) size_t pkt_len)
{ {
struct virtio_net_hdr *vhdr; struct virtio_net_hdr *vhdr;
bool hasip4, hasip6, hastcp, hasudp; bool hasip4, hasip6;
EthL4HdrProto l4hdr_proto;
uint8_t *data; uint8_t *data;
int len; int len;
@ -856,8 +857,10 @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
return; return;
} }
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp); net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
if (!(hasip4 || hasip6) || !(hastcp || hasudp)) { if (!(hasip4 || hasip6) ||
(l4hdr_proto != ETH_L4_HDR_PROTO_TCP &&
l4hdr_proto != ETH_L4_HDR_PROTO_UDP)) {
return; return;
} }
@ -885,7 +888,8 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
struct Vmxnet3_RxCompDesc *rxcd) struct Vmxnet3_RxCompDesc *rxcd)
{ {
int csum_ok, is_gso; int csum_ok, is_gso;
bool hasip4, hasip6, hastcp, hasudp; bool hasip4, hasip6;
EthL4HdrProto l4hdr_proto;
struct virtio_net_hdr *vhdr; struct virtio_net_hdr *vhdr;
uint8_t offload_type; uint8_t offload_type;
@ -911,16 +915,18 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
goto nocsum; goto nocsum;
} }
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp); net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
if ((!hastcp && !hasudp) || (!hasip4 && !hasip6)) { if ((l4hdr_proto != ETH_L4_HDR_PROTO_TCP &&
l4hdr_proto != ETH_L4_HDR_PROTO_UDP) ||
(!hasip4 && !hasip6)) {
goto nocsum; goto nocsum;
} }
rxcd->cnc = 0; rxcd->cnc = 0;
rxcd->v4 = hasip4 ? 1 : 0; rxcd->v4 = hasip4 ? 1 : 0;
rxcd->v6 = hasip6 ? 1 : 0; rxcd->v6 = hasip6 ? 1 : 0;
rxcd->tcp = hastcp ? 1 : 0; rxcd->tcp = l4hdr_proto == ETH_L4_HDR_PROTO_TCP;
rxcd->udp = hasudp ? 1 : 0; rxcd->udp = l4hdr_proto == ETH_L4_HDR_PROTO_UDP;
rxcd->fcs = rxcd->tuc = rxcd->ipc = 1; rxcd->fcs = rxcd->tuc = rxcd->ipc = 1;
return; return;

View file

@ -381,18 +381,24 @@ typedef struct eth_ip4_hdr_info_st {
bool fragment; bool fragment;
} eth_ip4_hdr_info; } eth_ip4_hdr_info;
typedef enum EthL4HdrProto {
ETH_L4_HDR_PROTO_INVALID,
ETH_L4_HDR_PROTO_TCP,
ETH_L4_HDR_PROTO_UDP
} EthL4HdrProto;
typedef struct eth_l4_hdr_info_st { typedef struct eth_l4_hdr_info_st {
union { union {
struct tcp_header tcp; struct tcp_header tcp;
struct udp_header udp; struct udp_header udp;
} hdr; } hdr;
EthL4HdrProto proto;
bool has_tcp_data; bool has_tcp_data;
} eth_l4_hdr_info; } eth_l4_hdr_info;
void eth_get_protocols(const struct iovec *iov, int iovcnt, void eth_get_protocols(const struct iovec *iov, int iovcnt,
bool *hasip4, bool *hasip6, bool *hasip4, bool *hasip6,
bool *hasudp, bool *hastcp,
size_t *l3hdr_off, size_t *l3hdr_off,
size_t *l4hdr_off, size_t *l4hdr_off,
size_t *l5hdr_off, size_t *l5hdr_off,

View file

@ -138,7 +138,6 @@ _eth_tcp_has_data(bool is_ip4,
void eth_get_protocols(const struct iovec *iov, int iovcnt, void eth_get_protocols(const struct iovec *iov, int iovcnt,
bool *hasip4, bool *hasip6, bool *hasip4, bool *hasip6,
bool *hasudp, bool *hastcp,
size_t *l3hdr_off, size_t *l3hdr_off,
size_t *l4hdr_off, size_t *l4hdr_off,
size_t *l5hdr_off, size_t *l5hdr_off,
@ -153,7 +152,8 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
size_t copied; size_t copied;
uint8_t ip_p; uint8_t ip_p;
*hasip4 = *hasip6 = *hasudp = *hastcp = false; *hasip4 = *hasip6 = false;
l4hdr_info->proto = ETH_L4_HDR_PROTO_INVALID;
proto = eth_get_l3_proto(iov, iovcnt, l2hdr_len); proto = eth_get_l3_proto(iov, iovcnt, l2hdr_len);
@ -197,11 +197,11 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
switch (ip_p) { switch (ip_p) {
case IP_PROTO_TCP: case IP_PROTO_TCP:
*hastcp = _eth_copy_chunk(input_size, if (_eth_copy_chunk(input_size,
iov, iovcnt, iov, iovcnt,
*l4hdr_off, sizeof(l4hdr_info->hdr.tcp), *l4hdr_off, sizeof(l4hdr_info->hdr.tcp),
&l4hdr_info->hdr.tcp); &l4hdr_info->hdr.tcp)) {
if (*hastcp) { l4hdr_info->proto = ETH_L4_HDR_PROTO_TCP;
*l5hdr_off = *l4hdr_off + *l5hdr_off = *l4hdr_off +
TCP_HEADER_DATA_OFFSET(&l4hdr_info->hdr.tcp); TCP_HEADER_DATA_OFFSET(&l4hdr_info->hdr.tcp);
@ -215,11 +215,13 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
break; break;
case IP_PROTO_UDP: case IP_PROTO_UDP:
*hasudp = _eth_copy_chunk(input_size, if (_eth_copy_chunk(input_size,
iov, iovcnt, iov, iovcnt,
*l4hdr_off, sizeof(l4hdr_info->hdr.udp), *l4hdr_off, sizeof(l4hdr_info->hdr.udp),
&l4hdr_info->hdr.udp); &l4hdr_info->hdr.udp)) {
l4hdr_info->proto = ETH_L4_HDR_PROTO_UDP;
*l5hdr_off = *l4hdr_off + sizeof(l4hdr_info->hdr.udp); *l5hdr_off = *l4hdr_off + sizeof(l4hdr_info->hdr.udp);
}
break; break;
} }
} }