diff options
| author | Peter Maydell | 2021-01-25 16:56:13 +0100 |
|---|---|---|
| committer | Peter Maydell | 2021-01-25 16:56:13 +0100 |
| commit | 31ee895047bdcf7387e3570cbd2a473c6f744b08 (patch) | |
| tree | bc28163f54b4f2729bcb8a87e4d37a4f7a94fd99 /net | |
| parent | Merge remote-tracking branch 'remotes/gkurz-gitlab/tags/9p-next-pull-request'... (diff) | |
| parent | net: checksum: Introduce fine control over checksum type (diff) | |
| download | qemu-31ee895047bdcf7387e3570cbd2a473c6f744b08.tar.gz qemu-31ee895047bdcf7387e3570cbd2a473c6f744b08.tar.xz qemu-31ee895047bdcf7387e3570cbd2a473c6f744b08.zip | |
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>
Diffstat (limited to 'net')
| -rw-r--r-- | net/checksum.c | 24 | ||||
| -rw-r--r-- | net/filter-rewriter.c | 4 | ||||
| -rw-r--r-- | net/net.c | 20 |
3 files changed, 41 insertions, 7 deletions
diff --git a/net/checksum.c b/net/checksum.c index aaa4000238..70f4eaeb3a 100644 --- a/net/checksum.c +++ b/net/checksum.c @@ -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)) { diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c index fc0e64c45b..10fe3939b1 100644 --- a/net/filter-rewriter.c +++ b/net/filter-rewriter.c @@ -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); } } @@ -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) |
