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:
parent
5fb7d14995
commit
65f474bbae
hw/net
include/net
net
@ -497,18 +497,20 @@ typedef struct E1000E_RSSInfo_st {
|
||||
static uint32_t
|
||||
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));
|
||||
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp);
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
@ -529,7 +531,7 @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt)
|
||||
* backends like these.
|
||||
*/
|
||||
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->rss_ex_dst_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 ||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1124,7 +1127,7 @@ static void
|
||||
e1000e_verify_csum_in_sw(E1000ECore *core,
|
||||
struct NetRxPkt *pkt,
|
||||
uint32_t *status_flags,
|
||||
bool hastcp, bool hasudp)
|
||||
EthL4HdrProto l4hdr_proto)
|
||||
{
|
||||
bool csum_valid;
|
||||
uint32_t csum_error;
|
||||
@ -1151,14 +1154,10 @@ e1000e_verify_csum_in_sw(E1000ECore *core,
|
||||
}
|
||||
|
||||
csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_TCPE;
|
||||
*status_flags |= E1000_RXD_STAT_TCPCS | csum_error;
|
||||
|
||||
if (hastcp) {
|
||||
*status_flags |= E1000_RXD_STAT_TCPCS |
|
||||
csum_error;
|
||||
} else if (hasudp) {
|
||||
*status_flags |= E1000_RXD_STAT_TCPCS |
|
||||
E1000_RXD_STAT_UDPCS |
|
||||
csum_error;
|
||||
if (l4hdr_proto == ETH_L4_HDR_PROTO_UDP) {
|
||||
*status_flags |= E1000_RXD_STAT_UDPCS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1187,7 +1186,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
|
||||
uint16_t *vlan_tag)
|
||||
{
|
||||
struct virtio_net_hdr *vhdr;
|
||||
bool hasip4, hasip6, hastcp, hasudp;
|
||||
bool hasip4, hasip6;
|
||||
EthL4HdrProto l4hdr_proto;
|
||||
uint32_t pkt_type;
|
||||
|
||||
*status_flags = E1000_RXD_STAT_DD;
|
||||
@ -1199,8 +1199,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
|
||||
|
||||
*status_flags |= E1000_RXD_STAT_EOP;
|
||||
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp);
|
||||
trace_e1000e_rx_metadata_protocols(hasip4, hasip6, hasudp, hastcp);
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
|
||||
trace_e1000e_rx_metadata_protocols(hasip4, hasip6, l4hdr_proto);
|
||||
|
||||
/* VLAN state */
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
trace_e1000e_rx_metadata_ack();
|
||||
}
|
||||
@ -1230,7 +1230,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
|
||||
if (hasip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_DIS)) {
|
||||
trace_e1000e_rx_metadata_ipv6_filtering_disabled();
|
||||
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;
|
||||
} else if (hasip4 || hasip6) {
|
||||
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) &&
|
||||
!(vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1263,10 +1264,17 @@ e1000e_build_rx_metadata(E1000ECore *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;
|
||||
} else if (hasudp) {
|
||||
break;
|
||||
|
||||
case ETH_L4_HDR_PROTO_UDP:
|
||||
*status_flags |= E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
trace_e1000e_rx_metadata_l4_cso_disabled();
|
||||
@ -1509,14 +1517,15 @@ e1000e_rx_descr_threshold_hit(E1000ECore *core, const E1000E_RingInfo *rxi)
|
||||
static bool
|
||||
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;
|
||||
|
||||
if (!e1000e_rx_use_ps_descriptor(core)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp);
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
|
||||
|
||||
if (hasip4) {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
*hdr_len = net_rx_pkt_get_l4_hdr_offset(pkt);
|
||||
|
@ -35,8 +35,6 @@ struct NetRxPkt {
|
||||
/* Analysis results */
|
||||
bool hasip4;
|
||||
bool hasip6;
|
||||
bool hasudp;
|
||||
bool hastcp;
|
||||
|
||||
size_t l3hdr_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,
|
||||
&pkt->hasudp, &pkt->hastcp,
|
||||
&pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off,
|
||||
&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);
|
||||
}
|
||||
|
||||
@ -200,21 +197,19 @@ void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data,
|
||||
assert(pkt);
|
||||
|
||||
eth_get_protocols(&iov, 1, &pkt->hasip4, &pkt->hasip6,
|
||||
&pkt->hasudp, &pkt->hastcp,
|
||||
&pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off,
|
||||
&pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info);
|
||||
}
|
||||
|
||||
void net_rx_pkt_get_protocols(struct NetRxPkt *pkt,
|
||||
bool *hasip4, bool *hasip6,
|
||||
bool *hasudp, bool *hastcp)
|
||||
EthL4HdrProto *l4hdr_proto)
|
||||
{
|
||||
assert(pkt);
|
||||
|
||||
*hasip4 = pkt->hasip4;
|
||||
*hasip6 = pkt->hasip6;
|
||||
*hasudp = pkt->hasudp;
|
||||
*hastcp = pkt->hastcp;
|
||||
*l4hdr_proto = pkt->l4hdr_info.proto;
|
||||
}
|
||||
|
||||
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;
|
||||
case NetPktRssIpV4Tcp:
|
||||
assert(pkt->hasip4);
|
||||
assert(pkt->hastcp);
|
||||
assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP);
|
||||
trace_net_rx_pkt_rss_ip4_tcp();
|
||||
_net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length);
|
||||
_net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length);
|
||||
break;
|
||||
case NetPktRssIpV6Tcp:
|
||||
assert(pkt->hasip6);
|
||||
assert(pkt->hastcp);
|
||||
assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP);
|
||||
trace_net_rx_pkt_rss_ip6_tcp();
|
||||
_net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &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;
|
||||
case NetPktRssIpV6TcpEx:
|
||||
assert(pkt->hasip6);
|
||||
assert(pkt->hastcp);
|
||||
assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_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_tcp(&rss_input[0], pkt, &rss_length);
|
||||
break;
|
||||
case NetPktRssIpV4Udp:
|
||||
assert(pkt->hasip4);
|
||||
assert(pkt->hasudp);
|
||||
assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP);
|
||||
trace_net_rx_pkt_rss_ip4_udp();
|
||||
_net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length);
|
||||
_net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length);
|
||||
break;
|
||||
case NetPktRssIpV6Udp:
|
||||
assert(pkt->hasip6);
|
||||
assert(pkt->hasudp);
|
||||
assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP);
|
||||
trace_net_rx_pkt_rss_ip6_udp();
|
||||
_net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length);
|
||||
_net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length);
|
||||
break;
|
||||
case NetPktRssIpV6UdpEx:
|
||||
assert(pkt->hasip6);
|
||||
assert(pkt->hasudp);
|
||||
assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_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_udp(&rss_input[0], pkt, &rss_length);
|
||||
@ -415,7 +410,7 @@ bool net_rx_pkt_is_tcp_ack(struct NetRxPkt *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;
|
||||
}
|
||||
|
||||
@ -426,7 +421,7 @@ bool net_rx_pkt_has_tcp_data(struct NetRxPkt *pkt)
|
||||
{
|
||||
assert(pkt);
|
||||
|
||||
if (pkt->hastcp) {
|
||||
if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP) {
|
||||
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();
|
||||
|
||||
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);
|
||||
trace_net_rx_pkt_l4_csum_calc_ip4_udp();
|
||||
} else {
|
||||
@ -537,7 +532,7 @@ _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt)
|
||||
csl, &cso);
|
||||
trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl);
|
||||
} 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);
|
||||
trace_net_rx_pkt_l4_csum_calc_ip6_udp();
|
||||
} 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();
|
||||
|
||||
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();
|
||||
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();
|
||||
return false;
|
||||
}
|
||||
@ -602,17 +599,22 @@ bool net_rx_pkt_fix_l4_csum(struct NetRxPkt *pkt)
|
||||
|
||||
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);
|
||||
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) {
|
||||
trace_net_rx_pkt_l4_csum_fix_udp_with_no_checksum();
|
||||
return false;
|
||||
}
|
||||
l4_cso = offsetof(struct udp_header, uh_sum);
|
||||
trace_net_rx_pkt_l4_csum_fix_udp(l4_cso);
|
||||
} else {
|
||||
break;
|
||||
|
||||
default:
|
||||
trace_net_rx_pkt_l4_csum_fix_not_xxp();
|
||||
return false;
|
||||
}
|
||||
|
@ -68,13 +68,12 @@ void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data,
|
||||
* @pkt: packet
|
||||
* @hasip4: whether the packet has an IPv4 header
|
||||
* @hasip6: whether the packet has an IPv6 header
|
||||
* @hasudp: whether the packet has a UDP header
|
||||
* @hastcp: whether the packet has a TCP header
|
||||
* @l4hdr_proto: protocol of L4 header
|
||||
*
|
||||
*/
|
||||
void net_rx_pkt_get_protocols(struct NetRxPkt *pkt,
|
||||
bool *hasip4, bool *hasip6,
|
||||
bool *hasudp, bool *hastcp);
|
||||
EthL4HdrProto *l4hdr_proto);
|
||||
|
||||
/**
|
||||
* fetches L3 header offset
|
||||
|
@ -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"
|
||||
|
||||
# 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_not_xxp(void) "Not a TCP/UDP packet"
|
||||
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_disabled(void) "RSS is disabled"
|
||||
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(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_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"
|
||||
|
@ -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,
|
||||
bool hasip6,
|
||||
bool hasudp,
|
||||
bool hastcp,
|
||||
EthL4HdrProto l4hdr_proto,
|
||||
uint32_t types)
|
||||
{
|
||||
if (hasip4) {
|
||||
if (hastcp && (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) {
|
||||
return NetPktRssIpV4Tcp;
|
||||
}
|
||||
if (hasudp && (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) {
|
||||
return NetPktRssIpV4Udp;
|
||||
switch (l4hdr_proto) {
|
||||
case ETH_L4_HDR_PROTO_TCP:
|
||||
if (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4) {
|
||||
return NetPktRssIpV4Tcp;
|
||||
}
|
||||
break;
|
||||
|
||||
case ETH_L4_HDR_PROTO_UDP:
|
||||
if (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4) {
|
||||
return NetPktRssIpV4Udp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) {
|
||||
return NetPktRssIpV4;
|
||||
}
|
||||
} else if (hasip6) {
|
||||
uint32_t mask = VIRTIO_NET_RSS_HASH_TYPE_TCP_EX |
|
||||
VIRTIO_NET_RSS_HASH_TYPE_TCPv6;
|
||||
switch (l4hdr_proto) {
|
||||
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)) {
|
||||
return (types & VIRTIO_NET_RSS_HASH_TYPE_TCP_EX) ?
|
||||
NetPktRssIpV6TcpEx : NetPktRssIpV6Tcp;
|
||||
case ETH_L4_HDR_PROTO_UDP:
|
||||
if (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) {
|
||||
return NetPktRssIpV6UdpEx;
|
||||
}
|
||||
if (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv6) {
|
||||
return NetPktRssIpV6Udp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mask = VIRTIO_NET_RSS_HASH_TYPE_UDP_EX | VIRTIO_NET_RSS_HASH_TYPE_UDPv6;
|
||||
if (hasudp && (types & mask)) {
|
||||
return (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) ?
|
||||
NetPktRssIpV6UdpEx : NetPktRssIpV6Udp;
|
||||
|
||||
if (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) {
|
||||
return NetPktRssIpV6Ex;
|
||||
}
|
||||
mask = VIRTIO_NET_RSS_HASH_TYPE_IP_EX | VIRTIO_NET_RSS_HASH_TYPE_IPv6;
|
||||
if (types & mask) {
|
||||
return (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) ?
|
||||
NetPktRssIpV6Ex : NetPktRssIpV6;
|
||||
if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv6) {
|
||||
return NetPktRssIpV6;
|
||||
}
|
||||
}
|
||||
return 0xff;
|
||||
@ -1800,7 +1822,8 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
|
||||
struct NetRxPkt *pkt = n->rx_pkt;
|
||||
uint8_t net_hash_type;
|
||||
uint32_t hash;
|
||||
bool hasip4, hasip6, hasudp, hastcp;
|
||||
bool hasip4, hasip6;
|
||||
EthL4HdrProto l4hdr_proto;
|
||||
static const uint8_t reports[NetPktRssIpV6UdpEx + 1] = {
|
||||
VIRTIO_NET_HASH_REPORT_IPv4,
|
||||
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,
|
||||
size - n->host_hdr_len);
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp);
|
||||
net_hash_type = virtio_net_get_hash_type(hasip4, hasip6, hasudp, hastcp,
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
|
||||
net_hash_type = virtio_net_get_hash_type(hasip4, hasip6, l4hdr_proto,
|
||||
n->rss_data.hash_types);
|
||||
if (net_hash_type > NetPktRssIpV6UdpEx) {
|
||||
if (n->rss_data.populate_hash) {
|
||||
|
@ -847,7 +847,8 @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
|
||||
size_t pkt_len)
|
||||
{
|
||||
struct virtio_net_hdr *vhdr;
|
||||
bool hasip4, hasip6, hastcp, hasudp;
|
||||
bool hasip4, hasip6;
|
||||
EthL4HdrProto l4hdr_proto;
|
||||
uint8_t *data;
|
||||
int len;
|
||||
|
||||
@ -856,8 +857,10 @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
|
||||
return;
|
||||
}
|
||||
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp);
|
||||
if (!(hasip4 || hasip6) || !(hastcp || hasudp)) {
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
|
||||
if (!(hasip4 || hasip6) ||
|
||||
(l4hdr_proto != ETH_L4_HDR_PROTO_TCP &&
|
||||
l4hdr_proto != ETH_L4_HDR_PROTO_UDP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -885,7 +888,8 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
|
||||
struct Vmxnet3_RxCompDesc *rxcd)
|
||||
{
|
||||
int csum_ok, is_gso;
|
||||
bool hasip4, hasip6, hastcp, hasudp;
|
||||
bool hasip4, hasip6;
|
||||
EthL4HdrProto l4hdr_proto;
|
||||
struct virtio_net_hdr *vhdr;
|
||||
uint8_t offload_type;
|
||||
|
||||
@ -911,16 +915,18 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
|
||||
goto nocsum;
|
||||
}
|
||||
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &hasudp, &hastcp);
|
||||
if ((!hastcp && !hasudp) || (!hasip4 && !hasip6)) {
|
||||
net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
|
||||
if ((l4hdr_proto != ETH_L4_HDR_PROTO_TCP &&
|
||||
l4hdr_proto != ETH_L4_HDR_PROTO_UDP) ||
|
||||
(!hasip4 && !hasip6)) {
|
||||
goto nocsum;
|
||||
}
|
||||
|
||||
rxcd->cnc = 0;
|
||||
rxcd->v4 = hasip4 ? 1 : 0;
|
||||
rxcd->v6 = hasip6 ? 1 : 0;
|
||||
rxcd->tcp = hastcp ? 1 : 0;
|
||||
rxcd->udp = hasudp ? 1 : 0;
|
||||
rxcd->tcp = l4hdr_proto == ETH_L4_HDR_PROTO_TCP;
|
||||
rxcd->udp = l4hdr_proto == ETH_L4_HDR_PROTO_UDP;
|
||||
rxcd->fcs = rxcd->tuc = rxcd->ipc = 1;
|
||||
return;
|
||||
|
||||
|
@ -381,18 +381,24 @@ typedef struct eth_ip4_hdr_info_st {
|
||||
bool fragment;
|
||||
} 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 {
|
||||
union {
|
||||
struct tcp_header tcp;
|
||||
struct udp_header udp;
|
||||
} hdr;
|
||||
|
||||
EthL4HdrProto proto;
|
||||
bool has_tcp_data;
|
||||
} eth_l4_hdr_info;
|
||||
|
||||
void eth_get_protocols(const struct iovec *iov, int iovcnt,
|
||||
bool *hasip4, bool *hasip6,
|
||||
bool *hasudp, bool *hastcp,
|
||||
size_t *l3hdr_off,
|
||||
size_t *l4hdr_off,
|
||||
size_t *l5hdr_off,
|
||||
|
26
net/eth.c
26
net/eth.c
@ -138,7 +138,6 @@ _eth_tcp_has_data(bool is_ip4,
|
||||
|
||||
void eth_get_protocols(const struct iovec *iov, int iovcnt,
|
||||
bool *hasip4, bool *hasip6,
|
||||
bool *hasudp, bool *hastcp,
|
||||
size_t *l3hdr_off,
|
||||
size_t *l4hdr_off,
|
||||
size_t *l5hdr_off,
|
||||
@ -153,7 +152,8 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
|
||||
size_t copied;
|
||||
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);
|
||||
|
||||
@ -197,11 +197,11 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
|
||||
|
||||
switch (ip_p) {
|
||||
case IP_PROTO_TCP:
|
||||
*hastcp = _eth_copy_chunk(input_size,
|
||||
iov, iovcnt,
|
||||
*l4hdr_off, sizeof(l4hdr_info->hdr.tcp),
|
||||
&l4hdr_info->hdr.tcp);
|
||||
if (*hastcp) {
|
||||
if (_eth_copy_chunk(input_size,
|
||||
iov, iovcnt,
|
||||
*l4hdr_off, sizeof(l4hdr_info->hdr.tcp),
|
||||
&l4hdr_info->hdr.tcp)) {
|
||||
l4hdr_info->proto = ETH_L4_HDR_PROTO_TCP;
|
||||
*l5hdr_off = *l4hdr_off +
|
||||
TCP_HEADER_DATA_OFFSET(&l4hdr_info->hdr.tcp);
|
||||
|
||||
@ -215,11 +215,13 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
|
||||
break;
|
||||
|
||||
case IP_PROTO_UDP:
|
||||
*hasudp = _eth_copy_chunk(input_size,
|
||||
iov, iovcnt,
|
||||
*l4hdr_off, sizeof(l4hdr_info->hdr.udp),
|
||||
&l4hdr_info->hdr.udp);
|
||||
*l5hdr_off = *l4hdr_off + sizeof(l4hdr_info->hdr.udp);
|
||||
if (_eth_copy_chunk(input_size,
|
||||
iov, iovcnt,
|
||||
*l4hdr_off, sizeof(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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user