-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1
 
 iQEcBAABAgAGBQJaPGoNAAoJEO8Ells5jWIR7lMH/iQrtE4qSCKbdIMM6Qf4ccpS
 qMV15tZmT2cVpGXWSrDl6xhQ+7BXmQX6buJqyuf97Q1niVJuqnilsmQrYkkh2mR4
 0NIunu3t24v0eeKcmIWnT/L7+9/S0h97X5TFQCZYST5W/ZsUYCYN2EaIGQWUN8y+
 dSrpJvoxDvFrMv66W5H/Kskm84LL2sqQg76cxawLy7nYF/M6SiRIoovuDSB58ceq
 iUZd1Jxk8IWPFktiAJ/zc3VKPfVuAomJhNMCNWNFEdDHEBmFe+TxqtsnnCMM22mA
 fZQCu3eOObW8J+1V/y+5S1g7cpHqUS4tpivQzGEYO6/OWpMPIOYseHIDIYM87G4=
 =BYlK
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging

# gpg: Signature made Fri 22 Dec 2017 02:12:29 GMT
# gpg:                using RSA key 0xEF04965B398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>"
# 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:
  qemu-doc: Update the deprecation information of -tftp, -bootp, -redir and -smb
  qemu-doc: The "-net nic" option can be used with "netdev=...", too
  net: Remove the legacy "-net channel" parameter
  net: remove unused compute_mcast_idx() function
  rtl8139: use inline net_crc32() and bitshift instead of compute_mcast_idx()
  ne2000: use inline net_crc32() and bitshift instead of compute_mcast_idx()
  ftgmac100: use inline net_crc32() and bitshift instead of compute_mcast_idx()
  lan9118: use inline net_crc32() and bitshift instead of compute_mcast_idx()
  opencores_eth: use inline net_crc32() and bitshift instead of compute_mcast_idx()
  eepro100: use inline net_crc32() and bitshift instead of compute_mcast_idx()
  sungem: fix multicast filter CRC calculation
  sunhme: switch sunhme over to use net_crc32_le()
  eepro100: switch eepro100 e100_compute_mcast_idx() over to use net_crc32()
  pcnet: switch pcnet over to use net_crc32_le()
  net: introduce net_crc32_le() function
  net: move CRC32 calculation from compute_mcast_idx() into its own net_crc32() function
  e1000: Separate TSO and non-TSO contexts, fixing UDP TX corruption
  e1000, e1000e: Move per-packet TX offload flags out of context state

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-01-08 09:15:42 +00:00
commit 8671016261
20 changed files with 144 additions and 203 deletions

View file

