summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPeter Maydell2016-06-02 15:26:57 +0200
committerPeter Maydell2016-06-02 15:26:57 +0200
commit2c107d7684f9e3c4db4780d0756bbf35b06aec07 (patch)
treed4b68dfdd7efc8bd3fb5fe89bcbb5baab1a23c85 /include
parentMerge remote-tracking branch 'remotes/famz/tags/pull-docker-20160601' into st... (diff)
parentAdd ENET device to i.MX6 SOC. (diff)
downloadqemu-2c107d7684f9e3c4db4780d0756bbf35b06aec07.tar.gz
qemu-2c107d7684f9e3c4db4780d0756bbf35b06aec07.tar.xz
qemu-2c107d7684f9e3c4db4780d0756bbf35b06aec07.zip
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging
# gpg: Signature made Thu 02 Jun 2016 07:23:18 BST using RSA key ID 398D6211 # 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: (31 commits) Add ENET device to i.MX6 SOC. Add ENET/Gbps Ethernet support to FEC device i.MX: move FEC device to a register array structure. i.MX: Rename i.MX FEC defines to ENET_XXX i.MX: reset TX/RX descriptors when FEC is disabled. i.MX: Fix FEC code for ECR register reset value. i.MX: Fix FEC code for MDIO address selection i.MX: Fix FEC code for MDIO operation selection net: handle optional VLAN header in checksum computation. net: improve UDP/TCP checksum computation. e1000e: Introduce qtest for e1000e device net: Introduce e1000e device emulation e1000: Move out code that will be reused in e1000e e1000_regs: Add definitions for Intel 82574-specific bits vmxnet3: Use pci_dma_* API instead of cpu_physical_memory_* net_pkt: Extend packet abstraction as required by e1000e functionality rtl8139: Move more TCP definitions to common header net_pkt: Name vmxnet3 packet abstractions more generic vmxnet3: Use common MAC address tracing macros net: Add macros for MAC address tracing ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r--include/hw/arm/fsl-imx6.h6
-rw-r--r--include/hw/net/imx_fec.h250
-rw-r--r--include/hw/pci/msix.h1
-rw-r--r--include/hw/pci/pci.h11
-rw-r--r--include/hw/pci/pci_regs.h2
-rw-r--r--include/hw/pci/pcie.h5
-rw-r--r--include/hw/pci/pcie_regs.h5
-rw-r--r--include/net/checksum.h49
-rw-r--r--include/net/eth.h158
-rw-r--r--include/net/net.h19
10 files changed, 402 insertions, 104 deletions
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index e9157ea4b3..ec6c509d74 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -28,6 +28,7 @@
#include "hw/gpio/imx_gpio.h"
#include "hw/sd/sdhci.h"
#include "hw/ssi/imx_spi.h"
+#include "hw/net/imx_fec.h"
#include "exec/memory.h"
#include "cpu.h"
@@ -58,6 +59,7 @@ typedef struct FslIMX6State {
IMXGPIOState gpio[FSL_IMX6_NUM_GPIOS];
SDHCIState esdhc[FSL_IMX6_NUM_ESDHCS];
IMXSPIState spi[FSL_IMX6_NUM_ECSPIS];
+ IMXFECState eth;
MemoryRegion rom;
MemoryRegion caam;
MemoryRegion ocram;
@@ -436,8 +438,8 @@ typedef struct FslIMX6State {
#define FSL_IMX6_HDMI_MASTER_IRQ 115
#define FSL_IMX6_HDMI_CEC_IRQ 116
#define FSL_IMX6_MLB150_LOW_IRQ 117
-#define FSL_IMX6_ENET_MAC_IRQ 118
-#define FSL_IMX6_ENET_MAC_1588_IRQ 119
+#define FSL_IMX6_ENET_MAC_1588_IRQ 118
+#define FSL_IMX6_ENET_MAC_IRQ 119
#define FSL_IMX6_PCIE1_IRQ 120
#define FSL_IMX6_PCIE2_IRQ 121
#define FSL_IMX6_PCIE3_IRQ 122
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index cbf86509e8..62ad473b05 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -1,5 +1,5 @@
/*
- * i.MX Fast Ethernet Controller emulation.
+ * i.MX FEC/ENET Ethernet Controller emulation.
*
* Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
*
@@ -27,27 +27,147 @@
#define TYPE_IMX_FEC "imx.fec"
#define IMX_FEC(obj) OBJECT_CHECK(IMXFECState, (obj), TYPE_IMX_FEC)
+#define TYPE_IMX_ENET "imx.enet"
+
#include "hw/sysbus.h"
#include "net/net.h"
-#define FEC_MAX_FRAME_SIZE 2032
-
-#define FEC_INT_HB (1 << 31)
-#define FEC_INT_BABR (1 << 30)
-#define FEC_INT_BABT (1 << 29)
-#define FEC_INT_GRA (1 << 28)
-#define FEC_INT_TXF (1 << 27)
-#define FEC_INT_TXB (1 << 26)
-#define FEC_INT_RXF (1 << 25)
-#define FEC_INT_RXB (1 << 24)
-#define FEC_INT_MII (1 << 23)
-#define FEC_INT_EBERR (1 << 22)
-#define FEC_INT_LC (1 << 21)
-#define FEC_INT_RL (1 << 20)
-#define FEC_INT_UN (1 << 19)
-
-#define FEC_EN 2
-#define FEC_RESET 1
+#define ENET_EIR 1
+#define ENET_EIMR 2
+#define ENET_RDAR 4
+#define ENET_TDAR 5
+#define ENET_ECR 9
+#define ENET_MMFR 16
+#define ENET_MSCR 17
+#define ENET_MIBC 25
+#define ENET_RCR 33
+#define ENET_TCR 49
+#define ENET_PALR 57
+#define ENET_PAUR 58
+#define ENET_OPD 59
+#define ENET_IAUR 70
+#define ENET_IALR 71
+#define ENET_GAUR 72
+#define ENET_GALR 73
+#define ENET_TFWR 81
+#define ENET_FRBR 83
+#define ENET_FRSR 84
+#define ENET_RDSR 96
+#define ENET_TDSR 97
+#define ENET_MRBR 98
+#define ENET_RSFL 100
+#define ENET_RSEM 101
+#define ENET_RAEM 102
+#define ENET_RAFL 103
+#define ENET_TSEM 104
+#define ENET_TAEM 105
+#define ENET_TAFL 106
+#define ENET_TIPG 107
+#define ENET_FTRL 108
+#define ENET_TACC 112
+#define ENET_RACC 113
+#define ENET_MIIGSK_CFGR 192
+#define ENET_MIIGSK_ENR 194
+#define ENET_ATCR 256
+#define ENET_ATVR 257
+#define ENET_ATOFF 258
+#define ENET_ATPER 259
+#define ENET_ATCOR 260
+#define ENET_ATINC 261
+#define ENET_ATSTMP 262
+#define ENET_TGSR 385
+#define ENET_TCSR0 386
+#define ENET_TCCR0 387
+#define ENET_TCSR1 388
+#define ENET_TCCR1 389
+#define ENET_TCSR2 390
+#define ENET_TCCR2 391
+#define ENET_TCSR3 392
+#define ENET_TCCR3 393
+#define ENET_MAX 400
+
+#define ENET_MAX_FRAME_SIZE 2032
+
+/* EIR and EIMR */
+#define ENET_INT_HB (1 << 31)
+#define ENET_INT_BABR (1 << 30)
+#define ENET_INT_BABT (1 << 29)
+#define ENET_INT_GRA (1 << 28)
+#define ENET_INT_TXF (1 << 27)
+#define ENET_INT_TXB (1 << 26)
+#define ENET_INT_RXF (1 << 25)
+#define ENET_INT_RXB (1 << 24)
+#define ENET_INT_MII (1 << 23)
+#define ENET_INT_EBERR (1 << 22)
+#define ENET_INT_LC (1 << 21)
+#define ENET_INT_RL (1 << 20)
+#define ENET_INT_UN (1 << 19)
+#define ENET_INT_PLR (1 << 18)
+#define ENET_INT_WAKEUP (1 << 17)
+#define ENET_INT_TS_AVAIL (1 << 16)
+#define ENET_INT_TS_TIMER (1 << 15)
+
+#define ENET_INT_MAC (ENET_INT_HB | ENET_INT_BABR | ENET_INT_BABT | \
+ ENET_INT_GRA | ENET_INT_TXF | ENET_INT_TXB | \
+ ENET_INT_RXF | ENET_INT_RXB | ENET_INT_MII | \
+ ENET_INT_EBERR | ENET_INT_LC | ENET_INT_RL | \
+ ENET_INT_UN | ENET_INT_PLR | ENET_INT_WAKEUP | \
+ ENET_INT_TS_AVAIL)
+
+/* RDAR */
+#define ENET_RDAR_RDAR (1 << 24)
+
+/* TDAR */
+#define ENET_TDAR_TDAR (1 << 24)
+
+/* ECR */
+#define ENET_ECR_RESET (1 << 0)
+#define ENET_ECR_ETHEREN (1 << 1)
+#define ENET_ECR_MAGICEN (1 << 2)
+#define ENET_ECR_SLEEP (1 << 3)
+#define ENET_ECR_EN1588 (1 << 4)
+#define ENET_ECR_SPEED (1 << 5)
+#define ENET_ECR_DBGEN (1 << 6)
+#define ENET_ECR_STOPEN (1 << 7)
+#define ENET_ECR_DSBWP (1 << 8)
+
+/* MIBC */
+#define ENET_MIBC_MIB_DIS (1 << 31)
+#define ENET_MIBC_MIB_IDLE (1 << 30)
+#define ENET_MIBC_MIB_CLEAR (1 << 29)
+
+/* RCR */
+#define ENET_RCR_LOOP (1 << 0)
+#define ENET_RCR_DRT (1 << 1)
+#define ENET_RCR_MII_MODE (1 << 2)
+#define ENET_RCR_PROM (1 << 3)
+#define ENET_RCR_BC_REJ (1 << 4)
+#define ENET_RCR_FCE (1 << 5)
+#define ENET_RCR_RGMII_EN (1 << 6)
+#define ENET_RCR_RMII_MODE (1 << 8)
+#define ENET_RCR_RMII_10T (1 << 9)
+#define ENET_RCR_PADEN (1 << 12)
+#define ENET_RCR_PAUFWD (1 << 13)
+#define ENET_RCR_CRCFWD (1 << 14)
+#define ENET_RCR_CFEN (1 << 15)
+#define ENET_RCR_MAX_FL_SHIFT (16)
+#define ENET_RCR_MAX_FL_LENGTH (14)
+#define ENET_RCR_NLC (1 << 30)
+#define ENET_RCR_GRS (1 << 31)
+
+/* TCR */
+#define ENET_TCR_GTS (1 << 0)
+#define ENET_TCR_FDEN (1 << 2)
+#define ENET_TCR_TFC_PAUSE (1 << 3)
+#define ENET_TCR_RFC_PAUSE (1 << 4)
+#define ENET_TCR_ADDSEL_SHIFT (5)
+#define ENET_TCR_ADDSEL_LENGTH (3)
+#define ENET_TCR_CRCFWD (1 << 9)
+
+/* RDSR */
+#define ENET_TWFR_TFWR_SHIFT (0)
+#define ENET_TWFR_TFWR_LENGTH (6)
+#define ENET_TWFR_STRFWD (1 << 8)
/* Buffer Descriptor. */
typedef struct {
@@ -56,22 +176,60 @@ typedef struct {
uint32_t data;
} IMXFECBufDesc;
-#define FEC_BD_R (1 << 15)
-#define FEC_BD_E (1 << 15)
-#define FEC_BD_O1 (1 << 14)
-#define FEC_BD_W (1 << 13)
-#define FEC_BD_O2 (1 << 12)
-#define FEC_BD_L (1 << 11)
-#define FEC_BD_TC (1 << 10)
-#define FEC_BD_ABC (1 << 9)
-#define FEC_BD_M (1 << 8)
-#define FEC_BD_BC (1 << 7)
-#define FEC_BD_MC (1 << 6)
-#define FEC_BD_LG (1 << 5)
-#define FEC_BD_NO (1 << 4)
-#define FEC_BD_CR (1 << 2)
-#define FEC_BD_OV (1 << 1)
-#define FEC_BD_TR (1 << 0)
+#define ENET_BD_R (1 << 15)
+#define ENET_BD_E (1 << 15)
+#define ENET_BD_O1 (1 << 14)
+#define ENET_BD_W (1 << 13)
+#define ENET_BD_O2 (1 << 12)
+#define ENET_BD_L (1 << 11)
+#define ENET_BD_TC (1 << 10)
+#define ENET_BD_ABC (1 << 9)
+#define ENET_BD_M (1 << 8)
+#define ENET_BD_BC (1 << 7)
+#define ENET_BD_MC (1 << 6)
+#define ENET_BD_LG (1 << 5)
+#define ENET_BD_NO (1 << 4)
+#define ENET_BD_CR (1 << 2)
+#define ENET_BD_OV (1 << 1)
+#define ENET_BD_TR (1 << 0)
+
+typedef struct {
+ uint16_t length;
+ uint16_t flags;
+ uint32_t data;
+ uint16_t status;
+ uint16_t option;
+ uint16_t checksum;
+ uint16_t head_proto;
+ uint32_t last_buffer;
+ uint32_t timestamp;
+ uint32_t reserved[2];
+} IMXENETBufDesc;
+
+#define ENET_BD_ME (1 << 15)
+#define ENET_BD_TX_INT (1 << 14)
+#define ENET_BD_TS (1 << 13)
+#define ENET_BD_PINS (1 << 12)
+#define ENET_BD_IINS (1 << 11)
+#define ENET_BD_PE (1 << 10)
+#define ENET_BD_CE (1 << 9)
+#define ENET_BD_UC (1 << 8)
+#define ENET_BD_RX_INT (1 << 7)
+
+#define ENET_BD_TXE (1 << 15)
+#define ENET_BD_UE (1 << 13)
+#define ENET_BD_EE (1 << 12)
+#define ENET_BD_FE (1 << 11)
+#define ENET_BD_LCE (1 << 10)
+#define ENET_BD_OE (1 << 9)
+#define ENET_BD_TSE (1 << 8)
+#define ENET_BD_ICE (1 << 5)
+#define ENET_BD_PCR (1 << 4)
+#define ENET_BD_VLAN (1 << 2)
+#define ENET_BD_IPV6 (1 << 1)
+#define ENET_BD_FRAG (1 << 0)
+
+#define ENET_BD_BDU (1 << 31)
typedef struct IMXFECState {
/*< private >*/
@@ -80,34 +238,20 @@ typedef struct IMXFECState {
/*< public >*/
NICState *nic;
NICConf conf;
- qemu_irq irq;
+ qemu_irq irq[2];
MemoryRegion iomem;
- uint32_t irq_state;
- uint32_t eir;
- uint32_t eimr;
- uint32_t rx_enabled;
+ uint32_t regs[ENET_MAX];
uint32_t rx_descriptor;
uint32_t tx_descriptor;
- uint32_t ecr;
- uint32_t mmfr;
- uint32_t mscr;
- uint32_t mibc;
- uint32_t rcr;
- uint32_t tcr;
- uint32_t tfwr;
- uint32_t frsr;
- uint32_t erdsr;
- uint32_t etdsr;
- uint32_t emrbr;
- uint32_t miigsk_cfgr;
- uint32_t miigsk_enr;
uint32_t phy_status;
uint32_t phy_control;
uint32_t phy_advertise;
uint32_t phy_int;
uint32_t phy_int_mask;
+
+ bool is_fec;
} IMXFECState;
#endif
diff --git a/include/hw/pci/msix.h b/include/hw/pci/msix.h
index 72e5f931c5..048a29dd2f 100644
--- a/include/hw/pci/msix.h
+++ b/include/hw/pci/msix.h
@@ -29,6 +29,7 @@ int msix_present(PCIDevice *dev);
bool msix_is_masked(PCIDevice *dev, unsigned vector);
void msix_set_pending(PCIDevice *dev, unsigned vector);
+void msix_clr_pending(PCIDevice *dev, int vector);
int msix_vector_use(PCIDevice *dev, unsigned vector);
void msix_vector_unuse(PCIDevice *dev, unsigned vector);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index ef6ba51f6c..4420f47598 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -465,16 +465,23 @@ pci_get_long(const uint8_t *config)
return ldl_le_p(config);
}
+/*
+ * PCI capabilities and/or their fields
+ * are generally DWORD aligned only so
+ * mechanism used by pci_set/get_quad()
+ * must be tolerant to unaligned pointers
+ *
+ */
static inline void
pci_set_quad(uint8_t *config, uint64_t val)
{
- cpu_to_le64w((uint64_t *)config, val);
+ stq_le_p(config, val);
}
static inline uint64_t
pci_get_quad(const uint8_t *config)
{
- return le64_to_cpup((const uint64_t *)config);
+ return ldq_le_p(config);
}
static inline void
diff --git a/include/hw/pci/pci_regs.h b/include/hw/pci/pci_regs.h
index ba8cbe9278..7a83142578 100644
--- a/include/hw/pci/pci_regs.h
+++ b/include/hw/pci/pci_regs.h
@@ -1 +1,3 @@
#include "standard-headers/linux/pci_regs.h"
+
+#define PCI_PM_CAP_VER_1_1 0x0002 /* PCI PM spec ver. 1.1 */
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index b48a7a2c5a..056d25e53c 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -80,8 +80,12 @@ struct PCIExpressDevice {
/* PCI express capability helper functions */
int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port);
+int pcie_cap_v1_init(PCIDevice *dev, uint8_t offset,
+ uint8_t type, uint8_t port);
int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset);
void pcie_cap_exit(PCIDevice *dev);
+int pcie_endpoint_cap_v1_init(PCIDevice *dev, uint8_t offset);
+void pcie_cap_v1_exit(PCIDevice *dev);
uint8_t pcie_cap_get_type(const PCIDevice *dev);
void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector);
uint8_t pcie_cap_flags_get_vector(PCIDevice *dev);
@@ -115,6 +119,7 @@ void pcie_add_capability(PCIDevice *dev,
uint16_t offset, uint16_t size);
void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn);
+void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num);
extern const VMStateDescription vmstate_pcie_device;
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index 6a28b33e69..a95522a13b 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -11,6 +11,7 @@
/* express capability */
+#define PCI_EXP_VER1_SIZEOF 0x14 /* express capability of ver. 1 */
#define PCI_EXP_VER2_SIZEOF 0x3c /* express capability of ver. 2 */
#define PCI_EXT_CAP_VER_SHIFT 16
#define PCI_EXT_CAP_NEXT_SHIFT 20
@@ -26,11 +27,11 @@
(((x) + PCI_EXT_CAP_ALIGN - 1) & ~(PCI_EXT_CAP_ALIGN - 1))
/* PCI_EXP_FLAGS */
-#define PCI_EXP_FLAGS_VER2 2 /* for now, supports only ver. 2 */
+#define PCI_EXP_FLAGS_VER1 1
+#define PCI_EXP_FLAGS_VER2 2
#define PCI_EXP_FLAGS_IRQ_SHIFT ctz32(PCI_EXP_FLAGS_IRQ)
#define PCI_EXP_FLAGS_TYPE_SHIFT ctz32(PCI_EXP_FLAGS_TYPE)
-
/* PCI_EXP_LINK{CAP, STA} */
/* link speed */
#define PCI_EXP_LNK_LS_25 1
diff --git a/include/net/checksum.h b/include/net/checksum.h
index 7de1acb79a..7df472c2fe 100644
--- a/include/net/checksum.h
+++ b/include/net/checksum.h
@@ -18,6 +18,7 @@
#ifndef QEMU_NET_CHECKSUM_H
#define QEMU_NET_CHECKSUM_H
+#include "qemu/bswap.h"
struct iovec;
uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq);
@@ -45,9 +46,55 @@ net_raw_checksum(uint8_t *data, int length)
* @iov_cnt: number of array elements
* @iov_off: starting iov offset for checksumming
* @size: length of data to be checksummed
+ * @csum_offset: offset of the checksum chunk
*/
uint32_t net_checksum_add_iov(const struct iovec *iov,
const unsigned int iov_cnt,
- uint32_t iov_off, uint32_t size);
+ uint32_t iov_off, uint32_t size,
+ uint32_t csum_offset);
+
+typedef struct toeplitz_key_st {
+ uint32_t leftmost_32_bits;
+ uint8_t *next_byte;
+} net_toeplitz_key;
+
+static inline
+void net_toeplitz_key_init(net_toeplitz_key *key, uint8_t *key_bytes)
+{
+ key->leftmost_32_bits = be32_to_cpu(*(uint32_t *)key_bytes);
+ key->next_byte = key_bytes + sizeof(uint32_t);
+}
+
+static inline
+void net_toeplitz_add(uint32_t *result,
+ uint8_t *input,
+ uint32_t len,
+ net_toeplitz_key *key)
+{
+ register uint32_t accumulator = *result;
+ register uint32_t leftmost_32_bits = key->leftmost_32_bits;
+ register uint32_t byte;
+
+ for (byte = 0; byte < len; byte++) {
+ register uint8_t input_byte = input[byte];
+ register uint8_t key_byte = *(key->next_byte++);
+ register uint8_t bit;
+
+ for (bit = 0; bit < 8; bit++) {
+ if (input_byte & (1 << 7)) {
+ accumulator ^= leftmost_32_bits;
+ }
+
+ leftmost_32_bits =
+ (leftmost_32_bits << 1) | ((key_byte & (1 << 7)) >> 7);
+
+ input_byte <<= 1;
+ key_byte <<= 1;
+ }
+ }
+
+ key->leftmost_32_bits = leftmost_32_bits;
+ *result = accumulator;
+}
#endif /* QEMU_NET_CHECKSUM_H */
diff --git a/include/net/eth.h b/include/net/eth.h
index 18d0be3b16..2013175857 100644
--- a/include/net/eth.h
+++ b/include/net/eth.h
@@ -67,6 +67,16 @@ typedef struct tcp_header {
uint16_t th_urp; /* urgent pointer */
} tcp_header;
+#define TCP_FLAGS_ONLY(flags) ((flags) & 0x3f)
+
+#define TCP_HEADER_FLAGS(tcp) \
+ TCP_FLAGS_ONLY(be16_to_cpu((tcp)->th_offset_flags))
+
+#define TCP_FLAG_ACK 0x10
+
+#define TCP_HEADER_DATA_OFFSET(tcp) \
+ (((be16_to_cpu((tcp)->th_offset_flags) >> 12) & 0xf) << 2)
+
typedef struct udp_header {
uint16_t uh_sport; /* source port */
uint16_t uh_dport; /* destination port */
@@ -108,11 +118,34 @@ struct ip6_header {
struct in6_address ip6_dst; /* destination address */
};
+typedef struct ip6_pseudo_header {
+ struct in6_address ip6_src;
+ struct in6_address ip6_dst;
+ uint32_t len;
+ uint8_t zero[3];
+ uint8_t next_hdr;
+} ip6_pseudo_header;
+
struct ip6_ext_hdr {
uint8_t ip6r_nxt; /* next header */
uint8_t ip6r_len; /* length in units of 8 octets */
};
+struct ip6_ext_hdr_routing {
+ uint8_t nxt;
+ uint8_t len;
+ uint8_t rtype;
+ uint8_t segleft;
+ uint8_t rsvd[4];
+};
+
+struct ip6_option_hdr {
+#define IP6_OPT_PAD1 (0x00)
+#define IP6_OPT_HOME (0xC9)
+ uint8_t type;
+ uint8_t len;
+};
+
struct udp_hdr {
uint16_t uh_sport; /* source port */
uint16_t uh_dport; /* destination port */
@@ -161,19 +194,22 @@ struct tcp_hdr {
#define PKT_GET_IP_HDR(p) \
((struct ip_header *)(((uint8_t *)(p)) + eth_get_l2_hdr_length(p)))
#define IP_HDR_GET_LEN(p) \
- ((((struct ip_header *)p)->ip_ver_len & 0x0F) << 2)
+ ((((struct ip_header *)(p))->ip_ver_len & 0x0F) << 2)
#define PKT_GET_IP_HDR_LEN(p) \
(IP_HDR_GET_LEN(PKT_GET_IP_HDR(p)))
#define PKT_GET_IP6_HDR(p) \
((struct ip6_header *) (((uint8_t *)(p)) + eth_get_l2_hdr_length(p)))
#define IP_HEADER_VERSION(ip) \
- ((ip->ip_ver_len >> 4)&0xf)
+ (((ip)->ip_ver_len >> 4) & 0xf)
+#define IP4_IS_FRAGMENT(ip) \
+ ((be16_to_cpu((ip)->ip_off) & (IP_OFFMASK | IP_MF)) != 0)
#define ETH_P_IP (0x0800) /* Internet Protocol packet */
#define ETH_P_ARP (0x0806) /* Address Resolution packet */
#define ETH_P_IPV6 (0x86dd)
#define ETH_P_VLAN (0x8100)
#define ETH_P_DVLAN (0x88a8)
+#define ETH_P_UNKNOWN (0xffff)
#define VLAN_VID_MASK 0x0fff
#define IP_HEADER_VERSION_4 (4)
#define IP_HEADER_VERSION_6 (6)
@@ -258,7 +294,7 @@ eth_get_l2_hdr_length(const void *p)
case ETH_P_VLAN:
return sizeof(struct eth_header) + sizeof(struct vlan_header);
case ETH_P_DVLAN:
- if (hvlan->h_proto == ETH_P_VLAN) {
+ if (be16_to_cpu(hvlan->h_proto) == ETH_P_VLAN) {
return sizeof(struct eth_header) + 2 * sizeof(struct vlan_header);
} else {
return sizeof(struct eth_header) + sizeof(struct vlan_header);
@@ -268,6 +304,19 @@ eth_get_l2_hdr_length(const void *p)
}
}
+static inline uint32_t
+eth_get_l2_hdr_length_iov(const struct iovec *iov, int iovcnt)
+{
+ uint8_t p[sizeof(struct eth_header) + sizeof(struct vlan_header)];
+ size_t copied = iov_to_buf(iov, iovcnt, 0, p, ARRAY_SIZE(p));
+
+ if (copied < ARRAY_SIZE(p)) {
+ return copied;
+ }
+
+ return eth_get_l2_hdr_length(p);
+}
+
static inline uint16_t
eth_get_pkt_tci(const void *p)
{
@@ -282,51 +331,67 @@ eth_get_pkt_tci(const void *p)
}
}
-static inline bool
-eth_strip_vlan(const void *p, uint8_t *new_ehdr_buf,
- uint16_t *payload_offset, uint16_t *tci)
-{
- uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto);
- struct vlan_header *hvlan = PKT_GET_VLAN_HDR(p);
- struct eth_header *new_ehdr = (struct eth_header *) new_ehdr_buf;
+bool
+eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
+ uint8_t *new_ehdr_buf,
+ uint16_t *payload_offset, uint16_t *tci);
- switch (proto) {
- case ETH_P_VLAN:
- case ETH_P_DVLAN:
- memcpy(new_ehdr->h_source, PKT_GET_ETH_HDR(p)->h_source, ETH_ALEN);
- memcpy(new_ehdr->h_dest, PKT_GET_ETH_HDR(p)->h_dest, ETH_ALEN);
- new_ehdr->h_proto = hvlan->h_proto;
- *tci = be16_to_cpu(hvlan->h_tci);
- *payload_offset =
- sizeof(struct eth_header) + sizeof(struct vlan_header);
- if (be16_to_cpu(new_ehdr->h_proto) == ETH_P_VLAN) {
- memcpy(PKT_GET_VLAN_HDR(new_ehdr),
- PKT_GET_DVLAN_HDR(p),
- sizeof(struct vlan_header));
- *payload_offset += sizeof(struct vlan_header);
- }
- return true;
- default:
- return false;
- }
-}
+bool
+eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
+ uint16_t vet, uint8_t *new_ehdr_buf,
+ uint16_t *payload_offset, uint16_t *tci);
-static inline uint16_t
-eth_get_l3_proto(const void *l2hdr, size_t l2hdr_len)
+uint16_t
+eth_get_l3_proto(const struct iovec *l2hdr_iov, int iovcnt, size_t l2hdr_len);
+
+void eth_setup_vlan_headers_ex(struct eth_header *ehdr, uint16_t vlan_tag,
+ uint16_t vlan_ethtype, bool *is_new);
+
+static inline void
+eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag,
+ bool *is_new)
{
- uint8_t *proto_ptr = (uint8_t *) l2hdr + l2hdr_len - sizeof(uint16_t);
- return be16_to_cpup((uint16_t *)proto_ptr);
+ eth_setup_vlan_headers_ex(ehdr, vlan_tag, ETH_P_VLAN, is_new);
}
-void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag,
- bool *is_new);
uint8_t eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto);
-void eth_get_protocols(const uint8_t *headers,
- uint32_t hdr_length,
+typedef struct eth_ip6_hdr_info_st {
+ uint8_t l4proto;
+ size_t full_hdr_len;
+ struct ip6_header ip6_hdr;
+ bool has_ext_hdrs;
+ bool rss_ex_src_valid;
+ struct in6_address rss_ex_src;
+ bool rss_ex_dst_valid;
+ struct in6_address rss_ex_dst;
+ bool fragment;
+} eth_ip6_hdr_info;
+
+typedef struct eth_ip4_hdr_info_st {
+ struct ip_header ip4_hdr;
+ bool fragment;
+} eth_ip4_hdr_info;
+
+typedef struct eth_l4_hdr_info_st {
+ union {
+ struct tcp_header tcp;
+ struct udp_header udp;
+ } hdr;
+
+ bool has_tcp_data;
+} eth_l4_hdr_info;
+
+void eth_get_protocols(const struct iovec *iov, int iovcnt,
bool *isip4, bool *isip6,
- bool *isudp, bool *istcp);
+ bool *isudp, bool *istcp,
+ size_t *l3hdr_off,
+ size_t *l4hdr_off,
+ size_t *l5hdr_off,
+ eth_ip6_hdr_info *ip6hdr_info,
+ eth_ip4_hdr_info *ip4hdr_info,
+ eth_l4_hdr_info *l4hdr_info);
void eth_setup_ip4_fragmentation(const void *l2hdr, size_t l2hdr_len,
void *l3hdr, size_t l3hdr_len,
@@ -337,11 +402,18 @@ void
eth_fix_ip4_checksum(void *l3hdr, size_t l3hdr_len);
uint32_t
-eth_calc_pseudo_hdr_csum(struct ip_header *iphdr, uint16_t csl);
+eth_calc_ip4_pseudo_hdr_csum(struct ip_header *iphdr,
+ uint16_t csl,
+ uint32_t *cso);
+
+uint32_t
+eth_calc_ip6_pseudo_hdr_csum(struct ip6_header *iphdr,
+ uint16_t csl,
+ uint8_t l4_proto,
+ uint32_t *cso);
bool
-eth_parse_ipv6_hdr(struct iovec *pkt, int pkt_frags,
- size_t ip6hdr_off, uint8_t *l4proto,
- size_t *full_hdr_len);
+eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags,
+ size_t ip6hdr_off, eth_ip6_hdr_info *info);
#endif
diff --git a/include/net/net.h b/include/net/net.h
index 73e4c466e2..a69e382ba7 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -9,6 +9,11 @@
#include "migration/vmstate.h"
#include "qapi-types.h"
+#define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
+#define MAC_ARG(x) ((uint8_t *)(x))[0], ((uint8_t *)(x))[1], \
+ ((uint8_t *)(x))[2], ((uint8_t *)(x))[3], \
+ ((uint8_t *)(x))[4], ((uint8_t *)(x))[5]
+
#define MAX_QUEUE_NUM 1024
/* Maximum GSO packet size (64k) plus plenty of room for
@@ -57,6 +62,8 @@ typedef void (SetOffload)(NetClientState *, int, int, int, int, int);
typedef void (SetVnetHdrLen)(NetClientState *, int);
typedef int (SetVnetLE)(NetClientState *, bool);
typedef int (SetVnetBE)(NetClientState *, bool);
+typedef struct SocketReadState SocketReadState;
+typedef void (SocketReadStateFinalize)(SocketReadState *rs);
typedef struct NetClientInfo {
NetClientOptionsKind type;
@@ -102,6 +109,15 @@ typedef struct NICState {
bool peer_deleted;
} NICState;
+struct SocketReadState {
+ int state; /* 0 = getting length, 1 = getting data */
+ uint32_t index;
+ uint32_t packet_len;
+ uint8_t buf[NET_BUFSIZE];
+ SocketReadStateFinalize *finalize;
+};
+
+int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size);
char *qemu_mac_strdup_printf(const uint8_t *macaddr);
NetClientState *qemu_find_netdev(const char *id);
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
@@ -160,6 +176,8 @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
void print_net_client(Monitor *mon, NetClientState *nc);
void hmp_info_network(Monitor *mon, const QDict *qdict);
+void net_socket_rs_init(SocketReadState *rs,
+ SocketReadStateFinalize *finalize);
/* NIC info */
@@ -178,7 +196,6 @@ struct NICInfo {
extern int nb_nics;
extern NICInfo nd_table[MAX_NICS];
-extern int default_net;
extern const char *host_net_devices[];
/* from net.c */