diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-03-22 11:24:55 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-03-22 11:24:55 +0000 |
commit | b184750926812cb78ac0caf4c4b2b13683b5bde3 (patch) | |
tree | 52f3351a4acfd6d7fdd93fdc5bd0b19c9eca7ec3 /net | |
parent | f0f20022a0c744930935fdb7020a8c18347d391a (diff) | |
parent | c7274b5ef43614dd133daec1e2018f71d8744088 (diff) |
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging
# gpg: Signature made Mon 22 Mar 2021 09:35:08 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/eth: Add an assert() and invert if() statement to simplify code
net/eth: Read ip6_ext_hdr_routing buffer before accessing it
net/eth: Check iovec has enough data earlier
net/eth: Check size earlier in _eth_get_rss_ex_dst_addr()
net/eth: Better describe _eth_get_rss_ex_dst_addr's offset argument
net/eth: Simplify _eth_get_rss_ex_dst_addr()
net/eth: Use correct in6_address offset in _eth_get_rss_ex_dst_addr()
net/colo-compare.c: Optimize removal of secondary packet
net/colo-compare.c: Fix memory leak for non-tcp packet
hw/net: virtio-net: Initialize nc->do_not_pad to true
net: Pad short frames to minimum size before sending from SLiRP/TAP
net: Add a 'do_not_pad" to NetClientState
net: eth: Add a helper to pad a short Ethernet frame
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/colo-compare.c | 3 | ||||
-rw-r--r-- | net/eth.c | 61 | ||||
-rw-r--r-- | net/slirp.c | 10 | ||||
-rw-r--r-- | net/tap-win32.c | 10 | ||||
-rw-r--r-- | net/tap.c | 10 |
5 files changed, 71 insertions, 23 deletions
diff --git a/net/colo-compare.c b/net/colo-compare.c index 84db4978ac..9d1ad99941 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -690,7 +690,8 @@ static void colo_compare_packet(CompareState *s, Connection *conn, if (result) { colo_release_primary_pkt(s, pkt); - g_queue_remove(&conn->secondary_list, result->data); + packet_destroy(result->data, NULL); + g_queue_delete_link(&conn->secondary_list, result); } else { /* * If one packet arrive late, the secondary_list or @@ -401,31 +401,29 @@ eth_is_ip6_extension_header_type(uint8_t hdr_type) static bool _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags, - size_t rthdr_offset, + size_t ext_hdr_offset, struct ip6_ext_hdr *ext_hdr, struct in6_address *dst_addr) { - struct ip6_ext_hdr_routing *rthdr = (struct ip6_ext_hdr_routing *) ext_hdr; - - if ((rthdr->rtype == 2) && - (rthdr->len == sizeof(struct in6_address) / 8) && - (rthdr->segleft == 1)) { - - size_t input_size = iov_size(pkt, pkt_frags); - size_t bytes_read; - - if (input_size < rthdr_offset + sizeof(*ext_hdr)) { - return false; - } + struct ip6_ext_hdr_routing rt_hdr; + size_t input_size = iov_size(pkt, pkt_frags); + size_t bytes_read; - bytes_read = iov_to_buf(pkt, pkt_frags, - rthdr_offset + sizeof(*ext_hdr), - dst_addr, sizeof(*dst_addr)); + if (input_size < ext_hdr_offset + sizeof(rt_hdr) + sizeof(*dst_addr)) { + return false; + } - return bytes_read == sizeof(*dst_addr); + bytes_read = iov_to_buf(pkt, pkt_frags, ext_hdr_offset, + &rt_hdr, sizeof(rt_hdr)); + assert(bytes_read == sizeof(rt_hdr)); + if ((rt_hdr.rtype != 2) || (rt_hdr.segleft != 1)) { + return false; } + bytes_read = iov_to_buf(pkt, pkt_frags, ext_hdr_offset + sizeof(rt_hdr), + dst_addr, sizeof(*dst_addr)); + assert(bytes_read == sizeof(*dst_addr)); - return false; + return true; } static bool @@ -528,10 +526,12 @@ bool eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags, } if (curr_ext_hdr_type == IP6_ROUTING) { - info->rss_ex_dst_valid = - _eth_get_rss_ex_dst_addr(pkt, pkt_frags, - ip6hdr_off + info->full_hdr_len, - &ext_hdr, &info->rss_ex_dst); + if (ext_hdr.ip6r_len == sizeof(struct in6_address) / 8) { + info->rss_ex_dst_valid = + _eth_get_rss_ex_dst_addr(pkt, pkt_frags, + ip6hdr_off + info->full_hdr_len, + &ext_hdr, &info->rss_ex_dst); + } } else if (curr_ext_hdr_type == IP6_DESTINATON) { info->rss_ex_src_valid = _eth_get_rss_ex_src_addr(pkt, pkt_frags, @@ -548,3 +548,20 @@ bool eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags, info->l4proto = ext_hdr.ip6r_nxt; return true; } + +bool eth_pad_short_frame(uint8_t *padded_pkt, size_t *padded_buflen, + const void *pkt, size_t pkt_size) +{ + assert(padded_buflen && *padded_buflen >= ETH_ZLEN); + + if (pkt_size >= ETH_ZLEN) { + return false; + } + + /* pad to minimum Ethernet frame length */ + memcpy(padded_pkt, pkt, pkt_size); + memset(&padded_pkt[pkt_size], 0, ETH_ZLEN - pkt_size); + *padded_buflen = ETH_ZLEN; + + return true; +} diff --git a/net/slirp.c b/net/slirp.c index 9454a673d6..a9fdc7a08f 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -31,6 +31,7 @@ #include <pwd.h> #include <sys/wait.h> #endif +#include "net/eth.h" #include "net/net.h" #include "clients.h" #include "hub.h" @@ -115,6 +116,15 @@ static ssize_t net_slirp_send_packet(const void *pkt, size_t pkt_len, void *opaque) { SlirpState *s = opaque; + uint8_t min_pkt[ETH_ZLEN]; + size_t min_pktsz = sizeof(min_pkt); + + if (!s->nc.peer->do_not_pad) { + if (eth_pad_short_frame(min_pkt, &min_pktsz, pkt, pkt_len)) { + pkt = min_pkt; + pkt_len = min_pktsz; + } + } return qemu_send_packet(&s->nc, pkt, pkt_len); } diff --git a/net/tap-win32.c b/net/tap-win32.c index 21e451107b..d7c2a8759c 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -31,6 +31,7 @@ #include "qemu-common.h" #include "clients.h" /* net_init_tap */ +#include "net/eth.h" #include "net/net.h" #include "net/tap.h" /* tap_has_ufo, ... */ #include "qemu/error-report.h" @@ -688,9 +689,18 @@ static void tap_win32_send(void *opaque) uint8_t *buf; int max_size = 4096; int size; + uint8_t min_pkt[ETH_ZLEN]; + size_t min_pktsz = sizeof(min_pkt); size = tap_win32_read(s->handle, &buf, max_size); if (size > 0) { + if (!s->nc.peer->do_not_pad) { + if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) { + buf = min_pkt; + size = min_pktsz; + } + } + qemu_send_packet(&s->nc, buf, size); tap_win32_free_buffer(s->handle, buf); } @@ -32,6 +32,7 @@ #include <sys/socket.h> #include <net/if.h> +#include "net/eth.h" #include "net/net.h" #include "clients.h" #include "monitor/monitor.h" @@ -189,6 +190,8 @@ static void tap_send(void *opaque) while (true) { uint8_t *buf = s->buf; + uint8_t min_pkt[ETH_ZLEN]; + size_t min_pktsz = sizeof(min_pkt); size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); if (size <= 0) { @@ -200,6 +203,13 @@ static void tap_send(void *opaque) size -= s->host_vnet_hdr_len; } + if (!s->nc.peer->do_not_pad) { + if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) { + buf = min_pkt; + size = min_pktsz; + } + } + size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed); if (size == 0) { tap_read_poll(s, false); |