mirror of
https://github.com/qemu/qemu.git
synced 2024-12-16 16:53:28 +08:00
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJgDonvAAoJEO8Ells5jWIR++8IAJBTpKDSwdwG1ySn5m6tHZHM GdFD2Ao8R8VsonJzw9i/1Gfn9T0icndRU6VC+nJEdvSLXUDoAQdmMmLCk4oml41g gzPzsc6bFKwKB4DG3RyixbEoUsMl7jQRoVYOgWy1Ezx2daAGG9PjuDMdBU4tNCFv IxkVpOz3RClhzaMz3O0OkLKljooRcvhePB+8FuZCOnBzxDJ9RU1KXDpv5kYMswFL 9f+D2UK474IcaAQCzKXuHrs/k3utMEY32udjqQdgb9y/8jZYJuEZSB7pyXozuSAO QSl62FxbAwfx85hVbMqnIa2Yd629SiVVHsotavAZz60fcBaQgrNbBTWDNlCrWJo= =XN54 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging # gpg: Signature made Mon 25 Jan 2021 09:05:51 GMT # gpg: using RSA key EF04965B398D6211 # gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" [marginal] # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211 * remotes/jasowang/tags/net-pull-request: net: checksum: Introduce fine control over checksum type net: checksum: Add IP header checksum calculation net: checksum: Skip fragmented IP packets net: Fix handling of id in netdev_add and netdev_del Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
31ee895047
@ -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 {
|
||||
|
@ -21,11 +21,16 @@
|
||||
#include "qemu/bswap.h"
|
||||
struct iovec;
|
||||
|
||||
#define CSUM_IP 0x01
|
||||
#define CSUM_TCP 0x02
|
||||
#define CSUM_UDP 0x04
|
||||
#define CSUM_ALL (CSUM_IP | CSUM_TCP | CSUM_UDP)
|
||||
|
||||
uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq);
|
||||
uint16_t net_checksum_finish(uint32_t sum);
|
||||
uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
|
||||
uint8_t *addrs, uint8_t *buf);
|
||||
void net_checksum_calculate(uint8_t *data, int length);
|
||||
void net_checksum_calculate(uint8_t *data, int length, int csum_flag);
|
||||
|
||||
static inline uint32_t
|
||||
net_checksum_add(int len, uint8_t *buf)
|
||||
|
@ -57,10 +57,11 @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
|
||||
return net_checksum_finish(sum);
|
||||
}
|
||||
|
||||
void net_checksum_calculate(uint8_t *data, int length)
|
||||
void net_checksum_calculate(uint8_t *data, int length, int csum_flag)
|
||||
{
|
||||
int mac_hdr_len, ip_len;
|
||||
struct ip_header *ip;
|
||||
uint16_t csum;
|
||||
|
||||
/*
|
||||
* Note: We cannot assume "data" is aligned, so the all code uses
|
||||
@ -106,6 +107,17 @@ void net_checksum_calculate(uint8_t *data, int length)
|
||||
return; /* not IPv4 */
|
||||
}
|
||||
|
||||
/* Calculate IP checksum */
|
||||
if (csum_flag & CSUM_IP) {
|
||||
stw_he_p(&ip->ip_sum, 0);
|
||||
csum = net_raw_checksum((uint8_t *)ip, IP_HDR_GET_LEN(ip));
|
||||
stw_be_p(&ip->ip_sum, csum);
|
||||
}
|
||||
|
||||
if (IP4_IS_FRAGMENT(ip)) {
|
||||
return; /* a fragmented IP packet */
|
||||
}
|
||||
|
||||
ip_len = lduw_be_p(&ip->ip_len);
|
||||
|
||||
/* Last, check that we have enough data for the all IP frame */
|
||||
@ -118,7 +130,10 @@ void net_checksum_calculate(uint8_t *data, int length)
|
||||
switch (ip->ip_p) {
|
||||
case IP_PROTO_TCP:
|
||||
{
|
||||
uint16_t csum;
|
||||
if (!(csum_flag & CSUM_TCP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tcp_header *tcp = (tcp_header *)(ip + 1);
|
||||
|
||||
if (ip_len < sizeof(tcp_header)) {
|
||||
@ -139,7 +154,10 @@ void net_checksum_calculate(uint8_t *data, int length)
|
||||
}
|
||||
case IP_PROTO_UDP:
|
||||
{
|
||||
uint16_t csum;
|
||||
if (!(csum_flag & CSUM_UDP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
udp_header *udp = (udp_header *)(ip + 1);
|
||||
|
||||
if (ip_len < sizeof(udp_header)) {
|
||||
|
@ -114,7 +114,7 @@ static int handle_primary_tcp_pkt(RewriterState *rf,
|
||||
tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset);
|
||||
|
||||
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
|
||||
pkt->size - pkt->vnet_hdr_len);
|
||||
pkt->size - pkt->vnet_hdr_len, CSUM_TCP);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -216,7 +216,7 @@ static int handle_secondary_tcp_pkt(RewriterState *rf,
|
||||
tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset);
|
||||
|
||||
net_checksum_calculate((uint8_t *)pkt->data + pkt->vnet_hdr_len,
|
||||
pkt->size - pkt->vnet_hdr_len);
|
||||
pkt->size - pkt->vnet_hdr_len, CSUM_TCP);
|
||||
}
|
||||
}
|
||||
|
||||
|
20
net/net.c
20
net/net.c
@ -983,6 +983,7 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
|
||||
static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
|
||||
{
|
||||
NetClientState *peer = NULL;
|
||||
NetClientState *nc;
|
||||
|
||||
if (is_netdev) {
|
||||
if (netdev->type == NET_CLIENT_DRIVER_NIC ||
|
||||
@ -1010,6 +1011,12 @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
nc = qemu_find_netdev(netdev->id);
|
||||
if (nc) {
|
||||
error_setg(errp, "Duplicate ID '%s'", netdev->id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) {
|
||||
/* FIXME drop when all init functions store an Error */
|
||||
if (errp && !*errp) {
|
||||
@ -1020,8 +1027,6 @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
|
||||
}
|
||||
|
||||
if (is_netdev) {
|
||||
NetClientState *nc;
|
||||
|
||||
nc = qemu_find_netdev(netdev->id);
|
||||
assert(nc);
|
||||
nc->is_netdev = true;
|
||||
@ -1135,6 +1140,7 @@ void qmp_netdev_add(Netdev *netdev, Error **errp)
|
||||
void qmp_netdev_del(const char *id, Error **errp)
|
||||
{
|
||||
NetClientState *nc;
|
||||
QemuOpts *opts;
|
||||
|
||||
nc = qemu_find_netdev(id);
|
||||
if (!nc) {
|
||||
@ -1149,6 +1155,16 @@ void qmp_netdev_del(const char *id, Error **errp)
|
||||
}
|
||||
|
||||
qemu_del_net_client(nc);
|
||||
|
||||
/*
|
||||
* Wart: we need to delete the QemuOpts associated with netdevs
|
||||
* created via CLI or HMP, to avoid bogus "Duplicate ID" errors in
|
||||
* HMP netdev_add.
|
||||
*/
|
||||
opts = qemu_opts_find(qemu_find_opts("netdev"), id);
|
||||
if (opts) {
|
||||
qemu_opts_del(opts);
|
||||
}
|
||||
}
|
||||
|
||||
static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
|
||||
|
Loading…
Reference in New Issue
Block a user