@ -98,7 +98,10 @@ typedef struct E1000State_st {
unsigned char data[0x10000];
uint16_t size;
unsigned char vlan_needed;
unsigned char sum_needed;
bool cptse;
e1000x_txd_props props;
e1000x_txd_props tso_props;
uint16_t tso_frames;
} tx;
@ -539,35 +542,37 @@ xmit_seg(E1000State *s)
uint16_t len;
unsigned int frames = s->tx.tso_frames, css, sofar;
struct e1000_tx *tp = &s->tx;
struct e1000x_txd_props *props = tp->cptse ? &tp->tso_props : &tp->props;
if (tp->props.tse && tp->props.cptse) {
css = tp->props.ipcss;
if (tp->cptse) {
css = props->ipcss;
DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
frames, tp->size, css);
if (tp->props.ip) { /* IPv4 */
if (props->ip) { /* IPv4 */
stw_be_p(tp->data+css+2, tp->size - css);
stw_be_p(tp->data+css+4,
lduw_be_p(tp->data + css + 4) + frames);
} else { /* IPv6 */
stw_be_p(tp->data+css+4, tp->size - css);
}
css = tp->props.tucss;
css = props->tucss;
len = tp->size - css;
DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->props.tcp, css, len);
if (tp->props.tcp) {
sofar = frames * tp->props.mss;
DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", props->tcp, css, len);
if (props->tcp) {
sofar = frames * props->mss;
stl_be_p(tp->data+css+4, ldl_be_p(tp->data+css+4)+sofar); /* seq */
if (tp->props.paylen - sofar > tp->props.mss) {
if (props->paylen - sofar > props->mss) {
tp->data[css + 13] &= ~9; /* PSH, FIN */
} else if (frames) {
e1000x_inc_reg_if_not_full(s->mac_reg, TSCTC);
}
} else /* UDP */
} else { /* UDP */
stw_be_p(tp->data+css+4, len);
if (tp->props.sum_needed & E1000_TXD_POPTS_TXSM) {
}
if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
unsigned int phsum;
// add pseudo-header length before checksum calculation
void *sp = tp->data + tp->props.tucso;
void *sp = tp->data + props->tucso;
phsum = lduw_be_p(sp) + len;
phsum = (phsum >> 16) + (phsum & 0xffff);
@ -576,13 +581,11 @@ xmit_seg(E1000State *s)
tp->tso_frames++;
}
if (tp->props.sum_needed & E1000_TXD_POPTS_TXSM) {
putsum(tp->data, tp->size, tp->props.tucso,
tp->props.tucss, tp->props.tucse);
if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
putsum(tp->data, tp->size, props->tucso, props->tucss, props->tucse);
}
if (tp->props.sum_needed & E1000_TXD_POPTS_IXSM) {
putsum(tp->data, tp->size, tp->props.ipcso,
tp->props.ipcss, tp->props.ipcse);
if (tp->sum_needed & E1000_TXD_POPTS_IXSM) {
putsum(tp->data, tp->size, props->ipcso, props->ipcss, props->ipcse);
}
if (tp->vlan_needed) {
memmove(tp->vlan, tp->data, 4);
@ -614,27 +617,27 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE);
if (dtype == E1000_TXD_CMD_DEXT) { /* context descriptor */
e1000x_read_tx_ctx_descr(xp, &tp->props);
tp->tso_frames = 0;
if (tp->props.tucso == 0) { /* this is probably wrong */
DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");
tp->props.tucso = tp->props.tucss + (tp->props.tcp ? 16 : 6);
if (le32_to_cpu(xp->cmd_and_length) & E1000_TXD_CMD_TSE) {
e1000x_read_tx_ctx_descr(xp, &tp->tso_props);
tp->tso_frames = 0;
} else {
e1000x_read_tx_ctx_descr(xp, &tp->props);
}
return;
} else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
// data descriptor
if (tp->size == 0) {
tp->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8;
tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
}
tp->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
tp->cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
} else {
// legacy descriptor
tp->props.cptse = 0;
tp->cptse = 0;
}
if (e1000x_vlan_enabled(s->mac_reg) &&
e1000x_is_vlan_txd(txd_lower) &&
(tp->props.cptse || txd_lower & E1000_TXD_CMD_EOP)) {
(tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
tp->vlan_needed = 1;
stw_be_p(tp->vlan_header,
le16_to_cpu(s->mac_reg[VET]));
@ -643,8 +646,8 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
}
addr = le64_to_cpu(dp->buffer_addr);
if (tp->props.tse && tp->props.cptse) {
msh = tp->props.hdr_len + tp->props.mss;
if (tp->cptse) {
msh = tp->tso_props.hdr_len + tp->tso_props.mss;
do {
bytes = split_size;
if (tp->size + bytes > msh)
@ -653,21 +656,19 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
bytes = MIN(sizeof(tp->data) - tp->size, bytes);
pci_dma_read(d, addr, tp->data + tp->size, bytes);
sz = tp->size + bytes;
if (sz >= tp->props.hdr_len && tp->size < tp->props.hdr_len) {
memmove(tp->header, tp->data, tp->props.hdr_len);
if (sz >= tp->tso_props.hdr_len
&& tp->size < tp->tso_props.hdr_len) {
memmove(tp->header, tp->data, tp->tso_props.hdr_len);
}
tp->size = sz;
addr += bytes;
if (sz == msh) {
xmit_seg(s);
memmove(tp->data, tp->header, tp->props.hdr_len);
tp->size = tp->props.hdr_len;
memmove(tp->data, tp->header, tp->tso_props.hdr_len);
tp->size = tp->tso_props.hdr_len;
}
split_size -= bytes;
} while (bytes && split_size);
} else if (!tp->props.tse && tp->props.cptse) {
// context descriptor TSE is not set, while data descriptor TSE is set
DBGOUT(TXERR, "TCP segmentation error\n");
} else {
split_size = MIN(sizeof(tp->data) - tp->size, split_size);
pci_dma_read(d, addr, tp->data + tp->size, split_size);
@ -676,14 +677,14 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
if (!(txd_lower & E1000_TXD_CMD_EOP))
return;
if (!(tp->props.tse && tp->props.cptse && tp->size < tp->props.hdr_len)) {
if (!(tp->cptse && tp->size < tp->tso_props.hdr_len)) {
xmit_seg(s);
}
tp->tso_frames = 0;
tp->props.sum_needed = 0;
tp->sum_needed = 0;
tp->vlan_needed = 0;
tp->size = 0;
tp->props.cptse = 0;
tp->cptse = 0;
}
static uint32_t
@ -1435,7 +1436,7 @@ static const VMStateDescription vmstate_e1000_full_mac_state = {
static const VMStateDescription vmstate_e1000 = {
.name = "e1000",
.version_id = 2,
.version_id = 3,
.minimum_version_id = 1,
.pre_save = e1000_pre_save,
.post_load = e1000_post_load,
@ -1461,7 +1462,7 @@ static const VMStateDescription vmstate_e1000 = {
VMSTATE_UINT16(tx.props.mss, E1000State),
VMSTATE_UINT16(tx.size, E1000State),
VMSTATE_UINT16(tx.tso_frames, E1000State),
VMSTATE_UINT8(tx.props.sum_needed, E1000State),
VMSTATE_UINT8(tx.sum_needed, E1000State),
VMSTATE_INT8(tx.props.ip, E1000State),
VMSTATE_INT8(tx.props.tcp, E1000State),
VMSTATE_BUFFER(tx.header, E1000State),
@ -1508,6 +1509,17 @@ static const VMStateDescription vmstate_e1000 = {
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32),
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128),
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
VMSTATE_UINT8_V(tx.tso_props.ipcss, E1000State, 3),
VMSTATE_UINT8_V(tx.tso_props.ipcso, E1000State, 3),
VMSTATE_UINT16_V(tx.tso_props.ipcse, E1000State, 3),
VMSTATE_UINT8_V(tx.tso_props.tucss, E1000State, 3),
VMSTATE_UINT8_V(tx.tso_props.tucso, E1000State, 3),
VMSTATE_UINT16_V(tx.tso_props.tucse, E1000State, 3),
VMSTATE_UINT32_V(tx.tso_props.paylen, E1000State, 3),
VMSTATE_UINT8_V(tx.tso_props.hdr_len, E1000State, 3),
VMSTATE_UINT16_V(tx.tso_props.mss, E1000State, 3),
VMSTATE_INT8_V(tx.tso_props.ip, E1000State, 3),
VMSTATE_INT8_V(tx.tso_props.tcp, E1000State, 3),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription*[]) {

View file

@ -556,7 +556,7 @@ static const VMStateDescription e1000e_vmstate_tx = {
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(props.sum_needed, struct e1000e_tx),
VMSTATE_UINT8(sum_needed, struct e1000e_tx),
VMSTATE_UINT8(props.ipcss, struct e1000e_tx),
VMSTATE_UINT8(props.ipcso, struct e1000e_tx),
VMSTATE_UINT16(props.ipcse, struct e1000e_tx),
@ -569,7 +569,7 @@ static const VMStateDescription e1000e_vmstate_tx = {
VMSTATE_INT8(props.ip, struct e1000e_tx),
VMSTATE_INT8(props.tcp, struct e1000e_tx),
VMSTATE_BOOL(props.tse, struct e1000e_tx),
VMSTATE_BOOL(props.cptse, struct e1000e_tx),
VMSTATE_BOOL(cptse, struct e1000e_tx),
VMSTATE_BOOL(skip_cp, struct e1000e_tx),
VMSTATE_END_OF_LIST()
}

View file

@ -632,18 +632,18 @@ e1000e_rss_parse_packet(E1000ECore *core,
static void
e1000e_setup_tx_offloads(E1000ECore *core, struct e1000e_tx *tx)
{
if (tx->props.tse && tx->props.cptse) {
if (tx->props.tse && tx->cptse) {
net_tx_pkt_build_vheader(tx->tx_pkt, true, true, tx->props.mss);
net_tx_pkt_update_ip_checksums(tx->tx_pkt);
e1000x_inc_reg_if_not_full(core->mac, TSCTC);
return;
}
if (tx->props.sum_needed & E1000_TXD_POPTS_TXSM) {
if (tx->sum_needed & E1000_TXD_POPTS_TXSM) {
net_tx_pkt_build_vheader(tx->tx_pkt, false, true, 0);
}
if (tx->props.sum_needed & E1000_TXD_POPTS_IXSM) {
if (tx->sum_needed & E1000_TXD_POPTS_IXSM) {
net_tx_pkt_update_ip_hdr_checksum(tx->tx_pkt);
}
}
@ -715,13 +715,13 @@ e1000e_process_tx_desc(E1000ECore *core,
return;
} else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
/* data descriptor */
tx->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8;
tx->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
tx->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
tx->cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
e1000e_process_ts_option(core, dp);
} else {
/* legacy descriptor */
e1000e_process_ts_option(core, dp);
tx->props.cptse = 0;
tx->cptse = 0;
}
addr = le64_to_cpu(dp->buffer_addr);
@ -747,8 +747,8 @@ e1000e_process_tx_desc(E1000ECore *core,
tx->skip_cp = false;
net_tx_pkt_reset(tx->tx_pkt);
tx->props.sum_needed = 0;
tx->props.cptse = 0;
tx->sum_needed = 0;
tx->cptse = 0;
}
}

View file

@ -71,6 +71,8 @@ struct E1000Core {
e1000x_txd_props props;
bool skip_cp;
unsigned char sum_needed;
bool cptse;
struct NetTxPkt *tx_pkt;
} tx[E1000E_NUM_QUEUES];

View file

@ -193,7 +193,6 @@ void e1000x_update_regs_on_autoneg_done(uint32_t *mac, uint16_t *phy);
void e1000x_increase_size_stats(uint32_t *mac, const int *size_regs, int size);
typedef struct e1000x_txd_props {
unsigned char sum_needed;
uint8_t ipcss;
uint8_t ipcso;
uint16_t ipcse;
@ -206,7 +205,6 @@ typedef struct e1000x_txd_props {
int8_t ip;
int8_t tcp;
bool tse;
bool cptse;
} e1000x_txd_props;
void e1000x_read_tx_ctx_descr(struct e1000_context_desc *d,

View file

@ -44,6 +44,7 @@
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "net/net.h"
#include "net/eth.h"
#include "hw/nvram/eeprom93xx.h"
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
@ -323,32 +324,8 @@ static const uint16_t eepro100_mdi_mask[] = {
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};
#define POLYNOMIAL 0x04c11db6
static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
/* From FreeBSD (locally modified). */
static unsigned e100_compute_mcast_idx(const uint8_t *ep)
{
uint32_t crc;
int carry, i, j;
uint8_t b;
crc = 0xffffffff;
for (i = 0; i < 6; i++) {
b = *ep++;
for (j = 0; j < 8; j++) {
carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
crc <<= 1;
b >>= 1;
if (carry) {
crc = ((crc ^ POLYNOMIAL) | carry);
}
}
}
return (crc & BITS(7, 2)) >> 2;
}
/* Read a 16 bit control/status (CSR) register. */
static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
{
@ -845,7 +822,8 @@ static void set_multicast_list(EEPRO100State *s)
uint8_t multicast_addr[6];
pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6);
TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
unsigned mcast_idx = e100_compute_mcast_idx(multicast_addr);
unsigned mcast_idx = (net_crc32(multicast_addr, ETH_ALEN) &
BITS(7, 2)) >> 2;
assert(mcast_idx < 64);
s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
}
@ -1681,7 +1659,7 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
if (s->configuration[21] & BIT(3)) {
/* Multicast all bit is set, receive all multicast frames. */
} else {
unsigned mcast_idx = e100_compute_mcast_idx(buf);
unsigned mcast_idx = (net_crc32(buf, ETH_ALEN) & BITS(7, 2)) >> 2;
assert(mcast_idx < 64);
if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
/* Multicast frame is allowed in hash table. */
@ -1701,7 +1679,7 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
rfd_status |= 0x0004;
} else if (s->configuration[20] & BIT(6)) {
/* Multiple IA bit set. */
unsigned mcast_idx = compute_mcast_idx(buf);
unsigned mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
assert(mcast_idx < 64);
if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
TRACE(RXTX, logout("%p accepted, multiple IA bit set\n", s));

View file

@ -762,7 +762,7 @@ static int ftgmac100_filter(FTGMAC100State *s, const uint8_t *buf, size_t len)
}
/* TODO: this does not seem to work for ftgmac100 */
mcast_idx = compute_mcast_idx(buf);
mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
if (!(s->math[mcast_idx / 32] & (1 << (mcast_idx % 32)))) {
return 0;
}

View file

@ -13,6 +13,7 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "net/net.h"
#include "net/eth.h"
#include "hw/devices.h"
#include "sysemu/sysemu.h"
#include "hw/ptimer.h"
@ -504,7 +505,7 @@ static int lan9118_filter(lan9118_state *s, const uint8_t *addr)
}
} else {
/* Hash matching */
hash = compute_mcast_idx(addr);
hash = net_crc32(addr, ETH_ALEN) >> 26;
if (hash & 0x20) {
return (s->mac_hashh >> (hash & 0x1f)) & 1;
} else {

View file

@ -23,6 +23,8 @@
*/
#include "qemu/osdep.h"
#include "hw/pci/pci.h"
#include "net/net.h"
#include "net/eth.h"
#include "ne2000.h"
#include "hw/loader.h"
#include "sysemu/sysemu.h"
@ -199,7 +201,7 @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
/* multicast */
if (!(s->rxcr & 0x08))
return size;
mcast_idx = compute_mcast_idx(buf);
mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
return size;
} else if (s->mem[0] == buf[0] &&

View file

@ -36,6 +36,7 @@
#include "hw/net/mii.h"
#include "hw/sysbus.h"
#include "net/net.h"
#include "net/eth.h"
#include "sysemu/sysemu.h"
#include "trace.h"
@ -373,7 +374,7 @@ static ssize_t open_eth_receive(NetClientState *nc,
if (memcmp(buf, bcast_addr, sizeof(bcast_addr)) == 0) {
miss = GET_REGBIT(s, MODER, BRO);
} else if ((buf[0] & 0x1) || GET_REGBIT(s, MODER, IAM)) {
unsigned mcast_idx = compute_mcast_idx(buf);
unsigned mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
miss = !(s->regs[HASH0 + mcast_idx / 32] &
(1 << (mcast_idx % 32)));
trace_open_eth_receive_mcast(

View file

@ -38,6 +38,7 @@
#include "qemu/osdep.h"
#include "hw/qdev.h"
#include "net/net.h"
#include "net/eth.h"
#include "qemu/timer.h"
#include "qemu/sockets.h"
#include "sysemu/sysemu.h"
@ -522,25 +523,6 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
be16_to_cpu(hdr->ether_type)); \
} while (0)
#define MULTICAST_FILTER_LEN 8
static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
{
#define LNC_POLYNOMIAL 0xEDB88320UL
uint32_t crc = 0xFFFFFFFF;
int idx, bit;
uint8_t data;
for (idx = 0; idx < 6; idx++) {
for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
data >>= 1;
}
}
return crc;
#undef LNC_POLYNOMIAL
}
#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
/* generated using the AUTODIN II polynomial
@ -656,7 +638,7 @@ static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
s->csr[10] & 0xff, s->csr[10] >> 8,
s->csr[11] & 0xff, s->csr[11] >> 8
};
int index = lnc_mchash(hdr->ether_dhost) >> 26;
int index = net_crc32_le(hdr->ether_dhost, ETH_ALEN) >> 26;
return !!(ladr[index >> 3] & (1 << (index & 7)));
}
return 0;

View file

@ -882,7 +882,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
return size;
}
int mcast_idx = compute_mcast_idx(buf);
int mcast_idx = net_crc32(buf, ETH_ALEN) >> 26;
if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
{

View file

@ -11,12 +11,11 @@
#include "hw/pci/pci.h"
#include "qemu/log.h"
#include "net/net.h"
#include "net/eth.h"
#include "net/checksum.h"
#include "hw/net/mii.h"
#include "sysemu/sysemu.h"
#include "trace.h"
/* For crc32 */
#include <zlib.h>
#define TYPE_SUNGEM "sungem"
@ -595,7 +594,7 @@ static ssize_t sungem_receive(NetClientState *nc, const uint8_t *buf,
}
/* Get MAC crc */
mac_crc = crc32(~0, buf, 6);
mac_crc = net_crc32_le(buf, ETH_ALEN);
/* Packet isn't for me ? */
rx_cond = sungem_check_rx_mac(s, buf, mac_crc);

View file

@ -698,29 +698,6 @@ static inline void sunhme_set_rx_ring_nr(SunHMEState *s, int i)
s->erxregs[HME_ERXI_RING >> 2] = ring;
}
#define POLYNOMIAL_LE 0xedb88320
static uint32_t sunhme_crc32_le(const uint8_t *p, int len)
{
uint32_t crc;
int carry, i, j;
uint8_t b;
crc = 0xffffffff;
for (i = 0; i < len; i++) {
b = *p++;
for (j = 0; j < 8; j++) {
carry = (crc & 0x1) ^ (b & 0x01);
crc >>= 1;
b >>= 1;
if (carry) {
crc = crc ^ POLYNOMIAL_LE;
}
}
}
return crc;
}
#define MIN_BUF_SIZE 60
static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf,
@ -761,7 +738,7 @@ static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf,
trace_sunhme_rx_filter_bcast_match();
} else if (s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_HENABLE) {
/* Didn't match local address, check hash filter */
int mcast_idx = sunhme_crc32_le(buf, 6) >> 26;
int mcast_idx = net_crc32_le(buf, ETH_ALEN) >> 26;
if (!(s->macregs[(HME_MACI_HASHTAB0 >> 2) - (mcast_idx >> 4)] &
(1 << (mcast_idx & 0xf)))) {
/* Didn't match hash filter */

View file

@ -227,7 +227,10 @@ NetClientState *net_hub_port_find(int hub_id);
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd);
#define POLYNOMIAL 0x04c11db6
#define POLYNOMIAL_BE 0x04c11db6
#define POLYNOMIAL_LE 0xedb88320
uint32_t net_crc32(const uint8_t *p, int len);
uint32_t net_crc32_le(const uint8_t *p, int len);
unsigned compute_mcast_idx(const uint8_t *ep);
#define vmstate_offset_macaddr(_state, _field) \

View file

@ -36,8 +36,6 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict);
int net_slirp_redir(const char *redir_str);
int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret);
int net_slirp_smb(const char *exported_dir);
void hmp_info_usernet(Monitor *mon, const QDict *qdict);

View file

@ -1565,13 +1565,6 @@ int net_init_clients(void)
int net_client_parse(QemuOptsList *opts_list, const char *optarg)
{
#if defined(CONFIG_SLIRP)
int ret;
if (net_slirp_parse_legacy(opts_list, optarg, &ret)) {
return ret;
}
#endif
if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
return -1;
}
@ -1581,25 +1574,48 @@ int net_client_parse(QemuOptsList *opts_list, const char *optarg)
/* From FreeBSD */
/* XXX: optimize */
unsigned compute_mcast_idx(const uint8_t *ep)
uint32_t net_crc32(const uint8_t *p, int len)
{
uint32_t crc;
int carry, i, j;
uint8_t b;
crc = 0xffffffff;
for (i = 0; i < 6; i++) {
b = *ep++;
for (i = 0; i < len; i++) {
b = *p++;
for (j = 0; j < 8; j++) {
carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
crc <<= 1;
b >>= 1;
if (carry) {
crc = ((crc ^ POLYNOMIAL) | carry);
crc = ((crc ^ POLYNOMIAL_BE) | carry);
}
}
}
return crc >> 26;
return crc;
}
uint32_t net_crc32_le(const uint8_t *p, int len)
{
uint32_t crc;
int carry, i, j;
uint8_t b;
crc = 0xffffffff;
for (i = 0; i < len; i++) {
b = *p++;
for (j = 0; j < 8; j++) {
carry = (crc & 0x1) ^ (b & 0x01);
crc >>= 1;
b >>= 1;
if (carry) {
crc ^= POLYNOMIAL_LE;
}
}
}
return crc;
}
QemuOptsList qemu_netdev_opts = {

View file

@ -956,37 +956,3 @@ int net_init_slirp(const Netdev *netdev, const char *name,
return ret;
}
int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret)
{
if (strcmp(opts_list->name, "net") != 0 ||
strncmp(optarg, "channel,", strlen("channel,")) != 0) {
return 0;
}
error_report("The '-net channel' option is deprecated. "
"Please use '-netdev user,guestfwd=...' instead.");
/* handle legacy -net channel,port:chr */
optarg += strlen("channel,");
if (QTAILQ_EMPTY(&slirp_stacks)) {
struct slirp_config_str *config;
config = g_malloc(sizeof(*config));
pstrcpy(config->str, sizeof(config->str), optarg);
config->flags = SLIRP_CFG_LEGACY;
config->next = slirp_configs;
slirp_configs = config;
*ret = 0;
} else {
Error *err = NULL;
*ret = slirp_guestfwd(QTAILQ_FIRST(&slirp_stacks), optarg, 1, &err);
if (*ret < 0) {
error_report_err(err);
}
}
return 1;
}

View file

@ -2648,32 +2648,36 @@ combined with ``-vnc tls-creds=tls0'
@subsection -tftp (since 2.6.0)
The ``-tftp /some/dir'' argument is now a synonym for setting
the ``-netdev user,tftp=/some/dir' argument. The new syntax
allows different settings to be provided per NIC.
The ``-tftp /some/dir'' argument is replaced by
``-netdev user,id=x,tftp=/some/dir'', either accompanied with
``-device ...,netdev=x'' (for pluggable NICs) or ``-net nic,netdev=x''
(for embedded NICs). The new syntax allows different settings to be
provided per NIC.
@subsection -bootp (since 2.6.0)
The ``-bootp /some/file'' argument is now a synonym for setting
the ``-netdev user,bootp=/some/file' argument. The new syntax
allows different settings to be provided per NIC.
The ``-bootp /some/file'' argument is replaced by
``-netdev user,id=x,bootp=/some/file'', either accompanied with
``-device ...,netdev=x'' (for pluggable NICs) or ``-net nic,netdev=x''
(for embedded NICs). The new syntax allows different settings to be
provided per NIC.
@subsection -redir (since 2.6.0)
The ``-redir ARGS'' argument is now a synonym for setting
the ``-netdev user,hostfwd=ARGS'' argument instead. The new
syntax allows different settings to be provided per NIC.
The ``-redir [tcp|udp]:hostport:[guestaddr]:guestport'' argument is
replaced by ``-netdev
user,id=x,hostfwd=[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport'',
either accompanied with ``-device ...,netdev=x'' (for pluggable NICs) or
``-net nic,netdev=x'' (for embedded NICs). The new syntax allows different
settings to be provided per NIC.
@subsection -smb (since 2.6.0)
The ``-smb /some/dir'' argument is now a synonym for setting
the ``-netdev user,smb=/some/dir'' argument instead. The new
syntax allows different settings to be provided per NIC.
@subsection -net channel (since 2.6.0)
The ``--net channel,ARGS'' argument is now a synonym for setting
the ``-netdev user,guestfwd=ARGS'' argument instead.
The ``-smb /some/dir'' argument is replaced by
``-netdev user,id=x,smb=/some/dir'', either accompanied with
``-device ...,netdev=x'' (for pluggable NICs) or ``-net nic,netdev=x''
(for embedded NICs). The new syntax allows different settings to be
provided per NIC.
@subsection -net vlan (since 2.9.0)

View file

@ -2035,9 +2035,10 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
"-netdev hubport,id=str,hubid=n\n"
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
DEF("net", HAS_ARG, QEMU_OPTION_net,
"-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
" old way to create a new NIC and connect it to VLAN 'n'\n"
" (use the '-device devtype,netdev=str' option if possible instead)\n"
"-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
" configure or create an on-board (or machine default) NIC and\n"
" connect it either to VLAN 'n' or the netdev 'nd' (for pluggable\n"
" NICs please use '-device devtype,netdev=nd' instead)\n"
"-net dump[,vlan=n][,file=f][,len=n]\n"
" dump traffic on vlan 'n' to file 'f' (max n bytes per packet)\n"
"-net none use it alone to have zero network devices. If no -net option\n"
@ -2058,10 +2059,11 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
" old way to initialize a host network interface\n"
" (use the -netdev option if possible instead)\n", QEMU_ARCH_ALL)
STEXI
@item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
@item -net nic[,vlan=@var{n}][,netdev=@var{nd}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
@findex -net
Create a new Network Interface Card and connect it to VLAN @var{n} (@var{n}
= 0 is the default). The NIC is an e1000 by default on the PC
Configure or create an on-board (or machine default) Network Interface Card
(NIC) and connect it either to VLAN @var{n} (@var{n} = 0 is the default), or
to the netdev @var{nd}. The NIC is an e1000 by default on the PC
target. Optionally, the MAC address can be changed to @var{mac}, the
device address set to @var{addr} (PCI cards only),
and a @var{name} can be assigned for use in monitor commands.