mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
net: checksum: Introduce fine control over checksum type
At present net_checksum_calculate() blindly calculates all types of checksums (IP, TCP, UDP). Some NICs may have a per type setting in their BDs to control what checksum should be offloaded. To support such hardware behavior, introduce a 'csum_flag' parameter to the net_checksum_calculate() API to allow fine control over what type checksum is calculated. Existing users of this API are updated accordingly. Signed-off-by: Bin Meng <bin.meng@windriver.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
d97f11590a
commit
f574633529
10 changed files with 55 additions and 33 deletions
|
@ -514,7 +514,7 @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
|
|||
/* After the last descriptor, send the packet */
|
||||
if (desc.status2 & TX_DESC_STATUS2_LAST_DESC) {
|
||||
if (desc.status2 & TX_DESC_STATUS2_CHECKSUM_MASK) {
|
||||
net_checksum_calculate(packet_buf, packet_bytes);
|
||||
net_checksum_calculate(packet_buf, packet_bytes, CSUM_ALL);
|
||||
}
|
||||
|
||||
qemu_send_packet(nc, packet_buf, packet_bytes);
|
||||
|
|
|
@ -1266,7 +1266,7 @@ static void gem_transmit(CadenceGEMState *s)
|
|||
|
||||
/* Is checksum offload enabled? */
|
||||
if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
|
||||
net_checksum_calculate(s->tx_packet, total_bytes);
|
||||
net_checksum_calculate(s->tx_packet, total_bytes, CSUM_ALL);
|
||||
}
|
||||
|
||||
/* Update MAC statistics */
|
||||
|
|
|
@ -183,13 +183,11 @@ static void process_tx_fcb(eTSEC *etsec)
|
|||
uint8_t *l3_header = etsec->tx_buffer + 8 + l3_header_offset;
|
||||
/* L4 header */
|
||||
uint8_t *l4_header = l3_header + l4_header_offset;
|
||||
int csum = 0;
|
||||
|
||||
/* if packet is IP4 and IP checksum is requested */
|
||||
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
|
||||
/* do IP4 checksum (TODO This function does TCP/UDP checksum
|
||||
* but not sure if it also does IP4 checksum.) */
|
||||
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||
etsec->tx_buffer_len - 8);
|
||||
csum |= CSUM_IP;
|
||||
}
|
||||
/* TODO Check the correct usage of the PHCS field of the FCB in case the NPH
|
||||
* flag is on */
|
||||
|
@ -201,9 +199,7 @@ static void process_tx_fcb(eTSEC *etsec)
|
|||
/* if checksum is requested */
|
||||
if (flags & FCB_TX_CTU) {
|
||||
/* do UDP checksum */
|
||||
|
||||
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||
etsec->tx_buffer_len - 8);
|
||||
csum |= CSUM_UDP;
|
||||
} else {
|
||||
/* set checksum field to 0 */
|
||||
l4_header[6] = 0;
|
||||
|
@ -211,10 +207,14 @@ static void process_tx_fcb(eTSEC *etsec)
|
|||
}
|
||||
} else if (flags & FCB_TX_CTU) { /* if TCP and checksum is requested */
|
||||
/* do TCP checksum */
|
||||
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||
etsec->tx_buffer_len - 8);
|
||||
csum |= CSUM_TCP;
|
||||
}
|
||||
}
|
||||
|
||||
if (csum) {
|
||||
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||
etsec->tx_buffer_len - 8, csum);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_tx_bd(eTSEC *etsec,
|
||||
|
|
|
@ -564,6 +564,7 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
|
|||
ptr += len;
|
||||
frame_size += len;
|
||||
if (bd.des0 & FTGMAC100_TXDES0_LTS) {
|
||||
int csum = 0;
|
||||
|
||||
/* Check for VLAN */
|
||||
if (flags & FTGMAC100_TXDES1_INS_VLANTAG &&
|
||||
|
@ -573,8 +574,18 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
|
|||
}
|
||||
|
||||
if (flags & FTGMAC100_TXDES1_IP_CHKSUM) {
|
||||
net_checksum_calculate(s->frame, frame_size);
|
||||
csum |= CSUM_IP;
|
||||
}
|
||||
if (flags & FTGMAC100_TXDES1_TCP_CHKSUM) {
|
||||
csum |= CSUM_TCP;
|
||||
}
|
||||
if (flags & FTGMAC100_TXDES1_UDP_CHKSUM) {
|
||||
csum |= CSUM_UDP;
|
||||
}
|
||||
if (csum) {
|
||||
net_checksum_calculate(s->frame, frame_size, csum);
|
||||
}
|
||||
|
||||
/* Last buffer in frame. */
|
||||
qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
|
||||
ptr = s->frame;
|
||||
|
|
|
@ -561,22 +561,18 @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
|
|||
ptr += len;
|
||||
frame_size += len;
|
||||
if (bd.flags & ENET_BD_L) {
|
||||
int csum = 0;
|
||||
|
||||
if (bd.option & ENET_BD_PINS) {
|
||||
struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
|
||||
if (IP_HEADER_VERSION(ip_hd) == 4) {
|
||||
net_checksum_calculate(s->frame, frame_size);
|
||||
}
|
||||
csum |= (CSUM_TCP | CSUM_UDP);
|
||||
}
|
||||
if (bd.option & ENET_BD_IINS) {
|
||||
struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
|
||||
/* We compute checksum only for IPv4 frames */
|
||||
if (IP_HEADER_VERSION(ip_hd) == 4) {
|
||||
uint16_t csum;
|
||||
ip_hd->ip_sum = 0;
|
||||
csum = net_raw_checksum((uint8_t *)ip_hd, sizeof(*ip_hd));
|
||||
ip_hd->ip_sum = cpu_to_be16(csum);
|
||||
}
|
||||
csum |= CSUM_IP;
|
||||
}
|
||||
if (csum) {
|
||||
net_checksum_calculate(s->frame, frame_size, csum);
|
||||
}
|
||||
|
||||
/* Last buffer in frame. */
|
||||
|
||||
qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
|
||||
|
|
|
@ -1464,7 +1464,7 @@ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
|
|||
(buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
|
||||
(buf[23] == 17) && /* ip.protocol == UDP */
|
||||
(buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
|
||||
net_checksum_calculate(buf, size);
|
||||
net_checksum_calculate(buf, size, CSUM_UDP);
|
||||
hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ static void net_tx_packets(struct XenNetDev *netdev)
|
|||
tmpbuf = g_malloc(XC_PAGE_SIZE);
|
||||
}
|
||||
memcpy(tmpbuf, page + txreq.offset, txreq.size);
|
||||
net_checksum_calculate(tmpbuf, txreq.size);
|
||||
net_checksum_calculate(tmpbuf, txreq.size, CSUM_ALL);
|
||||
qemu_send_packet(qemu_get_queue(netdev->nic), tmpbuf,
|
||||
txreq.size);
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue