gxemul: Update to 0.6.3 really
This commit is contained in:
parent
269f7c8073
commit
f557af58e9
18 changed files with 12 additions and 2614 deletions
|
@ -1,4 +1,4 @@
|
|||
@comment $NetBSD: PLIST,v 1.28 2019/08/23 13:13:49 ryoon Exp $
|
||||
@comment $NetBSD: PLIST,v 1.29 2021/02/22 14:03:35 ryoon Exp $
|
||||
bin/gxemul
|
||||
man/man1/gxemul.1
|
||||
share/doc/gxemul/20040504-ultrix45-boot1.png
|
||||
|
@ -112,6 +112,8 @@ share/doc/gxemul/20190612-netbsd-sgimips-2.png
|
|||
share/doc/gxemul/20190612-netbsd-sgimips-2_small.png
|
||||
share/doc/gxemul/20190616-netbsd-playstation2-userland-small.png
|
||||
share/doc/gxemul/20190616-netbsd-playstation2-userland.png
|
||||
share/doc/gxemul/20190715-sgi-o2-linux-small.png
|
||||
share/doc/gxemul/20190715-sgi-o2-linux.png
|
||||
share/doc/gxemul/Doxyfile
|
||||
share/doc/gxemul/HISTORY
|
||||
share/doc/gxemul/LICENSE
|
||||
|
@ -197,6 +199,10 @@ share/doc/gxemul/machines/machine_testmips-thumb.png
|
|||
share/doc/gxemul/misc.html
|
||||
share/doc/gxemul/model.png
|
||||
share/doc/gxemul/networking.html
|
||||
share/doc/gxemul/openbsd-luna88k-20210130-small.png
|
||||
share/doc/gxemul/openbsd-luna88k-20210130.png
|
||||
share/doc/gxemul/openbsd-luna88k-20210209-small.png
|
||||
share/doc/gxemul/openbsd-luna88k-20210209.png
|
||||
share/doc/gxemul/openbsd-pmax-20040710.png
|
||||
share/doc/gxemul/openbsd-pmax-20040710_small.png
|
||||
share/doc/gxemul/sgi-o2-real.jpg
|
||||
|
|
|
@ -1,22 +1,6 @@
|
|||
$NetBSD: distinfo,v 1.62 2021/01/16 16:49:36 skrll Exp $
|
||||
$NetBSD: distinfo,v 1.63 2021/02/22 14:03:35 ryoon Exp $
|
||||
|
||||
SHA1 (gxemul-0.6.2.tar.gz) = aabaeba783e70be952ab0056bf84d0f2b70c2155
|
||||
RMD160 (gxemul-0.6.2.tar.gz) = ccac73d82446f89792b1fc803bee623813f3aab2
|
||||
SHA512 (gxemul-0.6.2.tar.gz) = 4f389c509f9ecf39603ceed50e899e2bee285d3fefac9b3214076115ee71b5a7a68d1d92690b6debc8de5cf5f0303da83b3cc921a5c0b5eb4c7ad89baa730b59
|
||||
Size (gxemul-0.6.2.tar.gz) = 5897883 bytes
|
||||
SHA1 (patch-doc_networking.html) = dd7a1519a678196fd5a835317a32ba483630ece8
|
||||
SHA1 (patch-src_cpus_cpu__mips__instr__loadstore.cc) = 378c514ddf3b93279b2c479f21b77447d83d5afd
|
||||
SHA1 (patch-src_devices_dev_dec21143.cc) = 52f36741038c76a2dbafc7da6737e816aed5c9f9
|
||||
SHA1 (patch-src_devices_dev_ether.cc) = 00221e09530743e81faedcc75ee951fa853d0e2c
|
||||
SHA1 (patch-src_devices_dev_le.cc) = a728e8008a7a9f33aaf95811a33ebac2cb86e80e
|
||||
SHA1 (patch-src_devices_dev_rtl8139c.cc) = ee6dbba7c7c9c62c50493c476297ee5ac89d2b83
|
||||
SHA1 (patch-src_devices_dev_sgi_mec.cc) = 24b1259350faf60265df7958f0f680302f475e8e
|
||||
SHA1 (patch-src_devices_dev_sn.cc) = e939521be1630f51e7ddc67abe90980de38e8837
|
||||
SHA1 (patch-src_include_net.h) = 4d31fcefe384fcc9d68255825240c89b45acc92e
|
||||
SHA1 (patch-src_net_Makefile.skel) = 4738229a928b9cb5a2531dfc357297f91e9fdc09
|
||||
SHA1 (patch-src_net_net.cc) = 57397c9a8197ee25e7faa8c0733273014e3e0670
|
||||
SHA1 (patch-src_net_net_ether.cc) = ef7464dbb0812a9cb8d5be806db07cc19853fc1e
|
||||
SHA1 (patch-src_net_net_ip.cc) = f5615f3b347e9bdcd256fa4b5b1594473fd2e5e4
|
||||
SHA1 (patch-src_net_net_tap.cc) = f913b3efb51bc4a8080420988d5fc845e8a38f73
|
||||
SHA1 (patch-src_old_main_emul.cc) = 0b1106745e7c5d320e93f9f7775d8ced6109c089
|
||||
SHA1 (patch-src_old_main_emul_parse.cc) = 23048bc3a0a83fd189b3bbd4656ef0e1a2c23b99
|
||||
SHA1 (gxemul-0.6.3.tar.gz) = 433b26f34205924c4a0febd37ed9df3769da0111
|
||||
RMD160 (gxemul-0.6.3.tar.gz) = c155accc030fc63002be3a72aae1e6b33d027878
|
||||
SHA512 (gxemul-0.6.3.tar.gz) = 30bdb926ab180a44b277b734d5ff4d31b8f0a8b580c6976226f6ed1952cb50d16e18591591d6aeee243c5b3e9d27b71d24a3cba3906bcb332399f46a1ebd8ac5
|
||||
Size (gxemul-0.6.3.tar.gz) = 6024573 bytes
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
$NetBSD: patch-doc_networking.html,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Document tap(4)-based networking.
|
||||
|
||||
--- doc/networking.html.orig 2020-10-05 22:53:41.969487340 +0000
|
||||
+++ doc/networking.html 2020-10-05 22:54:17.309695478 +0000
|
||||
@@ -46,6 +46,7 @@ SUCH DAMAGE.
|
||||
<p><br>
|
||||
<ul>
|
||||
<li><a href="#intro">Introduction</a>
|
||||
+ <li><a href="#tap">Virtual Ethernet switch using a tap device</a>
|
||||
<li><a href="#multihost">Network across multiple hosts</a>
|
||||
<li><a href="#direct_example_1">Direct-access example 1: udp_snoop</a>
|
||||
</ul>
|
||||
@@ -60,9 +61,11 @@ SUCH DAMAGE.
|
||||
<a name="intro"></a>
|
||||
<h3>Introduction:</h3>
|
||||
|
||||
-<p>GXemul's current networking layer supports two modes:
|
||||
+<p>GXemul's current networking layer supports three modes:
|
||||
|
||||
<p><ol>
|
||||
+ <li>A vitual Ethernet switch built on top of a <i>tap</i> device.
|
||||
+ <p>
|
||||
<li>A NAT-like layer, which allows guest OSes to access the outside
|
||||
internet world (IPv4 only, so far). When only one machine is being
|
||||
emulated, the following default values apply to the guest OS:<pre>
|
||||
@@ -78,7 +81,7 @@ SUCH DAMAGE.
|
||||
ethernet packages from/to the emulator.
|
||||
</ol>
|
||||
|
||||
-<p><i>NOTE:</i> Both these modes have problems. The NAT-like layer is very
|
||||
+<p><i>NOTE:</i> The latter two modes have problems. The NAT-like layer is very
|
||||
"hackish" and was only meant as a proof-of-concept, to see if networking
|
||||
like this would work with e.g. NetBSD as a guest OS. (If you are
|
||||
interested in the technical details, and the reasons why NAT networking is
|
||||
@@ -120,6 +123,83 @@ href="machine_decstation.html#netbsdpmax
|
||||
|
||||
|
||||
|
||||
+<p><br>
|
||||
+<a name="tap"></a>
|
||||
+<h3>Virtual Ethernet switch using a <i>tap</i> device:</h3>
|
||||
+
|
||||
+<p>The simplest way to emulate a real Ethernet network is using a <i>tap</i>
|
||||
+device. In this mode, the emulator disables the simulated NAT and
|
||||
+direct-access machinery and internally treats all emulated NICs as if
|
||||
+they are on a single Ethernet switch. In this mode, packets destined for
|
||||
+the guest's specific MAC address as well as Ethernet multicast and broadcast
|
||||
+packets are send to the individual guest instances. Individual NIC
|
||||
+emulations may also apply their own multicast filtering; multcast filtering
|
||||
+is implemented for the DEC 21143 and Lance NICs.
|
||||
+
|
||||
+<p>The <i>tap</i> interface on the host can be thought of as an upstream
|
||||
+link on the virtual Ethernet switch. In addition to providing a "port"
|
||||
+for the host, the <i>tap</i> interface can be bridged to a physical Ethernet
|
||||
+port on the host, allowing the guests to access the host's connected LAN.
|
||||
+
|
||||
+<p>Networking services such as DHCP and DNS must be provided either by
|
||||
+the host or by the host's connected LAN.
|
||||
+
|
||||
+<p>Support for the <i>tap</i> device was developed on NetBSD, but should
|
||||
+also work on FreeBSD, OpenBSD, and Linux hosts.
|
||||
+
|
||||
+<p>Here is a simple example:
|
||||
+
|
||||
+<p><pre>
|
||||
+<font color="#2020cf">! Configuration file for
|
||||
+! virtual Ethernet switch networking
|
||||
+! using a tap device.</font>
|
||||
+
|
||||
+<b>net(</b>
|
||||
+ <b>tapdev(</b><font color="#ff003f">"/dev/tap0"</font><b>)</b>
|
||||
+<b>)</b>
|
||||
+<b>machine(</b>
|
||||
+ <b>name(<font color="#ff003f">"guest machine"</font>)</b>
|
||||
+
|
||||
+ <b>type(<font color="#ff003f">"dec"</font>)</b>
|
||||
+ <b>subtype(<font color="#ff003f">"5000/200"</font>)</b>
|
||||
+
|
||||
+ <font color="#2020cf">! Add a disk, etc.</font>
|
||||
+<b>)</b>
|
||||
+</pre>
|
||||
+
|
||||
+<p>Before starting the emulator, you will need to create the <i>tap</i>
|
||||
+interface on the host. Here is an example for NetBSD:
|
||||
+
|
||||
+<p><pre>
|
||||
+<b>#ifconfig tap0 create up</b>
|
||||
+</pre>
|
||||
+
|
||||
+<p>If you wish to simply network the host and the guests together, then
|
||||
+simply assign an IP address to the <i>tap</i> interface on the host:
|
||||
+
|
||||
+<p><pre>
|
||||
+<b># ifconfig tap0 10.0.0.254</b>
|
||||
+</pre>
|
||||
+
|
||||
+<p>You can now run a DHCP server on the host for the guests, or you can
|
||||
+configure the guests manually.
|
||||
+
|
||||
+<p>If instead you would like to bridge to the host's connected LAN,
|
||||
+Here is an example for NetBSD:
|
||||
+
|
||||
+<p><pre>
|
||||
+<b># ifconfig bridge0 create up</b>
|
||||
+<b># brconfig add tap0 add wm0</b>
|
||||
+</pre>
|
||||
+
|
||||
+<p>Although it <i>is</i> possible to have more than one machine per
|
||||
+configuration file, I strongly recommend against it. Please use one
|
||||
+configuration file for one emulated machine. Each configuration file
|
||||
+must have a unique <i>tap</i> instance, and machines in separate
|
||||
+configuration files must use bridged <i>tap</i> devices if they wish
|
||||
+to communicate with each other as if on the same LAN.
|
||||
+
|
||||
+
|
||||
|
||||
<p><br>
|
||||
<a name="multihost"></a>
|
|
@ -1,44 +0,0 @@
|
|||
$NetBSD: patch-src_cpus_cpu__mips__instr__loadstore.cc,v 1.1 2021/01/16 16:49:36 skrll Exp $
|
||||
|
||||
--- src/cpus/cpu_mips_instr_loadstore.cc.orig 2021-01-16 16:33:52.314709654 +0000
|
||||
+++ src/cpus/cpu_mips_instr_loadstore.cc
|
||||
@@ -58,6 +58,30 @@ void LS_GENERIC_N(struct cpu *cpu, struc
|
||||
/* Check alignment: */
|
||||
if (addr & (LS_SIZE - 1)) {
|
||||
#if 1
|
||||
+ uint64_t vaddr_vpn2=0, vaddr_asid=0;
|
||||
+
|
||||
+ int exc_model = cpu->cd.mips.cpu_type.exc_model;
|
||||
+ struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
|
||||
+
|
||||
+ if (exc_model == EXC3K) {
|
||||
+ vaddr_asid = (cp0->reg[COP0_ENTRYHI] &
|
||||
+ R2K3K_ENTRYHI_ASID_MASK) >>
|
||||
+ R2K3K_ENTRYHI_ASID_SHIFT;
|
||||
+ vaddr_vpn2 = (addr & R2K3K_ENTRYHI_VPN_MASK) >>
|
||||
+ R2K3K_ENTRYHI_VPN_SHIFT;
|
||||
+ } else {
|
||||
+ vaddr_asid = cp0->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
|
||||
+
|
||||
+ if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
|
||||
+ vaddr_vpn2 = (addr &
|
||||
+ ENTRYHI_VPN2_MASK_R10K) >>
|
||||
+ ENTRYHI_VPN2_SHIFT;
|
||||
+ } else {
|
||||
+ vaddr_vpn2 = (addr & ENTRYHI_VPN2_MASK) >>
|
||||
+ ENTRYHI_VPN2_SHIFT;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Cause an address alignment exception: */
|
||||
mips_cpu_exception(cpu,
|
||||
#ifdef LS_LOAD
|
||||
@@ -65,7 +89,7 @@ void LS_GENERIC_N(struct cpu *cpu, struc
|
||||
#else
|
||||
EXCEPTION_ADES,
|
||||
#endif
|
||||
- 0, addr, 0, 0, 0, 0);
|
||||
+ 0, addr, 0, vaddr_vpn2, vaddr_asid, 0);
|
||||
#else
|
||||
fatal("{ mips dyntrans alignment exception, size = %i,"
|
||||
" addr = %016"PRIx64", pc = %016"PRIx64" }\n", LS_SIZE,
|
|
@ -1,890 +0,0 @@
|
|||
$NetBSD: patch-src_devices_dev_dec21143.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
- Add support for tap(4)-based networking.
|
||||
- Process the setup packet, and implement all of the Tulip receive
|
||||
filtering modes.
|
||||
- Add ugly hack to deal with PCI vs. CPU views of main memory differences
|
||||
between systems.
|
||||
|
||||
--- src/devices/dev_dec21143.cc.orig 2020-10-05 22:54:55.903897678 +0000
|
||||
+++ src/devices/dev_dec21143.cc 2020-10-05 22:55:15.711704852 +0000
|
||||
@@ -45,8 +45,6 @@
|
||||
* o) Handle _writes_ to MII registers.
|
||||
* o) Make it work with modern Linux kernels (as a guest OS).
|
||||
* o) Endianness for descriptors? If necessary.
|
||||
- * o) Actually handle the "Setup" packet.
|
||||
- * o) MAC filtering on incoming packets.
|
||||
* o) Don't hardcode as many values.
|
||||
*/
|
||||
|
||||
@@ -76,16 +74,15 @@
|
||||
#define ROM_WIDTH 6
|
||||
|
||||
struct dec21143_data {
|
||||
+ /* NIC common data */
|
||||
+ struct nic_data nic;
|
||||
+
|
||||
struct interrupt irq;
|
||||
int irq_was_asserted;
|
||||
|
||||
/* PCI: */
|
||||
int pci_little_endian;
|
||||
|
||||
- /* Ethernet address, and a network which we are connected to: */
|
||||
- uint8_t mac[6];
|
||||
- struct net *net;
|
||||
-
|
||||
/* SROM emulation: */
|
||||
uint8_t srom[1 << (ROM_WIDTH + 1)];
|
||||
int srom_curbit;
|
||||
@@ -105,19 +102,66 @@ struct dec21143_data {
|
||||
uint32_t reg[N_REGS];
|
||||
|
||||
/* Internal TX state: */
|
||||
- uint64_t cur_tx_addr;
|
||||
+ uint32_t cur_tx_addr;
|
||||
unsigned char *cur_tx_buf;
|
||||
int cur_tx_buf_len;
|
||||
int tx_idling;
|
||||
int tx_idling_threshold;
|
||||
|
||||
/* Internal RX state: */
|
||||
- uint64_t cur_rx_addr;
|
||||
+ uint32_t cur_rx_addr;
|
||||
unsigned char *cur_rx_buf;
|
||||
int cur_rx_buf_len;
|
||||
int cur_rx_offset;
|
||||
+
|
||||
+ /*
|
||||
+ * Receive filter information. We keep our own copy of
|
||||
+ * the promiscuous flag because to implement some of the
|
||||
+ * filtering modes, we need to tell the network layer that
|
||||
+ * we want all packets.
|
||||
+ */
|
||||
+ int (*drop_packet)(struct net *, struct dec21143_data *);
|
||||
+ int allmulti;
|
||||
+ int promiscuous;
|
||||
+ int filter_needs_promiscuous;
|
||||
+ uint8_t perfect_filter[6 * TULIP_MAXADDRS];
|
||||
+
|
||||
+ /* Only 16 bits are used per filter word. */
|
||||
+#define MCHASH_NWORDS (TULIP_MCHASHSIZE / 16)
|
||||
+ uint32_t hash_filter[MCHASH_NWORDS];
|
||||
+ int hash_filter_saturated;
|
||||
+
|
||||
+ /*
|
||||
+ * XXX XXX XXX
|
||||
+ * XXX UGLY HACK. Need a proper way to deal with
|
||||
+ * XXX different PCI vs. CPU views of RAM.
|
||||
+ * XXX XXX XXX
|
||||
+ */
|
||||
+ uint32_t xxx_dma_to_phys_mask;
|
||||
};
|
||||
|
||||
+/* XXX This is an UGLY hack. */
|
||||
+static uint64_t dma_to_phys(const struct dec21143_data *d, uint32_t dma_addr)
|
||||
+{
|
||||
+ return dma_addr & d->xxx_dma_to_phys_mask;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static inline uint32_t load_le32(const uint8_t *buf)
|
||||
+{
|
||||
+ return buf[0] | ((uint32_t)buf[1] << 8) |
|
||||
+ ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static inline void store_le32(uint8_t *buf, uint32_t val)
|
||||
+{
|
||||
+ buf[0] = (uint8_t)val;
|
||||
+ buf[1] = (uint8_t)(val >> 8);
|
||||
+ buf[2] = (uint8_t)(val >> 16);
|
||||
+ buf[3] = (uint8_t)(val >> 24);
|
||||
+}
|
||||
+
|
||||
|
||||
/* Internal states during MII data stream decode: */
|
||||
#define MII_STATE_RESET 0
|
||||
@@ -130,6 +174,171 @@ struct dec21143_data {
|
||||
|
||||
|
||||
/*
|
||||
+ * The 21143 has multiple address matching modes:
|
||||
+ *
|
||||
+ * - Perfect Filtering: The chip interprets the descriptor buffer
|
||||
+ * as a table of 16 MAC addresses that it should match. The
|
||||
+ * station address and broadcast must be included in the list.
|
||||
+ *
|
||||
+ * - Hash Perfect Filtering: The chip interprets the descriptor buffer
|
||||
+ * as a 512-bit hash table plus one perfect filter match. Multicast
|
||||
+ * addresses only are matched against the hash table.
|
||||
+ *
|
||||
+ * - Inverse Filtering: Like Perfect Filtering, but the table is
|
||||
+ * addresses NOT to match.
|
||||
+ *
|
||||
+ * - Hash-only Filtering: Like Hash Perfect, except without the Perfect.
|
||||
+ * All addresses are matched against the hash table.
|
||||
+ *
|
||||
+ * The mode seleted by the TDCTL descriptor field is reflected in 3
|
||||
+ * read-only bits in the OPMODE register.
|
||||
+ *
|
||||
+ * We implement all 4 (NetBSD, at least, is known to use Perfect and
|
||||
+ * Hash Perfect on the 21143; it also uses Hash-only on the 21140).
|
||||
+ */
|
||||
+
|
||||
+#define TDCTL_Tx_FT_MASK (TDCTL_Tx_FT1|TDCTL_Tx_FT0)
|
||||
+
|
||||
+#define dec21143_mchash(addr) \
|
||||
+ (net_ether_crc32_le((addr), 6) & (TULIP_MCHASHSIZE - 1))
|
||||
+
|
||||
+static int dec21143_drop_packet_perfect(struct net *net,
|
||||
+ struct dec21143_data *d)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < TULIP_MAXADDRS; i++) {
|
||||
+ if (net_ether_eq(d->cur_rx_buf, &d->perfect_filter[6 * i])) {
|
||||
+ /* Match! */
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int dec21143_drop_packet_hashperfect(struct net *net,
|
||||
+ struct dec21143_data *d)
|
||||
+{
|
||||
+
|
||||
+ /*
|
||||
+ * In this mode, we have the network layer match our station
|
||||
+ * address, and we reflect the true promiscuous status there
|
||||
+ * as well. This means that if it's not a multicast address,
|
||||
+ * then it's already been sufficiently matched.
|
||||
+ */
|
||||
+ if (! net_ether_multicast(d->cur_rx_buf))
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Note that the broadcast address is also checked against
|
||||
+ * the hash table in this mode!
|
||||
+ */
|
||||
+
|
||||
+ const uint32_t hash = dec21143_mchash(d->cur_rx_buf);
|
||||
+ if (d->hash_filter[hash >> 4] & (1U << (hash & 0xf))) {
|
||||
+ /* Match! */
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int dec21143_drop_packet_inverse(struct net *net,
|
||||
+ struct dec21143_data *d)
|
||||
+{
|
||||
+ return !dec21143_drop_packet_perfect(net, d);
|
||||
+}
|
||||
+
|
||||
+static int dec21143_drop_packet_hashonly(struct net *net,
|
||||
+ struct dec21143_data *d)
|
||||
+{
|
||||
+ const uint32_t hash = dec21143_mchash(d->cur_rx_buf);
|
||||
+ if (d->hash_filter[hash >> 4] & (1U << (hash & 0xf))) {
|
||||
+ /* Match! */
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * dec21143_rx_drop_packet():
|
||||
+ *
|
||||
+ * Implement the logic to determine if we should drop a packet
|
||||
+ * before paassing it to the guest. Returns 1 if the packet
|
||||
+ * was dropped.
|
||||
+ */
|
||||
+static int dec21143_rx_drop_packet(struct net *net, struct dec21143_data *d)
|
||||
+{
|
||||
+ /* Only implement filtering if using a tap device. */
|
||||
+ if (net->tapdev == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * We might have told the network layer that we're promiscuous
|
||||
+ * due to the chosen filtering mode, so check the truth here.
|
||||
+ */
|
||||
+ if (d->promiscuous)
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * If the guest wants all multicast (either all the bits are
|
||||
+ * set or the OPMODE_PM bit is set), then check to see if we
|
||||
+ * can short-circuit the checks.
|
||||
+ */
|
||||
+ if (d->allmulti && net_ether_multicast(d->cur_rx_buf))
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Note that if we haven't gotten a setup packet yet, then
|
||||
+ * d->drop_packet will be NULL. If this happens, we always
|
||||
+ * drop. This is akin to the real hardware defaulting to
|
||||
+ * Perfect filtering mode but not having any valid addresses
|
||||
+ * in the list to match against.
|
||||
+ */
|
||||
+ if (d->drop_packet == NULL || d->drop_packet(net, d)) {
|
||||
+ /* Not for us; drop the packet. */
|
||||
+ free(d->cur_rx_buf);
|
||||
+ d->cur_rx_buf = NULL;
|
||||
+ d->cur_rx_buf_len = 0;
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * dec21143_update_rx_mode():
|
||||
+ *
|
||||
+ * Update promiscuous / allmulti indicators based on OPMODE
|
||||
+ * and filter state.
|
||||
+ */
|
||||
+static void dec21143_update_rx_mode(struct dec21143_data *d)
|
||||
+{
|
||||
+ int opmode_pr = (d->reg[CSR_OPMODE / 8] & OPMODE_PR) != 0;
|
||||
+ int opmode_pm = (d->reg[CSR_OPMODE / 8] & OPMODE_PM) != 0;
|
||||
+
|
||||
+ debug("[ dec21143 rx mode: opmode_pr = %d ]\n",
|
||||
+ opmode_pr);
|
||||
+ debug("[ dec21143 rx mode: filter_needs_promiscuous = %d ]\n",
|
||||
+ d->filter_needs_promiscuous);
|
||||
+ debug("[ dec21143 rx mode: opmode_pm = %d ]\n",
|
||||
+ opmode_pm);
|
||||
+ debug("[ dec21143 rx mode: filter_saturated = %d ]\n",
|
||||
+ d->hash_filter_saturated);
|
||||
+
|
||||
+ d->promiscuous = opmode_pr;
|
||||
+ d->nic.promiscuous_mode =
|
||||
+ d->promiscuous || d->filter_needs_promiscuous;
|
||||
+
|
||||
+ d->allmulti = opmode_pm || d->hash_filter_saturated;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
* dec21143_rx():
|
||||
*
|
||||
* Receive a packet. (If there is no current packet, then check for newly
|
||||
@@ -138,20 +347,23 @@ struct dec21143_data {
|
||||
*/
|
||||
int dec21143_rx(struct cpu *cpu, struct dec21143_data *d)
|
||||
{
|
||||
- uint64_t addr = d->cur_rx_addr, bufaddr;
|
||||
+ uint32_t addr = d->cur_rx_addr, bufaddr;
|
||||
unsigned char descr[16];
|
||||
uint32_t rdes0, rdes1, rdes2, rdes3;
|
||||
int bufsize, buf1_size, buf2_size, i, writeback_len = 4, to_xfer;
|
||||
|
||||
/* No current packet? Then check for new ones. */
|
||||
- if (d->cur_rx_buf == NULL) {
|
||||
+ while (d->cur_rx_buf == NULL) {
|
||||
/* Nothing available? Then abort. */
|
||||
- if (!net_ethernet_rx_avail(d->net, d))
|
||||
+ if (!net_ethernet_rx_avail(d->nic.net, &d->nic))
|
||||
return 0;
|
||||
|
||||
/* Get the next packet into our buffer: */
|
||||
- net_ethernet_rx(d->net, d, &d->cur_rx_buf,
|
||||
- &d->cur_rx_buf_len);
|
||||
+ net_ethernet_rx(d->nic.net, &d->nic,
|
||||
+ &d->cur_rx_buf, &d->cur_rx_buf_len);
|
||||
+
|
||||
+ if (dec21143_rx_drop_packet(d->nic.net, d))
|
||||
+ continue;
|
||||
|
||||
/* Append a 4 byte CRC: */
|
||||
d->cur_rx_buf_len += 4;
|
||||
@@ -165,15 +377,14 @@ int dec21143_rx(struct cpu *cpu, struct
|
||||
}
|
||||
|
||||
/* fatal("{ dec21143_rx: base = 0x%08x }\n", (int)addr); */
|
||||
- addr &= 0x7fffffff;
|
||||
|
||||
- if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),
|
||||
- MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
|
||||
+ if (!cpu->memory_rw(cpu, cpu->mem, dma_to_phys(d, addr),
|
||||
+ descr, sizeof(uint32_t), MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
|
||||
fatal("[ dec21143_rx: memory_rw failed! ]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
- rdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);
|
||||
+ rdes0 = load_le32(&descr[0]);
|
||||
|
||||
/* Only use descriptors owned by the 21143: */
|
||||
if (!(rdes0 & TDSTAT_OWN)) {
|
||||
@@ -181,16 +392,17 @@ int dec21143_rx(struct cpu *cpu, struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (!cpu->memory_rw(cpu, cpu->mem, addr + sizeof(uint32_t), descr +
|
||||
- sizeof(uint32_t), sizeof(uint32_t) * 3, MEM_READ, PHYSICAL |
|
||||
- NO_EXCEPTIONS)) {
|
||||
+ if (!cpu->memory_rw(cpu, cpu->mem,
|
||||
+ dma_to_phys(d, addr + sizeof(uint32_t)),
|
||||
+ descr + sizeof(uint32_t), sizeof(uint32_t) * 3, MEM_READ,
|
||||
+ PHYSICAL | NO_EXCEPTIONS)) {
|
||||
fatal("[ dec21143_rx: memory_rw failed! ]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
- rdes1 = descr[4] + (descr[5]<<8) + (descr[6]<<16) + (descr[7]<<24);
|
||||
- rdes2 = descr[8] + (descr[9]<<8) + (descr[10]<<16) + (descr[11]<<24);
|
||||
- rdes3 = descr[12] + (descr[13]<<8) + (descr[14]<<16) + (descr[15]<<24);
|
||||
+ rdes1 = load_le32(&descr[4]);
|
||||
+ rdes2 = load_le32(&descr[8]);
|
||||
+ rdes3 = load_le32(&descr[12]);
|
||||
|
||||
buf1_size = rdes1 & TDCTL_SIZE1;
|
||||
buf2_size = (rdes1 & TDCTL_SIZE2) >> TDCTL_SIZE2_SHIFT;
|
||||
@@ -210,7 +422,6 @@ int dec21143_rx(struct cpu *cpu, struct
|
||||
|
||||
debug("{ RX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
|
||||
(long long)addr, rdes0, rdes1, rdes2, rdes3, bufsize, (int)bufaddr);
|
||||
- bufaddr &= 0x7fffffff;
|
||||
|
||||
/* Turn off all status bits, and give up ownership: */
|
||||
rdes0 = 0x00000000;
|
||||
@@ -221,7 +432,7 @@ int dec21143_rx(struct cpu *cpu, struct
|
||||
|
||||
/* DMA bytes from the packet into emulated physical memory: */
|
||||
for (i=0; i<to_xfer; i++) {
|
||||
- cpu->memory_rw(cpu, cpu->mem, bufaddr + i,
|
||||
+ cpu->memory_rw(cpu, cpu->mem, dma_to_phys(d, bufaddr + i),
|
||||
d->cur_rx_buf + d->cur_rx_offset + i, 1, MEM_WRITE,
|
||||
PHYSICAL | NO_EXCEPTIONS);
|
||||
/* fatal(" %02x", d->cur_rx_buf[d->cur_rx_offset + i]); */
|
||||
@@ -253,19 +464,16 @@ int dec21143_rx(struct cpu *cpu, struct
|
||||
}
|
||||
|
||||
/* Descriptor writeback: */
|
||||
- descr[ 0] = rdes0; descr[ 1] = rdes0 >> 8;
|
||||
- descr[ 2] = rdes0 >> 16; descr[ 3] = rdes0 >> 24;
|
||||
+ store_le32(&descr[0], rdes0);
|
||||
if (writeback_len > 1) {
|
||||
- descr[ 4] = rdes1; descr[ 5] = rdes1 >> 8;
|
||||
- descr[ 6] = rdes1 >> 16; descr[ 7] = rdes1 >> 24;
|
||||
- descr[ 8] = rdes2; descr[ 9] = rdes2 >> 8;
|
||||
- descr[10] = rdes2 >> 16; descr[11] = rdes2 >> 24;
|
||||
- descr[12] = rdes3; descr[13] = rdes3 >> 8;
|
||||
- descr[14] = rdes3 >> 16; descr[15] = rdes3 >> 24;
|
||||
+ store_le32(&descr[4], rdes1);
|
||||
+ store_le32(&descr[8], rdes2);
|
||||
+ store_le32(&descr[12], rdes3);
|
||||
}
|
||||
|
||||
- if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t)
|
||||
- * writeback_len, MEM_WRITE, PHYSICAL | NO_EXCEPTIONS)) {
|
||||
+ if (!cpu->memory_rw(cpu, cpu->mem, dma_to_phys(d, addr), descr,
|
||||
+ sizeof(uint32_t) * writeback_len, MEM_WRITE,
|
||||
+ PHYSICAL | NO_EXCEPTIONS)) {
|
||||
fatal("[ dec21143_rx: memory_rw failed! ]\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -275,6 +483,178 @@ int dec21143_rx(struct cpu *cpu, struct
|
||||
|
||||
|
||||
/*
|
||||
+ * dec21143_setup_copy_enaddr():
|
||||
+ *
|
||||
+ * Copy an Ethernet address out of the setup packet.
|
||||
+ */
|
||||
+static void dec21143_setup_copy_enaddr(uint8_t *enaddr,
|
||||
+ const uint32_t *setup_packet)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < 3; i++) {
|
||||
+ enaddr[i*2 ] = (uint8_t)setup_packet[i];
|
||||
+ enaddr[i*2 + 1] = (uint8_t)(setup_packet[i] >> 8);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * dec21143_setup_perfect():
|
||||
+ *
|
||||
+ * Setup perfect filtering mode.
|
||||
+ */
|
||||
+static void dec21143_setup_perfect(struct dec21143_data *d,
|
||||
+ const uint32_t *setup_packet)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < TULIP_MAXADDRS; i++) {
|
||||
+ dec21143_setup_copy_enaddr(&d->perfect_filter[i * 6],
|
||||
+ &setup_packet[i * 3]);
|
||||
+ debug("dec21143 PERFECT[%d] %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
+ i,
|
||||
+ d->perfect_filter[i*6 + 0],
|
||||
+ d->perfect_filter[i*6 + 1],
|
||||
+ d->perfect_filter[i*6 + 2],
|
||||
+ d->perfect_filter[i*6 + 3],
|
||||
+ d->perfect_filter[i*6 + 4],
|
||||
+ d->perfect_filter[i*6 + 5]);
|
||||
+ }
|
||||
+
|
||||
+ d->drop_packet = dec21143_drop_packet_perfect;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * dec21143_setup_hashperfect():
|
||||
+ *
|
||||
+ * Setup hash-perfect filtering mode.
|
||||
+ */
|
||||
+static void dec21143_setup_hashperfect(struct dec21143_data *d,
|
||||
+ const uint32_t *setup_packet)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ debug("dec21143 HASHPERFECT:");
|
||||
+ for (i = 0; i < MCHASH_NWORDS; i++) {
|
||||
+ if ((i % 8) == 0)
|
||||
+ debug("\n\t");
|
||||
+ debug(" %04x", setup_packet[i]);
|
||||
+ d->hash_filter[i] = setup_packet[i];
|
||||
+ d->hash_filter_saturated |= (d->hash_filter[i] == 0xffff);
|
||||
+ }
|
||||
+ debug("\n");
|
||||
+
|
||||
+ dec21143_setup_copy_enaddr(d->nic.mac_address, &setup_packet[39]);
|
||||
+ debug("dec21143 HASHPERFECT %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
+ d->nic.mac_address[0],
|
||||
+ d->nic.mac_address[1],
|
||||
+ d->nic.mac_address[2],
|
||||
+ d->nic.mac_address[3],
|
||||
+ d->nic.mac_address[4],
|
||||
+ d->nic.mac_address[5]);
|
||||
+
|
||||
+ d->filter_needs_promiscuous = 0;
|
||||
+ d->drop_packet = dec21143_drop_packet_hashperfect;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * dec21143_setup_inverse():
|
||||
+ *
|
||||
+ * Setup inverse filtering mode.
|
||||
+ */
|
||||
+static void dec21143_setup_inverse(struct dec21143_data *d,
|
||||
+ const uint32_t *setup_packet)
|
||||
+{
|
||||
+ dec21143_setup_perfect(d, setup_packet);
|
||||
+ debug("dec21143 INVERSE ^^^^\n");
|
||||
+ d->drop_packet = dec21143_drop_packet_inverse;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * dec21143_setup_hashonly():
|
||||
+ *
|
||||
+ * Setup hash-only filtering mode.
|
||||
+ */
|
||||
+static void dec21143_setup_hashonly(struct dec21143_data *d,
|
||||
+ const uint32_t *setup_packet)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ debug("dec21143 HASHONLY:");
|
||||
+ for (i = 0; i < MCHASH_NWORDS; i++) {
|
||||
+ if ((i % 8) == 0)
|
||||
+ fatal("\n\t");
|
||||
+ debug(" %04x", setup_packet[i]);
|
||||
+ d->hash_filter[i] = setup_packet[i];
|
||||
+ d->hash_filter_saturated |= (d->hash_filter[i] == 0xffff);
|
||||
+ }
|
||||
+ debug("\n");
|
||||
+
|
||||
+ d->drop_packet = dec21143_drop_packet_hashonly;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * dec21143_process_setup_packet():
|
||||
+ *
|
||||
+ * Process the address filter setup packet.
|
||||
+ */
|
||||
+static void dec21143_process_setup_packet(struct cpu *cpu,
|
||||
+ struct dec21143_data *d, uint32_t tdctl, uint32_t bufaddr)
|
||||
+{
|
||||
+ uint32_t setup_packet[TULIP_SETUP_PACKET_LEN / sizeof(uint32_t)];
|
||||
+ uint8_t *cp = (uint8_t *)setup_packet;
|
||||
+ uint32_t tmp;
|
||||
+ int i;
|
||||
+
|
||||
+ if (!cpu->memory_rw(cpu, cpu->mem, dma_to_phys(d, bufaddr), cp,
|
||||
+ TULIP_SETUP_PACKET_LEN, MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
|
||||
+ fatal("[ dec21143_process_setup_packet: memory_rw failed! ]\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Ensure host order of each word. */
|
||||
+ for (i = 0; i < TULIP_SETUP_PACKET_LEN; i += sizeof(uint32_t)) {
|
||||
+ tmp = load_le32(&cp[i]);
|
||||
+ setup_packet[i / sizeof(uint32_t)] = tmp;
|
||||
+ }
|
||||
+
|
||||
+ /* Defaults. */
|
||||
+ d->hash_filter_saturated = 0;
|
||||
+ d->filter_needs_promiscuous = 1;
|
||||
+
|
||||
+ d->reg[CSR_OPMODE / 8] &= ~(OPMODE_HP | OPMODE_HO | OPMODE_IF);
|
||||
+
|
||||
+ switch (tdctl & TDCTL_Tx_FT_MASK) {
|
||||
+ case TDCTL_Tx_FT_PERFECT:
|
||||
+ dec21143_setup_perfect(d, setup_packet);
|
||||
+ break;
|
||||
+
|
||||
+ case TDCTL_Tx_FT_HASH:
|
||||
+ dec21143_setup_hashperfect(d, setup_packet);
|
||||
+ d->reg[CSR_OPMODE / 8] |= OPMODE_HP;
|
||||
+ break;
|
||||
+
|
||||
+ case TDCTL_Tx_FT_INVERSE:
|
||||
+ dec21143_setup_inverse(d, setup_packet);
|
||||
+ d->reg[CSR_OPMODE / 8] |= OPMODE_IF;
|
||||
+ break;
|
||||
+
|
||||
+ case TDCTL_Tx_FT_HASHONLY:
|
||||
+ dec21143_setup_hashonly(d, setup_packet);
|
||||
+ d->reg[CSR_OPMODE / 8] |= OPMODE_HO;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ dec21143_update_rx_mode(d);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
* dec21143_tx():
|
||||
*
|
||||
* Transmit a packet, if the guest OS has marked a descriptor as containing
|
||||
@@ -282,20 +662,18 @@ int dec21143_rx(struct cpu *cpu, struct
|
||||
*/
|
||||
int dec21143_tx(struct cpu *cpu, struct dec21143_data *d)
|
||||
{
|
||||
- uint64_t addr = d->cur_tx_addr, bufaddr;
|
||||
+ uint32_t addr = d->cur_tx_addr, bufaddr;
|
||||
unsigned char descr[16];
|
||||
uint32_t tdes0, tdes1, tdes2, tdes3;
|
||||
int bufsize, buf1_size, buf2_size, i;
|
||||
|
||||
- addr &= 0x7fffffff;
|
||||
-
|
||||
- if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),
|
||||
- MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
|
||||
+ if (!cpu->memory_rw(cpu, cpu->mem, dma_to_phys(d, addr), descr,
|
||||
+ sizeof(uint32_t), MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
|
||||
fatal("[ dec21143_tx: memory_rw failed! ]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
- tdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);
|
||||
+ tdes0 = load_le32(&descr[0]);
|
||||
|
||||
/* fatal("{ dec21143_tx: base=0x%08x, tdes0=0x%08x }\n",
|
||||
(int)addr, (int)tdes0); */
|
||||
@@ -310,16 +688,17 @@ int dec21143_tx(struct cpu *cpu, struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (!cpu->memory_rw(cpu, cpu->mem, addr + sizeof(uint32_t), descr +
|
||||
- sizeof(uint32_t), sizeof(uint32_t) * 3, MEM_READ, PHYSICAL |
|
||||
- NO_EXCEPTIONS)) {
|
||||
+ if (!cpu->memory_rw(cpu, cpu->mem,
|
||||
+ dma_to_phys(d, addr + sizeof(uint32_t)),
|
||||
+ descr + sizeof(uint32_t), sizeof(uint32_t) * 3, MEM_READ,
|
||||
+ PHYSICAL | NO_EXCEPTIONS)) {
|
||||
fatal("[ dec21143_tx: memory_rw failed! ]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
- tdes1 = descr[4] + (descr[5]<<8) + (descr[6]<<16) + (descr[7]<<24);
|
||||
- tdes2 = descr[8] + (descr[9]<<8) + (descr[10]<<16) + (descr[11]<<24);
|
||||
- tdes3 = descr[12] + (descr[13]<<8) + (descr[14]<<16) + (descr[15]<<24);
|
||||
+ tdes1 = load_le32(&descr[4]);
|
||||
+ tdes2 = load_le32(&descr[8]);
|
||||
+ tdes3 = load_le32(&descr[12]);
|
||||
|
||||
buf1_size = tdes1 & TDCTL_SIZE1;
|
||||
buf2_size = (tdes1 & TDCTL_SIZE2) >> TDCTL_SIZE2_SHIFT;
|
||||
@@ -338,10 +717,9 @@ int dec21143_tx(struct cpu *cpu, struct
|
||||
}
|
||||
|
||||
/*
|
||||
- fatal("{ TX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
|
||||
- (long long)addr, tdes0, tdes1, tdes2, tdes3, bufsize, (int)bufaddr);
|
||||
+ fatal("{ TX (%x): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
|
||||
+ addr, tdes0, tdes1, tdes2, tdes3, bufsize, bufaddr);
|
||||
*/
|
||||
- bufaddr &= 0x7fffffff;
|
||||
|
||||
/* Assume no error: */
|
||||
tdes0 &= ~ (TDSTAT_Tx_UF | TDSTAT_Tx_EC | TDSTAT_Tx_LC
|
||||
@@ -350,13 +728,13 @@ int dec21143_tx(struct cpu *cpu, struct
|
||||
if (tdes1 & TDCTL_Tx_SET) {
|
||||
/*
|
||||
* Setup Packet.
|
||||
- *
|
||||
- * TODO. For now, just ignore it, and pretend it worked.
|
||||
*/
|
||||
/* fatal("{ TX: setup packet }\n"); */
|
||||
- if (bufsize != 192)
|
||||
+ if (bufsize != TULIP_SETUP_PACKET_LEN)
|
||||
fatal("[ dec21143: setup packet len = %i, should be"
|
||||
- " 192! ]\n", (int)bufsize);
|
||||
+ " %d! ]\n", (int)bufsize, TULIP_SETUP_PACKET_LEN);
|
||||
+ else
|
||||
+ dec21143_process_setup_packet(cpu, d, tdes1, bufaddr);
|
||||
if (tdes1 & TDCTL_Tx_IC)
|
||||
d->reg[CSR_STATUS/8] |= STATUS_TI;
|
||||
/* New descriptor values, according to the docs: */
|
||||
@@ -388,7 +766,8 @@ int dec21143_tx(struct cpu *cpu, struct
|
||||
|
||||
/* "DMA" data from emulated physical memory into the buf: */
|
||||
for (i=0; i<bufsize; i++) {
|
||||
- cpu->memory_rw(cpu, cpu->mem, bufaddr + i,
|
||||
+ cpu->memory_rw(cpu, cpu->mem,
|
||||
+ dma_to_phys(d, bufaddr + i),
|
||||
d->cur_tx_buf + d->cur_tx_buf_len + i, 1, MEM_READ,
|
||||
PHYSICAL | NO_EXCEPTIONS);
|
||||
/* fatal(" %02x", d->cur_tx_buf[
|
||||
@@ -400,9 +779,9 @@ int dec21143_tx(struct cpu *cpu, struct
|
||||
/* Last segment? Then actually transmit it: */
|
||||
if (tdes1 & TDCTL_Tx_LS) {
|
||||
/* fatal("{ TX: data frame complete. }\n"); */
|
||||
- if (d->net != NULL) {
|
||||
- net_ethernet_tx(d->net, d, d->cur_tx_buf,
|
||||
- d->cur_tx_buf_len);
|
||||
+ if (d->nic.net != NULL) {
|
||||
+ net_ethernet_tx(d->nic.net, &d->nic,
|
||||
+ d->cur_tx_buf, d->cur_tx_buf_len);
|
||||
} else {
|
||||
static int warn = 0;
|
||||
if (!warn)
|
||||
@@ -430,17 +809,13 @@ int dec21143_tx(struct cpu *cpu, struct
|
||||
tdes0 |= TDSTAT_ES;
|
||||
|
||||
/* Descriptor writeback: */
|
||||
- descr[ 0] = tdes0; descr[ 1] = tdes0 >> 8;
|
||||
- descr[ 2] = tdes0 >> 16; descr[ 3] = tdes0 >> 24;
|
||||
- descr[ 4] = tdes1; descr[ 5] = tdes1 >> 8;
|
||||
- descr[ 6] = tdes1 >> 16; descr[ 7] = tdes1 >> 24;
|
||||
- descr[ 8] = tdes2; descr[ 9] = tdes2 >> 8;
|
||||
- descr[10] = tdes2 >> 16; descr[11] = tdes2 >> 24;
|
||||
- descr[12] = tdes3; descr[13] = tdes3 >> 8;
|
||||
- descr[14] = tdes3 >> 16; descr[15] = tdes3 >> 24;
|
||||
+ store_le32(&descr[0], tdes0);
|
||||
+ store_le32(&descr[4], tdes1);
|
||||
+ store_le32(&descr[8], tdes2);
|
||||
+ store_le32(&descr[12], tdes3);
|
||||
|
||||
- if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t)
|
||||
- * 4, MEM_WRITE, PHYSICAL | NO_EXCEPTIONS)) {
|
||||
+ if (!cpu->memory_rw(cpu, cpu->mem, dma_to_phys(d, addr), descr,
|
||||
+ sizeof(uint32_t) * 4, MEM_WRITE, PHYSICAL | NO_EXCEPTIONS)) {
|
||||
fatal("[ dec21143_tx: memory_rw failed! ]\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -750,7 +1125,6 @@ static void srom_access(struct cpu *cpu,
|
||||
*/
|
||||
static void dec21143_reset(struct cpu *cpu, struct dec21143_data *d)
|
||||
{
|
||||
- int leaf;
|
||||
|
||||
if (d->cur_rx_buf != NULL)
|
||||
free(d->cur_rx_buf);
|
||||
@@ -759,7 +1133,6 @@ static void dec21143_reset(struct cpu *c
|
||||
d->cur_rx_buf = d->cur_tx_buf = NULL;
|
||||
|
||||
memset(d->reg, 0, sizeof(uint32_t) * N_REGS);
|
||||
- memset(d->srom, 0, sizeof(d->srom));
|
||||
memset(d->mii_phy_reg, 0, sizeof(d->mii_phy_reg));
|
||||
|
||||
/* Register values at reset, according to the manual: */
|
||||
@@ -772,35 +1145,8 @@ static void dec21143_reset(struct cpu *c
|
||||
d->tx_idling_threshold = 10;
|
||||
d->cur_rx_addr = d->cur_tx_addr = 0;
|
||||
|
||||
- /* Version (= 1) and Chip count (= 1): */
|
||||
- d->srom[TULIP_ROM_SROM_FORMAT_VERION] = 1;
|
||||
- d->srom[TULIP_ROM_CHIP_COUNT] = 1;
|
||||
-
|
||||
/* Set the MAC address: */
|
||||
- memcpy(d->srom + TULIP_ROM_IEEE_NETWORK_ADDRESS, d->mac, 6);
|
||||
-
|
||||
- leaf = 30;
|
||||
- d->srom[TULIP_ROM_CHIPn_DEVICE_NUMBER(0)] = 0;
|
||||
- d->srom[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)] = leaf & 255;
|
||||
- d->srom[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)+1] = leaf >> 8;
|
||||
-
|
||||
- d->srom[leaf+TULIP_ROM_IL_SELECT_CONN_TYPE] = 0; /* Not used? */
|
||||
- d->srom[leaf+TULIP_ROM_IL_MEDIA_COUNT] = 2;
|
||||
- leaf += TULIP_ROM_IL_MEDIAn_BLOCK_BASE;
|
||||
-
|
||||
- d->srom[leaf] = 7; /* descriptor length */
|
||||
- d->srom[leaf+1] = TULIP_ROM_MB_21142_SIA;
|
||||
- d->srom[leaf+2] = TULIP_ROM_MB_MEDIA_100TX;
|
||||
- /* here comes 4 bytes of GPIO control/data settings */
|
||||
- leaf += d->srom[leaf];
|
||||
-
|
||||
- d->srom[leaf] = 15; /* descriptor length */
|
||||
- d->srom[leaf+1] = TULIP_ROM_MB_21142_MII;
|
||||
- d->srom[leaf+2] = 0; /* PHY nr */
|
||||
- d->srom[leaf+3] = 0; /* len of select sequence */
|
||||
- d->srom[leaf+4] = 0; /* len of reset sequence */
|
||||
- /* 5,6, 7,8, 9,10, 11,12, 13,14 = unused by GXemul */
|
||||
- leaf += d->srom[leaf];
|
||||
+ memcpy(d->nic.mac_address, d->srom + TULIP_ROM_IEEE_NETWORK_ADDRESS, 6);
|
||||
|
||||
/* MII PHY initial state: */
|
||||
d->mii_state = MII_STATE_RESET;
|
||||
@@ -814,12 +1160,13 @@ static void dec21143_reset(struct cpu *c
|
||||
DEVICE_ACCESS(dec21143)
|
||||
{
|
||||
struct dec21143_data *d = (struct dec21143_data *) extra;
|
||||
- uint64_t idata = 0, odata = 0;
|
||||
+ uint32_t idata = 0, odata = 0;
|
||||
uint32_t oldreg = 0;
|
||||
int regnr = relative_addr >> 3;
|
||||
|
||||
if (writeflag == MEM_WRITE)
|
||||
- idata = memory_readmax64(cpu, data, len | d->pci_little_endian);
|
||||
+ idata = (uint32_t)memory_readmax64(cpu, data,
|
||||
+ len | d->pci_little_endian);
|
||||
|
||||
if ((relative_addr & 7) == 0 && regnr < N_REGS) {
|
||||
if (writeflag == MEM_READ) {
|
||||
@@ -916,8 +1263,15 @@ DEVICE_ACCESS(dec21143)
|
||||
/* Turned off RX? Then go to stopped state: */
|
||||
d->reg[CSR_STATUS/8] &= ~STATUS_RS;
|
||||
}
|
||||
+ /* Maintain r/o filter mode bits: */
|
||||
+ d->reg[CSR_OPMODE/8] &=
|
||||
+ ~(OPMODE_HP | OPMODE_HO | OPMODE_IF);
|
||||
+ d->reg[CSR_OPMODE/8] |= oldreg &
|
||||
+ (OPMODE_HP | OPMODE_HO | OPMODE_IF);
|
||||
idata &= ~(OPMODE_HBD | OPMODE_SCR | OPMODE_PCS
|
||||
- | OPMODE_PS | OPMODE_SF | OPMODE_TTM | OPMODE_FD);
|
||||
+ | OPMODE_PS | OPMODE_SF | OPMODE_TTM | OPMODE_FD
|
||||
+ | OPMODE_IF | OPMODE_HO | OPMODE_HP | OPMODE_PR
|
||||
+ | OPMODE_PM);
|
||||
if (idata & OPMODE_PNIC_IT) {
|
||||
idata &= ~OPMODE_PNIC_IT;
|
||||
d->tx_idling = d->tx_idling_threshold;
|
||||
@@ -926,6 +1280,7 @@ DEVICE_ACCESS(dec21143)
|
||||
fatal("[ dec21143: UNIMPLEMENTED OPMODE bits"
|
||||
": 0x%08x ]\n", (int)idata);
|
||||
}
|
||||
+ dec21143_update_rx_mode(d);
|
||||
dev_dec21143_tick(cpu, extra);
|
||||
}
|
||||
break;
|
||||
@@ -976,6 +1331,7 @@ DEVINIT(dec21143)
|
||||
{
|
||||
struct dec21143_data *d;
|
||||
char name2[100];
|
||||
+ int leaf;
|
||||
|
||||
CHECK_ALLOCATION(d = (struct dec21143_data *) malloc(sizeof(struct dec21143_data)));
|
||||
memset(d, 0, sizeof(struct dec21143_data));
|
||||
@@ -983,15 +1339,80 @@ DEVINIT(dec21143)
|
||||
INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
|
||||
d->pci_little_endian = devinit->pci_little_endian;
|
||||
|
||||
- net_generate_unique_mac(devinit->machine, d->mac);
|
||||
- net_add_nic(devinit->machine->emul->net, d, d->mac);
|
||||
- d->net = devinit->machine->emul->net;
|
||||
+ /* XXX XXX XXX */
|
||||
+ switch (devinit->machine->machine_type) {
|
||||
+ /*
|
||||
+ * Footbridge systems -- this is actually configurable by
|
||||
+ * system software, but this is the window setting that
|
||||
+ * NetBSD uses.
|
||||
+ */
|
||||
+ case MACHINE_CATS:
|
||||
+ case MACHINE_NETWINDER:
|
||||
+ d->xxx_dma_to_phys_mask = ~0x20000000;
|
||||
+ break;
|
||||
+
|
||||
+ /*
|
||||
+ * V3 Semi PCI bus controller -- this is actually configurable
|
||||
+ * by system sofware, but this is the value previously hard-coded
|
||||
+ * for all platforms that did not work on Footbridge systems.
|
||||
+ */
|
||||
+ case MACHINE_ALGOR:
|
||||
+ /* FALLTHROUGH */
|
||||
+
|
||||
+ /* Other known users of dc21143 that came along for the ride. */
|
||||
+ case MACHINE_COBALT:
|
||||
+ case MACHINE_PMPPC:
|
||||
+ case MACHINE_PREP:
|
||||
+ case MACHINE_MACPPC:
|
||||
+ case MACHINE_MVMEPPC:
|
||||
+ d->xxx_dma_to_phys_mask = 0x7fffffff;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ fatal("[ dec21143: default DMA mask for unhandled machine %d\n",
|
||||
+ devinit->machine->machine_type);
|
||||
+ d->xxx_dma_to_phys_mask = 0xffffffff;
|
||||
+ }
|
||||
+
|
||||
+ memset(d->srom, 0, sizeof(d->srom));
|
||||
+
|
||||
+ /* Version (= 1) and Chip count (= 1): */
|
||||
+ d->srom[TULIP_ROM_SROM_FORMAT_VERION] = 1;
|
||||
+ d->srom[TULIP_ROM_CHIP_COUNT] = 1;
|
||||
+
|
||||
+ leaf = 30;
|
||||
+ d->srom[TULIP_ROM_CHIPn_DEVICE_NUMBER(0)] = 0;
|
||||
+ d->srom[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)] = leaf & 255;
|
||||
+ d->srom[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)+1] = leaf >> 8;
|
||||
+
|
||||
+ d->srom[leaf+TULIP_ROM_IL_SELECT_CONN_TYPE] = 0; /* Not used? */
|
||||
+ d->srom[leaf+TULIP_ROM_IL_MEDIA_COUNT] = 2;
|
||||
+ leaf += TULIP_ROM_IL_MEDIAn_BLOCK_BASE;
|
||||
+
|
||||
+ d->srom[leaf] = 7; /* descriptor length */
|
||||
+ d->srom[leaf+1] = TULIP_ROM_MB_21142_SIA;
|
||||
+ d->srom[leaf+2] = TULIP_ROM_MB_MEDIA_100TX;
|
||||
+ /* here comes 4 bytes of GPIO control/data settings */
|
||||
+ leaf += d->srom[leaf];
|
||||
+
|
||||
+ d->srom[leaf] = 15; /* descriptor length */
|
||||
+ d->srom[leaf+1] = TULIP_ROM_MB_21142_MII;
|
||||
+ d->srom[leaf+2] = 0; /* PHY nr */
|
||||
+ d->srom[leaf+3] = 0; /* len of select sequence */
|
||||
+ d->srom[leaf+4] = 0; /* len of reset sequence */
|
||||
+ /* 5,6, 7,8, 9,10, 11,12, 13,14 = unused by GXemul */
|
||||
+ leaf += d->srom[leaf];
|
||||
+
|
||||
+ net_generate_unique_mac(devinit->machine, d->nic.mac_address);
|
||||
+ memcpy(d->srom + TULIP_ROM_IEEE_NETWORK_ADDRESS, d->nic.mac_address, 6);
|
||||
+ net_add_nic(devinit->machine->emul->net, &d->nic);
|
||||
|
||||
dec21143_reset(devinit->machine->cpus[0], d);
|
||||
|
||||
snprintf(name2, sizeof(name2), "%s [%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
- devinit->name, d->mac[0], d->mac[1], d->mac[2], d->mac[3],
|
||||
- d->mac[4], d->mac[5]);
|
||||
+ devinit->name, d->nic.mac_address[0], d->nic.mac_address[1],
|
||||
+ d->nic.mac_address[2], d->nic.mac_address[3],
|
||||
+ d->nic.mac_address[4], d->nic.mac_address[5]);
|
||||
|
||||
memory_device_register(devinit->machine->memory, name2,
|
||||
devinit->addr, 0x100, dev_dec21143_access, d, DM_DEFAULT, NULL);
|
|
@ -1,74 +0,0 @@
|
|||
$NetBSD: patch-src_devices_dev_ether.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add support for tap(4)-based networking.
|
||||
|
||||
--- src/devices/dev_ether.cc.orig 2020-10-05 22:56:01.167967575 +0000
|
||||
+++ src/devices/dev_ether.cc 2020-10-05 22:56:17.330782903 +0000
|
||||
@@ -49,6 +49,8 @@
|
||||
#define DEV_ETHER_TICK_SHIFT 14
|
||||
|
||||
struct ether_data {
|
||||
+ struct nic_data nic;
|
||||
+
|
||||
unsigned char buf[DEV_ETHER_BUFFER_SIZE];
|
||||
unsigned char mac[6];
|
||||
|
||||
@@ -66,7 +68,7 @@ DEVICE_TICK(ether)
|
||||
|
||||
d->status &= ~DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE;
|
||||
if (cpu->machine->emul->net != NULL)
|
||||
- r = net_ethernet_rx_avail(cpu->machine->emul->net, d);
|
||||
+ r = net_ethernet_rx_avail(cpu->machine->emul->net, &d->nic);
|
||||
if (r)
|
||||
d->status |= DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE;
|
||||
|
||||
@@ -147,7 +149,7 @@ DEVICE_ACCESS(ether)
|
||||
else {
|
||||
d->status &= ~DEV_ETHER_STATUS_PACKET_RECEIVED;
|
||||
if (net_ethernet_rx(cpu->machine->emul->net,
|
||||
- d, &incoming_ptr, &incoming_len)) {
|
||||
+ &d->nic, &incoming_ptr, &incoming_len)) {
|
||||
d->status |=
|
||||
DEV_ETHER_STATUS_PACKET_RECEIVED;
|
||||
if (incoming_len>DEV_ETHER_BUFFER_SIZE)
|
||||
@@ -167,7 +169,7 @@ DEVICE_ACCESS(ether)
|
||||
fatal("[ ether: SEND but no net? ]\n");
|
||||
else
|
||||
net_ethernet_tx(cpu->machine->emul->net,
|
||||
- d, d->buf, d->packet_len);
|
||||
+ &d->nic, d->buf, d->packet_len);
|
||||
d->status &= ~DEV_ETHER_STATUS_PACKET_RECEIVED;
|
||||
dev_ether_tick(cpu, d);
|
||||
break;
|
||||
@@ -183,7 +185,7 @@ DEVICE_ACCESS(ether)
|
||||
fatal("[ ether: read of MAC is not allowed! ]\n");
|
||||
} else {
|
||||
// Write out the MAC address to the address given.
|
||||
- cpu->memory_rw(cpu, cpu->mem, idata, d->mac,
|
||||
+ cpu->memory_rw(cpu, cpu->mem, idata, d->nic.mac_address,
|
||||
6, MEM_WRITE, CACHE_NONE);
|
||||
}
|
||||
break;
|
||||
@@ -221,9 +223,11 @@ DEVINIT(ether)
|
||||
|
||||
INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
|
||||
|
||||
- net_generate_unique_mac(devinit->machine, d->mac);
|
||||
+ net_generate_unique_mac(devinit->machine, d->nic.mac_address);
|
||||
snprintf(tmp, sizeof(tmp), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
- d->mac[0], d->mac[1], d->mac[2], d->mac[3], d->mac[4], d->mac[5]);
|
||||
+ d->nic.mac_address[0], d->nic.mac_address[1],
|
||||
+ d->nic.mac_address[2], d->nic.mac_address[3],
|
||||
+ d->nic.mac_address[4], d->nic.mac_address[5]);
|
||||
|
||||
snprintf(n1, nlen, "%s [%s]", devinit->name, tmp);
|
||||
snprintf(n2, nlen, "%s [%s, control]", devinit->name, tmp);
|
||||
@@ -237,7 +241,7 @@ DEVINIT(ether)
|
||||
DEV_ETHER_LENGTH-DEV_ETHER_BUFFER_SIZE, dev_ether_access, (void *)d,
|
||||
DM_DEFAULT, NULL);
|
||||
|
||||
- net_add_nic(devinit->machine->emul->net, d, d->mac);
|
||||
+ net_add_nic(devinit->machine->emul->net, &d->nic);
|
||||
|
||||
machine_add_tickfunction(devinit->machine,
|
||||
dev_ether_tick, d, DEV_ETHER_TICK_SHIFT);
|
|
@ -1,232 +0,0 @@
|
|||
$NetBSD: patch-src_devices_dev_le.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
- Add support for tap(4)-based networking.
|
||||
- Process the setup packet, and implement address filtering.
|
||||
|
||||
--- src/devices/dev_le.cc.orig 2020-10-05 22:56:40.808218933 +0000
|
||||
+++ src/devices/dev_le.cc 2020-10-05 22:56:55.751440817 +0000
|
||||
@@ -72,9 +72,10 @@
|
||||
|
||||
extern int quiet_mode;
|
||||
|
||||
-#define LE_MODE_LOOP 4
|
||||
-#define LE_MODE_DTX 2
|
||||
-#define LE_MODE_DRX 1
|
||||
+#define LE_MODE_PROM 0x8000
|
||||
+#define LE_MODE_LOOP 0x0004
|
||||
+#define LE_MODE_DTX 0x0002
|
||||
+#define LE_MODE_DRX 0x0001
|
||||
|
||||
|
||||
#define N_REGISTERS 4
|
||||
@@ -83,6 +84,8 @@ extern int quiet_mode;
|
||||
|
||||
|
||||
struct le_data {
|
||||
+ struct nic_data nic;
|
||||
+
|
||||
struct interrupt irq;
|
||||
int irq_asserted;
|
||||
|
||||
@@ -101,13 +104,14 @@ struct le_data {
|
||||
uint32_t init_block_addr;
|
||||
|
||||
uint16_t mode;
|
||||
- uint64_t padr; /* MAC address */
|
||||
- uint64_t ladrf;
|
||||
+ uint16_t ladrf[4];
|
||||
uint32_t rdra; /* receive descriptor ring address */
|
||||
int rlen; /* nr of rx descriptors */
|
||||
uint32_t tdra; /* transmit descriptor ring address */
|
||||
int tlen; /* nr ot tx descriptors */
|
||||
|
||||
+ int allmulti;/* receive all multicast packets */
|
||||
+
|
||||
/* Current rx and tx descriptor indices: */
|
||||
int rxp;
|
||||
int txp;
|
||||
@@ -157,6 +161,9 @@ static void le_write_16bit(struct le_dat
|
||||
*/
|
||||
static void le_chip_init(struct le_data *d)
|
||||
{
|
||||
+ uint16_t tmp;
|
||||
+ uint8_t macaddr[6];
|
||||
+
|
||||
d->init_block_addr = (d->reg[1] & 0xffff) + ((d->reg[2] & 0xff) << 16);
|
||||
if (d->init_block_addr & 1)
|
||||
fatal("[ le: WARNING! initialization block address "
|
||||
@@ -165,13 +172,36 @@ static void le_chip_init(struct le_data
|
||||
debug("[ le: d->init_block_addr = 0x%06x ]\n", d->init_block_addr);
|
||||
|
||||
d->mode = le_read_16bit(d, d->init_block_addr + 0);
|
||||
- d->padr = le_read_16bit(d, d->init_block_addr + 2);
|
||||
- d->padr += (le_read_16bit(d, d->init_block_addr + 4) << 16);
|
||||
- d->padr += (le_read_16bit(d, d->init_block_addr + 6) << 32);
|
||||
- d->ladrf = le_read_16bit(d, d->init_block_addr + 8);
|
||||
- d->ladrf += (le_read_16bit(d, d->init_block_addr + 10) << 16);
|
||||
- d->ladrf += (le_read_16bit(d, d->init_block_addr + 12) << 32);
|
||||
- d->ladrf += (le_read_16bit(d, d->init_block_addr + 14) << 48);
|
||||
+
|
||||
+ /*
|
||||
+ * The MAC address is packed into the PADR field as 3 little-endian
|
||||
+ * 16-bit words.
|
||||
+ */
|
||||
+ tmp = le_read_16bit(d, d->init_block_addr + 2);
|
||||
+ macaddr[0] = (uint8_t)(tmp);
|
||||
+ macaddr[1] = (uint8_t)(tmp >> 8);
|
||||
+ tmp = le_read_16bit(d, d->init_block_addr + 4);
|
||||
+ macaddr[2] = (uint8_t)(tmp);
|
||||
+ macaddr[3] = (uint8_t)(tmp >> 8);
|
||||
+ tmp = le_read_16bit(d, d->init_block_addr + 6);
|
||||
+ macaddr[4] = (uint8_t)(tmp);
|
||||
+ macaddr[5] = (uint8_t)(tmp >> 8);
|
||||
+ memcpy(d->nic.mac_address, macaddr, sizeof(d->nic.mac_address));
|
||||
+
|
||||
+ /*
|
||||
+ * The muticast address filter is packed into the LADRF field
|
||||
+ * as 4 little-endian 16-bit words.
|
||||
+ */
|
||||
+ d->ladrf[0] = le_read_16bit(d, d->init_block_addr + 8);
|
||||
+ d->ladrf[1] = le_read_16bit(d, d->init_block_addr + 10);
|
||||
+ d->ladrf[2] = le_read_16bit(d, d->init_block_addr + 12);
|
||||
+ d->ladrf[3] = le_read_16bit(d, d->init_block_addr + 14);
|
||||
+ if (d->ladrf[0] == 0xffff && d->ladrf[1] == 0xffff &&
|
||||
+ d->ladrf[2] == 0xffff && d->ladrf[3] == 0xffff)
|
||||
+ d->allmulti = 1;
|
||||
+ else
|
||||
+ d->allmulti = 0;
|
||||
+
|
||||
d->rdra = le_read_16bit(d, d->init_block_addr + 16);
|
||||
d->rdra += ((le_read_16bit(d, d->init_block_addr + 18) & 0xff) << 16);
|
||||
d->rlen = 1 << ((le_read_16bit(d, d->init_block_addr + 18) >> 13) & 7);
|
||||
@@ -179,13 +209,16 @@ static void le_chip_init(struct le_data
|
||||
d->tdra += ((le_read_16bit(d, d->init_block_addr + 22) & 0xff) << 16);
|
||||
d->tlen = 1 << ((le_read_16bit(d, d->init_block_addr + 22) >> 13) & 7);
|
||||
|
||||
- debug("[ le: DEBUG: mode %04x ]\n", d->mode);
|
||||
- debug("[ le: DEBUG: padr %016llx ]\n", (long long)d->padr);
|
||||
- debug("[ le: DEBUG: ladrf %016llx ]\n", (long long)d->ladrf);
|
||||
- debug("[ le: DEBUG: rdra %06llx ]\n", d->rdra);
|
||||
- debug("[ le: DEBUG: rlen %3i ]\n", d->rlen);
|
||||
- debug("[ le: DEBUG: tdra %06llx ]\n", d->tdra);
|
||||
- debug("[ le: DEBUG: tlen %3i ]\n", d->tlen);
|
||||
+ debug("[ le: DEBUG: mode %04x ]\n", d->mode);
|
||||
+ debug("[ le: DEBUG: padr %02x:%02x:%02x:%02x:%02x:%02x ]\n",
|
||||
+ macaddr[0], macaddr[1], macaddr[2],
|
||||
+ macaddr[3], macaddr[4], macaddr[5]);
|
||||
+ debug("[ le: DEBUG: ladrf %04x:%04x:%04x:%04x ]\n",
|
||||
+ d->ladrf[0], d->ladrf[1], d->ladrf[2], d->ladrf[3]);
|
||||
+ debug("[ le: DEBUG: rdra %06llx ]\n", d->rdra);
|
||||
+ debug("[ le: DEBUG: rlen %3i ]\n", d->rlen);
|
||||
+ debug("[ le: DEBUG: tdra %06llx ]\n", d->tdra);
|
||||
+ debug("[ le: DEBUG: tlen %3i ]\n", d->tlen);
|
||||
|
||||
/* Set TXON and RXON, unless they are disabled by 'mode': */
|
||||
if (d->mode & LE_MODE_DTX)
|
||||
@@ -198,6 +231,9 @@ static void le_chip_init(struct le_data
|
||||
else
|
||||
d->reg[0] |= LE_RXON;
|
||||
|
||||
+ /* Initialize promiscuous mode. */
|
||||
+ d->nic.promiscuous_mode = (d->mode & LE_MODE_PROM) ? 1 : 0;
|
||||
+
|
||||
/* Go to the start of the descriptor rings: */
|
||||
d->rxp = d->txp = 0;
|
||||
|
||||
@@ -308,7 +344,8 @@ static void le_tx(struct net *net, struc
|
||||
* the packet.
|
||||
*/
|
||||
if (enp) {
|
||||
- net_ethernet_tx(net, d, d->tx_packet, d->tx_packet_len);
|
||||
+ net_ethernet_tx(net, &d->nic, d->tx_packet,
|
||||
+ d->tx_packet_len);
|
||||
|
||||
free(d->tx_packet);
|
||||
d->tx_packet = NULL;
|
||||
@@ -446,6 +483,62 @@ static void le_rx(struct net *net, struc
|
||||
|
||||
|
||||
/*
|
||||
+ * le_rx_drop_packet():
|
||||
+ *
|
||||
+ * Implement the logic to determine if we should drop a packet
|
||||
+ * before passing it to the guest. Returns 1 if the packet was
|
||||
+ * dropped.
|
||||
+ */
|
||||
+static int
|
||||
+le_rx_drop_packet(struct net *net, struct le_data *d)
|
||||
+{
|
||||
+ /* Only implement filtering if using a tap device. */
|
||||
+ if (net->tapdev == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * The network layer has already checked for our MAC address
|
||||
+ * or promiscuous mode. We just need to check the multicast
|
||||
+ * filter or broadcast.
|
||||
+ */
|
||||
+
|
||||
+ /* If the packet is not multicast, we know it should be received. */
|
||||
+ if (! net_ether_multicast(d->rx_packet))
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Optimization -- if the guest has set all of the filter
|
||||
+ * bits, then we can skip additional checks.
|
||||
+ */
|
||||
+ if (d->allmulti)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Check for broadcast. */
|
||||
+ if (net_ether_broadcast(d->rx_packet))
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Check the multicast address filter. We pass the address
|
||||
+ * through the little-endian Ethernet CRC generator. The
|
||||
+ * high-order 6 bits are the index into the 64-bit filter.
|
||||
+ * The upper 2 bits select the 16-bit filter word, and the
|
||||
+ * remaining 4 select the bit in the word.
|
||||
+ */
|
||||
+ uint32_t crc = net_ether_crc32_le(d->rx_packet, 6);
|
||||
+ crc >>= 26;
|
||||
+ if (d->ladrf[crc >> 4] & (1 << (crc & 0xf)))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Not for us; drop the packet. */
|
||||
+ free(d->rx_packet);
|
||||
+ d->rx_packet = NULL;
|
||||
+ d->rx_packet_len = 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
* le_register_fix():
|
||||
*/
|
||||
static void le_register_fix(struct net *net, struct le_data *d)
|
||||
@@ -481,9 +574,12 @@ static void le_register_fix(struct net *
|
||||
break;
|
||||
|
||||
if (d->rx_packet == NULL &&
|
||||
- net_ethernet_rx_avail(net, d))
|
||||
- net_ethernet_rx(net, d,
|
||||
+ net_ethernet_rx_avail(net, &d->nic)) {
|
||||
+ net_ethernet_rx(net, &d->nic,
|
||||
&d->rx_packet, &d->rx_packet_len);
|
||||
+ if (le_rx_drop_packet(net, d))
|
||||
+ continue;
|
||||
+ }
|
||||
} while (d->rx_packet != NULL);
|
||||
}
|
||||
|
||||
@@ -813,6 +909,7 @@ void dev_le_init(struct machine *machine
|
||||
|
||||
machine_add_tickfunction(machine, dev_le_tick, d, LE_TICK_SHIFT);
|
||||
|
||||
- net_add_nic(machine->emul->net, d, &d->rom[0]);
|
||||
+ memcpy(d->nic.mac_address, &d->rom[0], sizeof(d->nic.mac_address));
|
||||
+ net_add_nic(machine->emul->net, &d->nic);
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
$NetBSD: patch-src_devices_dev_rtl8139c.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Updates for tap(4)-related changes to Ethernet support.
|
||||
|
||||
--- src/devices/dev_rtl8139c.cc.orig 2020-10-05 22:57:40.189047655 +0000
|
||||
+++ src/devices/dev_rtl8139c.cc 2020-10-05 22:57:53.936646578 +0000
|
||||
@@ -50,8 +50,9 @@
|
||||
#define EEPROM_SIZE 0x100
|
||||
|
||||
struct rtl8139c_data {
|
||||
+ struct nic_data nic;
|
||||
+
|
||||
struct interrupt irq;
|
||||
- unsigned char macaddr[6];
|
||||
|
||||
/* Registers: */
|
||||
uint8_t rl_command;
|
||||
@@ -205,25 +206,26 @@ DEVINIT(rtl8139c)
|
||||
|
||||
INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
|
||||
|
||||
- net_generate_unique_mac(devinit->machine, d->macaddr);
|
||||
+ net_generate_unique_mac(devinit->machine, d->nic.mac_address);
|
||||
|
||||
/* TODO: eeprom address width = 6 on 8129? */
|
||||
d->eeprom_address_width = 8;
|
||||
d->eeprom_reg[0] = 0x8139;
|
||||
- d->eeprom_reg[7] = d->macaddr[0] + (d->macaddr[1] << 8);
|
||||
- d->eeprom_reg[8] = d->macaddr[2] + (d->macaddr[3] << 8);
|
||||
- d->eeprom_reg[9] = d->macaddr[4] + (d->macaddr[5] << 8);
|
||||
+ d->eeprom_reg[7] = d->nic.mac_address[0] + (d->nic.mac_address[1] << 8);
|
||||
+ d->eeprom_reg[8] = d->nic.mac_address[2] + (d->nic.mac_address[3] << 8);
|
||||
+ d->eeprom_reg[9] = d->nic.mac_address[4] + (d->nic.mac_address[5] << 8);
|
||||
|
||||
CHECK_ALLOCATION(name2 = (char *) malloc(nlen));
|
||||
snprintf(name2, nlen, "%s [%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
- devinit->name, d->macaddr[0], d->macaddr[1], d->macaddr[2],
|
||||
- d->macaddr[3], d->macaddr[4], d->macaddr[5]);
|
||||
+ devinit->name, d->nic.mac_address[0], d->nic.mac_address[1],
|
||||
+ d->nic.mac_address[2], d->nic.mac_address[3],
|
||||
+ d->nic.mac_address[4], d->nic.mac_address[5]);
|
||||
|
||||
memory_device_register(devinit->machine->memory, name2,
|
||||
devinit->addr, DEV_RTL8139C_LENGTH, dev_rtl8139c_access, (void *)d,
|
||||
DM_DEFAULT, NULL);
|
||||
|
||||
- net_add_nic(devinit->machine->emul->net, d, d->macaddr);
|
||||
+ net_add_nic(devinit->machine->emul->net, &d->nic);
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
$NetBSD: patch-src_devices_dev_sgi_mec.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Updates for tap(4)-related changes to Ethernet support.
|
||||
|
||||
--- src/devices/dev_sgi_mec.cc.orig 2020-10-05 22:58:11.248005164 +0000
|
||||
+++ src/devices/dev_sgi_mec.cc 2020-10-05 22:58:31.644418157 +0000
|
||||
@@ -81,13 +81,13 @@
|
||||
#define N_RX_ADDRESSES 16
|
||||
|
||||
struct sgi_mec_data {
|
||||
+ struct nic_data nic;
|
||||
+
|
||||
uint64_t reg[DEV_SGI_MEC_LENGTH / sizeof(uint64_t)];
|
||||
|
||||
struct interrupt irq;
|
||||
int prev_asserted;
|
||||
|
||||
- unsigned char macaddr[6];
|
||||
-
|
||||
unsigned char cur_tx_packet[MAX_TX_PACKET_LEN];
|
||||
int cur_tx_packet_len;
|
||||
|
||||
@@ -157,8 +157,8 @@ static int mec_try_rx(struct cpu *cpu, s
|
||||
}
|
||||
|
||||
if (d->cur_rx_packet == NULL &&
|
||||
- net_ethernet_rx_avail(cpu->machine->emul->net, d))
|
||||
- net_ethernet_rx(cpu->machine->emul->net, d,
|
||||
+ net_ethernet_rx_avail(cpu->machine->emul->net, &d->nic))
|
||||
+ net_ethernet_rx(cpu->machine->emul->net, &d->nic,
|
||||
&d->cur_rx_packet, &d->cur_rx_packet_len);
|
||||
|
||||
if (d->cur_rx_packet == NULL)
|
||||
@@ -343,7 +343,7 @@ static int mec_try_tx(struct cpu *cpu, s
|
||||
if (j < len)
|
||||
fatal("[ mec_try_tx: not enough data? ]\n");
|
||||
|
||||
- net_ethernet_tx(cpu->machine->emul->net, d,
|
||||
+ net_ethernet_tx(cpu->machine->emul->net, &d->nic,
|
||||
d->cur_tx_packet, d->cur_tx_packet_len);
|
||||
|
||||
/* see openbsd's if_mec.c for details */
|
||||
@@ -675,13 +675,14 @@ void dev_sgi_mec_init(struct machine *ma
|
||||
memset(d, 0, sizeof(struct sgi_mec_data));
|
||||
|
||||
INTERRUPT_CONNECT(irq_path, d->irq);
|
||||
- memcpy(d->macaddr, macaddr, 6);
|
||||
+ memcpy(d->nic.mac_address, macaddr, 6);
|
||||
mec_reset(d);
|
||||
|
||||
CHECK_ALLOCATION(name2 = (char *) malloc(nlen));
|
||||
snprintf(name2, nlen, "mec [%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
- d->macaddr[0], d->macaddr[1], d->macaddr[2],
|
||||
- d->macaddr[3], d->macaddr[4], d->macaddr[5]);
|
||||
+ d->nic.mac_address[0], d->nic.mac_address[1],
|
||||
+ d->nic.mac_address[2], d->nic.mac_address[3],
|
||||
+ d->nic.mac_address[4], d->nic.mac_address[5]);
|
||||
|
||||
memory_device_register(mem, name2, baseaddr,
|
||||
DEV_SGI_MEC_LENGTH, dev_sgi_mec_access, (void *)d,
|
||||
@@ -690,7 +691,7 @@ void dev_sgi_mec_init(struct machine *ma
|
||||
machine_add_tickfunction(machine, dev_sgi_mec_tick, d,
|
||||
MEC_TICK_SHIFT);
|
||||
|
||||
- net_add_nic(machine->emul->net, d, macaddr);
|
||||
+ net_add_nic(machine->emul->net, &d->nic);
|
||||
}
|
||||
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
$NetBSD: patch-src_devices_dev_sn.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Updates for tap(4)-related changes to Ethernet support.
|
||||
|
||||
--- src/devices/dev_sn.cc.orig 2020-10-05 22:58:49.162038719 +0000
|
||||
+++ src/devices/dev_sn.cc 2020-10-05 22:59:04.524312162 +0000
|
||||
@@ -48,8 +48,8 @@
|
||||
#define DEV_SN_LENGTH 0x1000
|
||||
|
||||
struct sn_data {
|
||||
+ struct nic_data nic;
|
||||
struct interrupt irq;
|
||||
- unsigned char macaddr[6];
|
||||
uint32_t reg[SONIC_NREGS];
|
||||
};
|
||||
|
||||
@@ -104,18 +104,19 @@ DEVINIT(sn)
|
||||
|
||||
INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
|
||||
|
||||
- net_generate_unique_mac(devinit->machine, d->macaddr);
|
||||
+ net_generate_unique_mac(devinit->machine, d->nic.mac_address);
|
||||
|
||||
CHECK_ALLOCATION(name2 = (char *) malloc(nlen));
|
||||
snprintf(name2, nlen, "%s [%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
- devinit->name, d->macaddr[0], d->macaddr[1], d->macaddr[2],
|
||||
- d->macaddr[3], d->macaddr[4], d->macaddr[5]);
|
||||
+ devinit->name, d->nic.mac_address[0], d->nic.mac_address[1],
|
||||
+ d->nic.mac_address[2], d->nic.mac_address[3],
|
||||
+ d->nic.mac_address[4], d->nic.mac_address[5]);
|
||||
|
||||
memory_device_register(devinit->machine->memory, name2,
|
||||
devinit->addr, DEV_SN_LENGTH,
|
||||
dev_sn_access, (void *)d, DM_DEFAULT, NULL);
|
||||
|
||||
- net_add_nic(devinit->machine->emul->net, d, d->macaddr);
|
||||
+ net_add_nic(devinit->machine->emul->net, &d->nic);
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
$NetBSD: patch-src_include_net.h,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add support for tap(4)-based networking.
|
||||
|
||||
--- src/include/net.h.orig 2020-10-05 22:59:17.124851904 +0000
|
||||
+++ src/include/net.h 2020-10-05 22:59:31.468423021 +0000
|
||||
@@ -112,6 +112,15 @@ struct tcp_connection {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
+/* Common data for emulated Ethernet NICs. */
|
||||
+
|
||||
+struct nic_data {
|
||||
+ struct net *net; /* net we belong to */
|
||||
+ uint8_t mac_address[6]; /* our MAC address */
|
||||
+ int promiscuous_mode;/* receive all packets */
|
||||
+};
|
||||
+
|
||||
+/*****************************************************************************/
|
||||
|
||||
#define MAX_TCP_CONNECTIONS 100
|
||||
#define MAX_UDP_CONNECTIONS 100
|
||||
@@ -120,13 +129,17 @@ struct net {
|
||||
/* The emul struct which this net belong to: */
|
||||
struct emul *emul;
|
||||
|
||||
+ /* The network's tap device, if we're using tap: */
|
||||
+ const char *tapdev;
|
||||
+ int tap_fd;
|
||||
+
|
||||
/* The network's addresses: */
|
||||
struct in_addr netmask_ipv4;
|
||||
int netmask_ipv4_len;
|
||||
|
||||
/* NICs connected to this network: */
|
||||
int n_nics;
|
||||
- void **nic_extra; /* one void * per NIC */
|
||||
+ struct nic_data **nic_data; /* one per NIC */
|
||||
|
||||
/* The "special machine": */
|
||||
unsigned char gateway_ipv4_addr[4];
|
||||
@@ -151,6 +164,18 @@ struct net {
|
||||
struct remote_net *remote_nets;
|
||||
};
|
||||
|
||||
+/* net_tap.c: */
|
||||
+void net_tap_rx_avail(struct net *net);
|
||||
+void net_tap_tx(struct net *net, struct nic_data *nic, unsigned char *packet,
|
||||
+ int len);
|
||||
+int net_tap_init(struct net *net, const char *tapdev);
|
||||
+
|
||||
+/* net_ether.cc */
|
||||
+int net_ether_eq(const uint8_t *a1, const uint8_t *a2);
|
||||
+int net_ether_broadcast(const uint8_t *a);
|
||||
+int net_ether_multicast(const uint8_t *a);
|
||||
+uint32_t net_ether_crc32_le(const uint8_t *buf, size_t len);
|
||||
+
|
||||
/* net_misc.c: */
|
||||
void net_debugaddr(void *addr, int type);
|
||||
void net_generate_unique_mac(struct machine *, unsigned char *macbuf);
|
||||
@@ -162,25 +187,27 @@ void net_ip_checksum(unsigned char *ip_h
|
||||
void net_ip_tcp_checksum(unsigned char *tcp_header, int chksumoffset,
|
||||
int tcp_len, unsigned char *srcaddr, unsigned char *dstaddr,
|
||||
int udpflag);
|
||||
-void net_ip_tcp_connectionreply(struct net *net, void *extra,
|
||||
+void net_ip_tcp_connectionreply(struct net *net, struct nic_data *nic,
|
||||
int con_id, int connecting, unsigned char *data, int datalen, int rst);
|
||||
-void net_ip_broadcast(struct net *net, void *extra,
|
||||
+void net_ip_broadcast(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len);
|
||||
-void net_ip(struct net *net, void *extra, unsigned char *packet, int len);
|
||||
-void net_udp_rx_avail(struct net *net, void *extra);
|
||||
-void net_tcp_rx_avail(struct net *net, void *extra);
|
||||
+void net_ip(struct net *net, struct nic_data *nic, unsigned char *packet,
|
||||
+ int len);
|
||||
+void net_udp_rx_avail(struct net *net, struct nic_data *nic);
|
||||
+void net_tcp_rx_avail(struct net *net, struct nic_data *nic);
|
||||
|
||||
/* net.c: */
|
||||
struct ethernet_packet_link *net_allocate_ethernet_packet_link(
|
||||
- struct net *net, void *extra, size_t len);
|
||||
-int net_ethernet_rx_avail(struct net *net, void *extra);
|
||||
-int net_ethernet_rx(struct net *net, void *extra,
|
||||
+ struct net *net, struct nic_data *nic, size_t len);
|
||||
+int net_ethernet_rx_avail(struct net *net, struct nic_data *nic);
|
||||
+int net_ethernet_rx(struct net *net, struct nic_data *nic,
|
||||
unsigned char **packetp, int *lenp);
|
||||
-void net_ethernet_tx(struct net *net, void *extra,
|
||||
+void net_ethernet_tx(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len);
|
||||
void net_dumpinfo(struct net *net);
|
||||
-void net_add_nic(struct net *net, void *extra, unsigned char *macaddr);
|
||||
+void net_add_nic(struct net *net, struct nic_data *nic);
|
||||
struct net *net_init(struct emul *emul, int init_flags,
|
||||
+ const char *tapdev,
|
||||
const char *ipv4addr, int netipv4len, char **remote, int n_remote,
|
||||
int local_port, const char *settings_prefix);
|
||||
|
||||
@@ -195,7 +222,7 @@ struct ethernet_packet_link {
|
||||
struct ethernet_packet_link *prev;
|
||||
struct ethernet_packet_link *next;
|
||||
|
||||
- void *extra;
|
||||
+ struct nic_data *nic;
|
||||
unsigned char *data;
|
||||
int len;
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
$NetBSD: patch-src_net_Makefile.skel,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add support for tap(4)-based networking.
|
||||
|
||||
--- src/net/Makefile.skel.orig 2020-10-05 22:59:56.683092920 +0000
|
||||
+++ src/net/Makefile.skel 2020-10-05 23:00:09.053165122 +0000
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
CXXFLAGS=$(CWARNINGS) $(COPTIM) $(XINCLUDE) $(DINCLUDE)
|
||||
|
||||
-OBJS=net.o net_ip.o net_misc.o
|
||||
+OBJS=net.o net_ip.o net_misc.o net_tap.o net_ether.o
|
||||
|
||||
all: $(OBJS)
|
||||
|
|
@ -1,318 +0,0 @@
|
|||
$NetBSD: patch-src_net_net.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add support for tap(4)-based networking.
|
||||
|
||||
--- src/net/net.cc.orig 2020-10-05 23:00:24.839832619 +0000
|
||||
+++ src/net/net.cc 2020-10-05 23:00:41.597469289 +0000
|
||||
@@ -30,10 +30,10 @@
|
||||
* (Read the README file in this directory for more details.)
|
||||
*
|
||||
*
|
||||
- * NOTE: The 'extra' argument used in many functions in this file is a pointer
|
||||
- * to something unique for each NIC (i.e. the NIC itself :-), so that if
|
||||
- * multiple NICs are emulated concurrently, they will not get packets that
|
||||
- * are meant for some other controller.
|
||||
+ * NOTE: The 'nic' argument used in many functions in this file is a pointer
|
||||
+ * to the nic_data for each NIC, so that if multiple NICs are emulated
|
||||
+ * concurrently, they will not get packets that are meant for some other
|
||||
+ * controller.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -62,7 +62,7 @@
|
||||
*
|
||||
* This routine allocates an ethernet_packet_link struct, and adds it at
|
||||
* the end of the packet chain. A data buffer is allocated, and the data,
|
||||
- * extra, and len fields of the link are set.
|
||||
+ * nic, and len fields of the link are set.
|
||||
*
|
||||
* Note: The data buffer is not zeroed.
|
||||
*
|
||||
@@ -70,7 +70,7 @@
|
||||
* failure.
|
||||
*/
|
||||
struct ethernet_packet_link *net_allocate_ethernet_packet_link(
|
||||
- struct net *net, void *extra, size_t len)
|
||||
+ struct net *net, struct nic_data *nic, size_t len)
|
||||
{
|
||||
struct ethernet_packet_link *lp;
|
||||
|
||||
@@ -78,7 +78,7 @@ struct ethernet_packet_link *net_allocat
|
||||
malloc(sizeof(struct ethernet_packet_link)));
|
||||
|
||||
lp->len = len;
|
||||
- lp->extra = extra;
|
||||
+ lp->nic = nic;
|
||||
CHECK_ALLOCATION(lp->data = (unsigned char *) malloc(len));
|
||||
|
||||
lp->next = NULL;
|
||||
@@ -116,7 +116,7 @@ struct ethernet_packet_link *net_allocat
|
||||
* An ARP request with the same from and to IP addresses should be ignored.
|
||||
* (This would be a host testing to see if there is an IP collision.)
|
||||
*/
|
||||
-static void net_arp(struct net *net, void *extra,
|
||||
+static void net_arp(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len, int reverse)
|
||||
{
|
||||
int q;
|
||||
@@ -161,7 +161,7 @@ static void net_arp(struct net *net, voi
|
||||
break;
|
||||
|
||||
lp = net_allocate_ethernet_packet_link(
|
||||
- net, extra, 60 + 14);
|
||||
+ net, nic, 60 + 14);
|
||||
|
||||
/* Copy the old packet first: */
|
||||
memset(lp->data, 0, 60 + 14);
|
||||
@@ -186,7 +186,7 @@ static void net_arp(struct net *net, voi
|
||||
break;
|
||||
case 3: /* Reverse Request */
|
||||
lp = net_allocate_ethernet_packet_link(
|
||||
- net, extra, 60 + 14);
|
||||
+ net, nic, 60 + 14);
|
||||
|
||||
/* Copy the old packet first: */
|
||||
memset(lp->data, 0, 60 + 14);
|
||||
@@ -242,7 +242,7 @@ static void net_arp(struct net *net, voi
|
||||
/*
|
||||
* net_ethernet_rx_avail():
|
||||
*
|
||||
- * Return 1 if there is a packet available for this 'extra' pointer, otherwise
|
||||
+ * Return 1 if there is a packet available for this nic, otherwise
|
||||
* return 0.
|
||||
*
|
||||
* Appart from actually checking for incoming packets from the outside world,
|
||||
@@ -250,12 +250,21 @@ static void net_arp(struct net *net, voi
|
||||
* a return value telling us whether there is a packet or not, we don't
|
||||
* actually get the packet.
|
||||
*/
|
||||
-int net_ethernet_rx_avail(struct net *net, void *extra)
|
||||
+int net_ethernet_rx_avail(struct net *net, struct nic_data *nic)
|
||||
{
|
||||
if (net == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
+ * If we're using a tap device, check in with that and
|
||||
+ * that's it.
|
||||
+ */
|
||||
+ if (net->tapdev) {
|
||||
+ net_tap_rx_avail(net);
|
||||
+ return net_ethernet_rx(net, nic, NULL, NULL);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
* If the network is distributed across multiple emulator processes,
|
||||
* then receive incoming packets from those processes.
|
||||
*/
|
||||
@@ -282,7 +291,7 @@ int net_ethernet_rx_avail(struct net *ne
|
||||
for (i=0; i<net->n_nics; i++) {
|
||||
struct ethernet_packet_link *lp;
|
||||
lp = net_allocate_ethernet_packet_link(
|
||||
- net, net->nic_extra[i], res);
|
||||
+ net, net->nic_data[i], res);
|
||||
memcpy(lp->data, buf, res);
|
||||
}
|
||||
}
|
||||
@@ -290,10 +299,10 @@ int net_ethernet_rx_avail(struct net *ne
|
||||
}
|
||||
|
||||
/* IP protocol specific: */
|
||||
- net_udp_rx_avail(net, extra);
|
||||
- net_tcp_rx_avail(net, extra);
|
||||
+ net_udp_rx_avail(net, nic);
|
||||
+ net_tcp_rx_avail(net, nic);
|
||||
|
||||
- return net_ethernet_rx(net, extra, NULL, NULL);
|
||||
+ return net_ethernet_rx(net, nic, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -309,11 +318,11 @@ int net_ethernet_rx_avail(struct net *ne
|
||||
* available, 0 is returned.
|
||||
*
|
||||
* If packetp is NULL, then the search is aborted as soon as a packet with
|
||||
- * the correct 'extra' field is found, and a 1 is returned, but as packetp
|
||||
+ * the correct 'nic' field is found, and a 1 is returned, but as packetp
|
||||
* is NULL we can't return the actual packet. (This is the internal form
|
||||
* if net_ethernet_rx_avail().)
|
||||
*/
|
||||
-int net_ethernet_rx(struct net *net, void *extra,
|
||||
+int net_ethernet_rx(struct net *net, struct nic_data *nic,
|
||||
unsigned char **packetp, int *lenp)
|
||||
{
|
||||
struct ethernet_packet_link *lp, *prev;
|
||||
@@ -321,12 +330,12 @@ int net_ethernet_rx(struct net *net, voi
|
||||
if (net == NULL)
|
||||
return 0;
|
||||
|
||||
- /* Find the first packet which has the right 'extra' field. */
|
||||
+ /* Find the first packet which has the right 'nic' field. */
|
||||
|
||||
lp = net->first_ethernet_packet;
|
||||
prev = NULL;
|
||||
while (lp != NULL) {
|
||||
- if (lp->extra == extra) {
|
||||
+ if (lp->nic == nic) {
|
||||
/* We found a packet for this controller! */
|
||||
if (packetp == NULL || lenp == NULL)
|
||||
return 1;
|
||||
@@ -368,7 +377,7 @@ int net_ethernet_rx(struct net *net, voi
|
||||
* If the packet can be handled here, it will not necessarily be transmitted
|
||||
* to the outside world.
|
||||
*/
|
||||
-void net_ethernet_tx(struct net *net, void *extra,
|
||||
+void net_ethernet_tx(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len)
|
||||
{
|
||||
int i, eth_type, for_the_gateway;
|
||||
@@ -376,8 +385,6 @@ void net_ethernet_tx(struct net *net, vo
|
||||
if (net == NULL)
|
||||
return;
|
||||
|
||||
- for_the_gateway = !memcmp(packet, net->gateway_ethernet_addr, 6);
|
||||
-
|
||||
/* Drop too small packets: */
|
||||
if (len < 20) {
|
||||
fatal("[ net_ethernet_tx: Warning: dropping tiny packet "
|
||||
@@ -386,15 +393,26 @@ void net_ethernet_tx(struct net *net, vo
|
||||
}
|
||||
|
||||
/*
|
||||
+ * If we're using a tap device, we send the packet that way
|
||||
+ * and that's it.
|
||||
+ */
|
||||
+ if (net->tapdev) {
|
||||
+ net_tap_tx(net, nic, packet, len);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for_the_gateway = !memcmp(packet, net->gateway_ethernet_addr, 6);
|
||||
+
|
||||
+ /*
|
||||
* Copy this packet to all other NICs on this network (except if
|
||||
* it is aimed specifically at the gateway's ethernet address):
|
||||
*/
|
||||
- if (!for_the_gateway && extra != NULL && net->n_nics > 0) {
|
||||
+ if (!for_the_gateway && nic != NULL && net->n_nics > 0) {
|
||||
for (i=0; i<net->n_nics; i++)
|
||||
- if (extra != net->nic_extra[i]) {
|
||||
+ if (nic != net->nic_data[i]) {
|
||||
struct ethernet_packet_link *lp;
|
||||
lp = net_allocate_ethernet_packet_link(net,
|
||||
- net->nic_extra[i], len);
|
||||
+ net->nic_data[i], len);
|
||||
|
||||
/* Copy the entire packet: */
|
||||
memcpy(lp->data, packet, len);
|
||||
@@ -438,7 +456,7 @@ void net_ethernet_tx(struct net *net, vo
|
||||
if (eth_type == ETHERTYPE_IP) {
|
||||
/* Routed via the gateway? */
|
||||
if (for_the_gateway) {
|
||||
- net_ip(net, extra, packet, len);
|
||||
+ net_ip(net, nic, packet, len);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -446,7 +464,7 @@ void net_ethernet_tx(struct net *net, vo
|
||||
if (packet[0] == 0xff && packet[1] == 0xff &&
|
||||
packet[2] == 0xff && packet[3] == 0xff &&
|
||||
packet[4] == 0xff && packet[5] == 0xff) {
|
||||
- net_ip_broadcast(net, extra, packet, len);
|
||||
+ net_ip_broadcast(net, nic, packet, len);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -465,13 +483,13 @@ void net_ethernet_tx(struct net *net, vo
|
||||
if (len != 42 && len != 60)
|
||||
fatal("[ net_ethernet_tx: WARNING! unusual "
|
||||
"ARP len (%i) ]\n", len);
|
||||
- net_arp(net, extra, packet + 14, len - 14, 0);
|
||||
+ net_arp(net, nic, packet + 14, len - 14, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* RARP: */
|
||||
if (eth_type == ETHERTYPE_REVARP) {
|
||||
- net_arp(net, extra, packet + 14, len - 14, 1);
|
||||
+ net_arp(net, nic, packet + 14, len - 14, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -595,21 +613,28 @@ static void parse_resolvconf(struct net
|
||||
* Add a NIC to a network. (All NICs on a network will see each other's
|
||||
* packets.)
|
||||
*/
|
||||
-void net_add_nic(struct net *net, void *extra, unsigned char *macaddr)
|
||||
+void net_add_nic(struct net *net, struct nic_data *nic)
|
||||
{
|
||||
if (net == NULL)
|
||||
return;
|
||||
|
||||
- if (extra == NULL) {
|
||||
- fprintf(stderr, "net_add_nic(): extra = NULL\n");
|
||||
+ if (nic == NULL) {
|
||||
+ fprintf(stderr, "net_add_nic(): nic = NULL\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
- net->n_nics ++;
|
||||
- CHECK_ALLOCATION(net->nic_extra = (void **)
|
||||
- realloc(net->nic_extra, sizeof(void *) * net->n_nics));
|
||||
+ /*
|
||||
+ * Set up some of the basics for this NIC. We assume the
|
||||
+ * device has set up all of the other fields.
|
||||
+ */
|
||||
+ nic->net = net;
|
||||
+ nic->promiscuous_mode = 0;
|
||||
+
|
||||
+ net->n_nics++;
|
||||
+ CHECK_ALLOCATION(net->nic_data = (struct nic_data **)
|
||||
+ realloc(net->nic_data, sizeof(struct nic_data *) * net->n_nics));
|
||||
|
||||
- net->nic_extra[net->n_nics - 1] = extra;
|
||||
+ net->nic_data[net->n_nics - 1] = nic;
|
||||
}
|
||||
|
||||
|
||||
@@ -661,6 +686,12 @@ void net_dumpinfo(struct net *net)
|
||||
|
||||
debug_indentation(iadd);
|
||||
|
||||
+ if (net->tapdev) {
|
||||
+ debug("tap device: %s\n", net->tapdev);
|
||||
+ debug_indentation(-iadd);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
debug("simulated network: ");
|
||||
net_debugaddr(&net->netmask_ipv4, NET_ADDR_IPV4);
|
||||
debug("/%i", net->netmask_ipv4_len);
|
||||
@@ -718,6 +749,7 @@ void net_dumpinfo(struct net *net)
|
||||
* On failure, exit() is called.
|
||||
*/
|
||||
struct net *net_init(struct emul *emul, int init_flags,
|
||||
+ const char *tapdev,
|
||||
const char *ipv4addr, int netipv4len,
|
||||
char **remote, int n_remote, int local_port,
|
||||
const char *settings_prefix)
|
||||
@@ -734,6 +766,19 @@ struct net *net_init(struct emul *emul,
|
||||
/* Sane defaults: */
|
||||
net->timestamp = 0;
|
||||
net->first_ethernet_packet = net->last_ethernet_packet = NULL;
|
||||
+ net->tapdev = NULL;
|
||||
+ net->tap_fd = -1;
|
||||
+
|
||||
+ /*
|
||||
+ * If we're using a tap device, attempt to initialize it and
|
||||
+ * none of the other stuff.
|
||||
+ */
|
||||
+ if (tapdev) {
|
||||
+ if (! net_tap_init(net, tapdev))
|
||||
+ exit(1);
|
||||
+ net_dumpinfo(net);
|
||||
+ return net;
|
||||
+ }
|
||||
|
||||
#ifdef HAVE_INET_PTON
|
||||
res = inet_pton(AF_INET, ipv4addr, &net->netmask_ipv4);
|
|
@ -1,150 +0,0 @@
|
|||
$NetBSD: patch-src_net_net_ether.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add some generic Ethernet routines used for address filtering.
|
||||
|
||||
--- /dev/null 2020-10-05 22:44:11.028207457 +0000
|
||||
+++ src/net/net_ether.cc 2020-10-05 23:01:48.744053911 +0000
|
||||
@@ -0,0 +1,143 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2020 Jason R. Thorpe. All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. The name of the author may not be used to endorse or promote products
|
||||
+ * derived from this software without specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+ * SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Common Ethernet support routines.
|
||||
+ */
|
||||
+
|
||||
+#include <sys/types.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include "misc.h"
|
||||
+#include "net.h"
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * net_ether_eq():
|
||||
+ *
|
||||
+ * Compare two Ethernet addresses for equality.
|
||||
+ */
|
||||
+int net_ether_eq(const uint8_t *a1, const uint8_t *a2)
|
||||
+{
|
||||
+
|
||||
+ return a1[5] == a2[5] &&
|
||||
+ a1[4] == a2[4] &&
|
||||
+ a1[3] == a2[3] &&
|
||||
+ a1[2] == a2[2] &&
|
||||
+ a1[1] == a2[1] &&
|
||||
+ a1[0] == a2[0];
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * net_ether_broadcast():
|
||||
+ *
|
||||
+ * Returns 1 if the specified destination address is the Ethernet
|
||||
+ * broadcast address.
|
||||
+ */
|
||||
+int net_ether_broadcast(const uint8_t *a)
|
||||
+{
|
||||
+ static const uint8_t ether_broadcast[6] =
|
||||
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
+
|
||||
+ return net_ether_eq(a, ether_broadcast);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * net_ether_multicast():
|
||||
+ *
|
||||
+ * Returns 1 if the specfied destination address is an Ethernet
|
||||
+ * multicast address.
|
||||
+ *
|
||||
+ * Note that this also matches Ethernet broadcast, which is just
|
||||
+ * a special case of multicast.
|
||||
+ */
|
||||
+int net_ether_multicast(const uint8_t *a)
|
||||
+{
|
||||
+ return (*a & 0x01);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Copyright (c) 1982, 1989, 1993
|
||||
+ * The Regents of the University of California. All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. Neither the name of the University nor the names of its contributors
|
||||
+ * may be used to endorse or promote products derived from this software
|
||||
+ * without specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+ * SUCH DAMAGE.
|
||||
+ *
|
||||
+ * @(#)if_ethersubr.c 8.2 (Berkeley) 4/4/96
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * net_ether_crc32_le():
|
||||
+ *
|
||||
+ * Fast table-driven little-endian Ethernet CRC generator.
|
||||
+ */
|
||||
+uint32_t net_ether_crc32_le(const uint8_t *buf, size_t len)
|
||||
+{
|
||||
+ static const uint32_t crctab[] = {
|
||||
+ 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
||||
+ 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
||||
+ 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
|
||||
+ };
|
||||
+ uint32_t crc;
|
||||
+ size_t i;
|
||||
+
|
||||
+ crc = 0xffffffffU; /* initial value */
|
||||
+
|
||||
+ for (i = 0; i < len; i++) {
|
||||
+ crc ^= buf[i];
|
||||
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
|
||||
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
|
||||
+ }
|
||||
+
|
||||
+ return crc;
|
||||
+}
|
|
@ -1,238 +0,0 @@
|
|||
$NetBSD: patch-src_net_net_ip.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add support for tap(4)-based networking.
|
||||
|
||||
--- src/net/net_ip.cc.orig 2020-10-05 23:02:21.375165006 +0000
|
||||
+++ src/net/net_ip.cc 2020-10-05 23:02:33.181030722 +0000
|
||||
@@ -155,7 +155,7 @@ void net_ip_tcp_checksum(unsigned char *
|
||||
* 1c1d1e1f202122232425262728292a2b
|
||||
* 2c2d2e2f3031323334353637
|
||||
*/
|
||||
-static void net_ip_icmp(struct net *net, void *extra,
|
||||
+static void net_ip_icmp(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len)
|
||||
{
|
||||
int type;
|
||||
@@ -166,7 +166,7 @@ static void net_ip_icmp(struct net *net,
|
||||
switch (type) {
|
||||
case 8: /* ECHO request */
|
||||
debug("[ ICMP echo ]\n");
|
||||
- lp = net_allocate_ethernet_packet_link(net, extra, len);
|
||||
+ lp = net_allocate_ethernet_packet_link(net, nic, len);
|
||||
|
||||
/* Copy the old packet first: */
|
||||
memcpy(lp->data + 12, packet + 12, len - 12);
|
||||
@@ -225,7 +225,7 @@ static void tcp_closeconnection(struct n
|
||||
* This creates an ethernet packet for the guest OS with an ACK to the
|
||||
* initial SYN packet.
|
||||
*/
|
||||
-void net_ip_tcp_connectionreply(struct net *net, void *extra,
|
||||
+void net_ip_tcp_connectionreply(struct net *net, struct nic_data *nic,
|
||||
int con_id, int connecting, unsigned char *data, int datalen, int rst)
|
||||
{
|
||||
struct ethernet_packet_link *lp;
|
||||
@@ -238,7 +238,7 @@ void net_ip_tcp_connectionreply(struct n
|
||||
net->tcp_connections[con_id].tcp_id ++;
|
||||
tcp_length = 20 + option_len + datalen;
|
||||
ip_len = 20 + tcp_length;
|
||||
- lp = net_allocate_ethernet_packet_link(net, extra, 14 + ip_len);
|
||||
+ lp = net_allocate_ethernet_packet_link(net, nic, 14 + ip_len);
|
||||
|
||||
/* Ethernet header: */
|
||||
memcpy(lp->data + 0, net->tcp_connections[con_id].ethernet_address, 6);
|
||||
@@ -376,7 +376,7 @@ void net_ip_tcp_connectionreply(struct n
|
||||
* http://www.networksorcery.com/enp/protocol/tcp.htm
|
||||
* http://www.tcpipguide.com/free/t_TCPIPTransmissionControlProtocolTCP.htm
|
||||
*/
|
||||
-static void net_ip_tcp(struct net *net, void *extra,
|
||||
+static void net_ip_tcp(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len)
|
||||
{
|
||||
int con_id, free_con_id, i, res;
|
||||
@@ -585,7 +585,7 @@ static void net_ip_tcp(struct net *net,
|
||||
|
||||
if (rst) {
|
||||
debug("[ 'rst': disconnecting TCP connection %i ]\n", con_id);
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 1);
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 0, NULL, 0, 1);
|
||||
tcp_closeconnection(net, con_id);
|
||||
return;
|
||||
}
|
||||
@@ -596,7 +596,7 @@ static void net_ip_tcp(struct net *net,
|
||||
"connection %i ]\n", con_id);
|
||||
|
||||
/* Send an RST? (TODO, this is wrong...) */
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 1);
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 0, NULL, 0, 1);
|
||||
|
||||
/* ... and forget about this connection: */
|
||||
tcp_closeconnection(net, con_id);
|
||||
@@ -610,7 +610,7 @@ static void net_ip_tcp(struct net *net,
|
||||
|
||||
/* Send an ACK: */
|
||||
net->tcp_connections[con_id].state = TCP_OUTSIDE_CONNECTED;
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 0, NULL, 0, 0);
|
||||
net->tcp_connections[con_id].state = TCP_OUTSIDE_DISCONNECTED2;
|
||||
return;
|
||||
}
|
||||
@@ -620,7 +620,7 @@ static void net_ip_tcp(struct net *net,
|
||||
con_id);
|
||||
|
||||
/* Send ACK: */
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 0, NULL, 0, 0);
|
||||
net->tcp_connections[con_id].state = TCP_OUTSIDE_DISCONNECTED2;
|
||||
|
||||
/* Return and send FIN: */
|
||||
@@ -725,7 +725,7 @@ debug(" all acked\n");
|
||||
|
||||
ret:
|
||||
/* Send an ACK (or FIN) to the guest OS: */
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 0, NULL, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -746,7 +746,7 @@ ret:
|
||||
* srcport=fffc dstport=0035 length=0028 chksum=76b6
|
||||
* 43e20100000100000000000003667470066e6574627364036f726700001c0001
|
||||
*/
|
||||
-static void net_ip_udp(struct net *net, void *extra,
|
||||
+static void net_ip_udp(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len)
|
||||
{
|
||||
int con_id, free_con_id, i, srcport, dstport, udp_len;
|
||||
@@ -882,7 +882,8 @@ static void net_ip_udp(struct net *net,
|
||||
*
|
||||
* Handle an IP packet, coming from the emulated NIC.
|
||||
*/
|
||||
-void net_ip(struct net *net, void *extra, unsigned char *packet, int len)
|
||||
+void net_ip(struct net *net, struct nic_data *nic, unsigned char *packet,
|
||||
+ int len)
|
||||
{
|
||||
#if 1
|
||||
int i;
|
||||
@@ -913,13 +914,13 @@ void net_ip(struct net *net, void *extra
|
||||
/* IPv4: */
|
||||
switch (packet[23]) {
|
||||
case 1: /* ICMP */
|
||||
- net_ip_icmp(net, extra, packet, len);
|
||||
+ net_ip_icmp(net, nic, packet, len);
|
||||
break;
|
||||
case 6: /* TCP */
|
||||
- net_ip_tcp(net, extra, packet, len);
|
||||
+ net_ip_tcp(net, nic, packet, len);
|
||||
break;
|
||||
case 17:/* UDP */
|
||||
- net_ip_udp(net, extra, packet, len);
|
||||
+ net_ip_udp(net, nic, packet, len);
|
||||
break;
|
||||
default:
|
||||
fatal("[ net: IP: UNIMPLEMENTED protocol %i ]\n",
|
||||
@@ -939,7 +940,7 @@ void net_ip(struct net *net, void *extra
|
||||
* Read http://tools.ietf.org/html/rfc2131 for details on DHCP.
|
||||
* (And http://users.telenet.be/mydotcom/library/network/dhcp.htm.)
|
||||
*/
|
||||
-static void net_ip_broadcast_dhcp(struct net *net, void *extra,
|
||||
+static void net_ip_broadcast_dhcp(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len)
|
||||
{
|
||||
/*
|
||||
@@ -1008,7 +1009,7 @@ static void net_ip_broadcast_dhcp(struct
|
||||
fatal(" ]\n");
|
||||
|
||||
reply_len = 307;
|
||||
- lp = net_allocate_ethernet_packet_link(net, extra, reply_len);
|
||||
+ lp = net_allocate_ethernet_packet_link(net, nic, reply_len);
|
||||
|
||||
/* From old packet, copy everything before options field: */
|
||||
memcpy(lp->data, packet, 278);
|
||||
@@ -1130,7 +1131,7 @@ packet = lp->data;
|
||||
* Handle an IP broadcast packet, coming from the emulated NIC.
|
||||
* (This is usually a DHCP request, or similar.)
|
||||
*/
|
||||
-void net_ip_broadcast(struct net *net, void *extra,
|
||||
+void net_ip_broadcast(struct net *net, struct nic_data *nic,
|
||||
unsigned char *packet, int len)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) &net->netmask_ipv4;
|
||||
@@ -1193,7 +1194,7 @@ void net_ip_broadcast(struct net *net, v
|
||||
packet[23] == 0x11 && /* UDP */
|
||||
packet[34] == 0 && packet[35] == 68 && /* DHCP client */
|
||||
packet[36] == 0 && packet[37] == 67) { /* DHCP server */
|
||||
- net_ip_broadcast_dhcp(net, extra, packet, len);
|
||||
+ net_ip_broadcast_dhcp(net, nic, packet, len);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1222,7 +1223,7 @@ void net_ip_broadcast(struct net *net, v
|
||||
*
|
||||
* Receive any available UDP packets (from the outside world).
|
||||
*/
|
||||
-void net_udp_rx_avail(struct net *net, void *extra)
|
||||
+void net_udp_rx_avail(struct net *net, struct nic_data *nic)
|
||||
{
|
||||
int received_packets_this_tick = 0;
|
||||
int max_packets_this_tick = 200;
|
||||
@@ -1326,7 +1327,7 @@ void net_udp_rx_avail(struct net *net, v
|
||||
|
||||
ip_len = 20 + this_packets_data_length;
|
||||
|
||||
- lp = net_allocate_ethernet_packet_link(net, extra,
|
||||
+ lp = net_allocate_ethernet_packet_link(net, nic,
|
||||
14 + 20 + this_packets_data_length);
|
||||
|
||||
/* Ethernet header: */
|
||||
@@ -1381,7 +1382,7 @@ void net_udp_rx_avail(struct net *net, v
|
||||
*
|
||||
* Receive any available TCP packets (from the outside world).
|
||||
*/
|
||||
-void net_tcp_rx_avail(struct net *net, void *extra)
|
||||
+void net_tcp_rx_avail(struct net *net, struct nic_data *nic)
|
||||
{
|
||||
int received_packets_this_tick = 0;
|
||||
int max_packets_this_tick = 200;
|
||||
@@ -1445,7 +1446,7 @@ void net_tcp_rx_avail(struct net *net, v
|
||||
net->tcp_connections[con_id].state =
|
||||
TCP_OUTSIDE_CONNECTED;
|
||||
debug("CHANGING TO TCP_OUTSIDE_CONNECTED\n");
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 1,
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 1,
|
||||
NULL, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1477,7 +1478,7 @@ void net_tcp_rx_avail(struct net *net, v
|
||||
net->tcp_connections[con_id].
|
||||
incoming_buf_seqnr;
|
||||
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id,
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id,
|
||||
0, net->tcp_connections[con_id].
|
||||
incoming_buf,
|
||||
net->tcp_connections[con_id].
|
||||
@@ -1519,21 +1520,21 @@ void net_tcp_rx_avail(struct net *net, v
|
||||
memcpy(net->tcp_connections[con_id].incoming_buf,
|
||||
buf, res);
|
||||
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 0,
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 0,
|
||||
buf, res, 0);
|
||||
} else if (res == 0) {
|
||||
net->tcp_connections[con_id].state =
|
||||
TCP_OUTSIDE_DISCONNECTED;
|
||||
debug("CHANGING TO TCP_OUTSIDE_DISCONNECTED, read"
|
||||
" res=0\n");
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 0,
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 0,
|
||||
NULL, 0, 0);
|
||||
} else {
|
||||
net->tcp_connections[con_id].state =
|
||||
TCP_OUTSIDE_DISCONNECTED;
|
||||
fatal("CHANGING TO TCP_OUTSIDE_DISCONNECTED, "
|
||||
"read res<=0, errno = %i\n", errno);
|
||||
- net_ip_tcp_connectionreply(net, extra, con_id, 0,
|
||||
+ net_ip_tcp_connectionreply(net, nic, con_id, 0,
|
||||
NULL, 0, 0);
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
$NetBSD: patch-src_net_net_tap.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add support for tap(4)-based networking.
|
||||
|
||||
--- /dev/null 2020-10-05 22:44:11.028207457 +0000
|
||||
+++ src/net/net_tap.cc 2020-10-05 23:03:15.768748362 +0000
|
||||
@@ -0,0 +1,185 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2020 Jason R. Thorpe. All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. The name of the author may not be used to endorse or promote products
|
||||
+ * derived from this software without specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+ * SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Support for Ethernet tap interfaces.
|
||||
+ *
|
||||
+ * A single tap instance is used for the entire simulated network.
|
||||
+ * We treat this as sort of virtual Ethernet switch, with the tap
|
||||
+ * being the upstream port. This is very simple, conceptually, and
|
||||
+ * fits in nicely with the rest of the network simulation model in
|
||||
+ * GXemul.
|
||||
+ *
|
||||
+ * Use of the tap interface is completely optional, but if it is used
|
||||
+ * the all of the virtual IP network support is bypassed completely.
|
||||
+ */
|
||||
+
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <string.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include "misc.h"
|
||||
+#include "net.h"
|
||||
+
|
||||
+/*
|
||||
+ * net_tap_rx_for_nic():
|
||||
+ *
|
||||
+ * Receive a packet from the virtual Ethernet switch for this NIC.
|
||||
+ */
|
||||
+static void net_tap_rx_for_nic(struct net *net, struct nic_data *nic,
|
||||
+ unsigned char *buf, ssize_t size)
|
||||
+{
|
||||
+ struct ethernet_packet_link *lp;
|
||||
+
|
||||
+ /*
|
||||
+ * We should deliver to the interface if:
|
||||
+ *
|
||||
+ * ==> The interface is in promiscuous mode.
|
||||
+ * -- or --
|
||||
+ * ==> The packet is broadcast or multicast (the emulated device
|
||||
+ * can further apply a multicast filter if it wishes).
|
||||
+ * -- or --
|
||||
+ * ==> The destination MAC address matches the NIC MAC address.
|
||||
+ *
|
||||
+ * Note that normally a switch would not know if an interface
|
||||
+ * is in promiscuous mode, but this is a bit of extra magic
|
||||
+ * we implement because we can for the sake of convenience.
|
||||
+ * Also, some emulated interfaces may want to see all packets
|
||||
+ * so as to implement their own filtering logic.
|
||||
+ *
|
||||
+ * Also note that testing for multicast also catches the broadcast
|
||||
+ * case.
|
||||
+ */
|
||||
+
|
||||
+ if (nic->promiscuous_mode ||
|
||||
+ net_ether_multicast(buf) || net_ether_eq(nic->mac_address, buf)) {
|
||||
+ lp = net_allocate_ethernet_packet_link(net, nic, (int)size);
|
||||
+ memcpy(lp->data, buf, size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * net_tap_rx_avail():
|
||||
+ *
|
||||
+ * We poll the net-shared tap device and link up any available packets to
|
||||
+ * their destination interfaces, acting like a virtual Ethernet switch.
|
||||
+ */
|
||||
+void net_tap_rx_avail(struct net *net)
|
||||
+{
|
||||
+ int received_packets_this_tick = 0;
|
||||
+ int max_packets_this_tick = 200;
|
||||
+
|
||||
+ for (;;) {
|
||||
+ unsigned char buf[1518];
|
||||
+ ssize_t bytes_read;
|
||||
+ int i;
|
||||
+
|
||||
+ if (received_packets_this_tick > max_packets_this_tick)
|
||||
+ break;
|
||||
+
|
||||
+ /* Read one packet from the tap device. */
|
||||
+ bytes_read = read(net->tap_fd, buf, sizeof(buf));
|
||||
+
|
||||
+ if (bytes_read < 0) {
|
||||
+ /* No more packets available on the tap. */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Drop runt packets now; allow other layers to assume
|
||||
+ * valid Ethernet frames. This really should be 64, but
|
||||
+ * 20 is used in the transmit path.
|
||||
+ */
|
||||
+ if (bytes_read < 20)
|
||||
+ continue;
|
||||
+
|
||||
+ for (i = 0; i < net->n_nics; i++) {
|
||||
+ net_tap_rx_for_nic(net, net->nic_data[i],
|
||||
+ buf, bytes_read);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * net_tap_tx():
|
||||
+ *
|
||||
+ * Transmit an ethernet packet, as seen from the emulated ethernet controller,
|
||||
+ * to the net-shared tap device. Even if the packet is destined only for
|
||||
+ * a NIC on the local virtual Ethernet switch, we always send it to the
|
||||
+ * tap device so that the host system can monitor traffic by running tcpdump
|
||||
+ * on its view of the tap.
|
||||
+ */
|
||||
+void net_tap_tx(struct net *net, struct nic_data *nic,
|
||||
+ unsigned char *packet, int len)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < net->n_nics; i++) {
|
||||
+ if (nic == net->nic_data[i])
|
||||
+ continue;
|
||||
+ net_tap_rx_for_nic(net, net->nic_data[i], packet, len);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Don't bother checking for errors here. The tap driver in the
|
||||
+ * kernel will either take the entire packet or none of it, and
|
||||
+ * there isn't any useful error recovery for us anyway.
|
||||
+ */
|
||||
+ write(net->tap_fd, packet, len);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * net_tap_init():
|
||||
+ *
|
||||
+ * Initialize the tap interface. Returns 1 if successful, 0 otherwise.
|
||||
+ */
|
||||
+int net_tap_init(struct net *net, const char *tapdev)
|
||||
+{
|
||||
+ int fd;
|
||||
+ int one = 1;
|
||||
+
|
||||
+ fd = open(tapdev, O_RDWR);
|
||||
+ if (fd < 0) {
|
||||
+ fatal("[ net: unable to open tap device '%s': %s ]\n",
|
||||
+ tapdev, strerror(errno));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (ioctl(fd, FIONBIO, &one) < 0) {
|
||||
+ fatal("[ net: unable to set non-blocking mode on "
|
||||
+ "tap device '%s': %s ]\n", tapdev, strerror(errno));
|
||||
+ close(fd);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ net->tapdev = strdup(tapdev);
|
||||
+ net->tap_fd = fd;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
|
@ -1,14 +0,0 @@
|
|||
$NetBSD: patch-src_old_main_emul.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add support for tap(4)-based networking.
|
||||
|
||||
--- src/old_main/emul.cc.orig 2020-10-05 23:04:14.559513959 +0000
|
||||
+++ src/old_main/emul.cc 2020-10-05 23:04:26.418738637 +0000
|
||||
@@ -748,6 +748,7 @@ void emul_simple_init(struct emul *emul)
|
||||
|
||||
/* Create a simple network: */
|
||||
emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,
|
||||
+ NULL,
|
||||
NET_DEFAULT_IPV4_MASK,
|
||||
NET_DEFAULT_IPV4_LEN,
|
||||
NULL, 0, 0, NULL);
|
|
@ -1,38 +0,0 @@
|
|||
$NetBSD: patch-src_old_main_emul_parse.cc,v 1.1 2020/10/07 00:43:05 thorpej Exp $
|
||||
|
||||
Add support for tap(4)-based networking.
|
||||
|
||||
--- src/old_main/emul_parse.cc.orig 2020-10-05 23:04:38.529354586 +0000
|
||||
+++ src/old_main/emul_parse.cc 2020-10-05 23:04:50.653298084 +0000
|
||||
@@ -197,6 +197,7 @@ static void read_one_word(FILE *f, char
|
||||
#define PARSESTATE_NET 2
|
||||
#define PARSESTATE_MACHINE 3
|
||||
|
||||
+static char cur_net_tapdev[50];
|
||||
static char cur_net_ipv4net[50];
|
||||
static char cur_net_ipv4len[50];
|
||||
static char cur_net_local_port[10];
|
||||
@@ -315,6 +316,7 @@ static void parse__emul(struct emul *e,
|
||||
line, EXPECT_LEFT_PARENTHESIS);
|
||||
|
||||
/* Default net: */
|
||||
+ strlcpy(cur_net_tapdev, "", sizeof(cur_net_tapdev));
|
||||
strlcpy(cur_net_ipv4net, NET_DEFAULT_IPV4_MASK,
|
||||
sizeof(cur_net_ipv4net));
|
||||
snprintf(cur_net_ipv4len, sizeof(cur_net_ipv4len), "%i",
|
||||
@@ -391,6 +393,7 @@ static void parse__net(struct emul *e, F
|
||||
sizeof(cur_net_local_port));
|
||||
|
||||
e->net = net_init(e, NET_INIT_FLAG_GATEWAY,
|
||||
+ cur_net_tapdev[0] ? cur_net_tapdev : NULL,
|
||||
cur_net_ipv4net, atoi(cur_net_ipv4len),
|
||||
cur_net_remote, cur_net_n_remote,
|
||||
atoi(cur_net_local_port), NULL);
|
||||
@@ -410,6 +413,7 @@ static void parse__net(struct emul *e, F
|
||||
return;
|
||||
}
|
||||
|
||||
+ WORD("tapdev", cur_net_tapdev);
|
||||
WORD("ipv4net", cur_net_ipv4net);
|
||||
WORD("ipv4len", cur_net_ipv4len);
|
||||
WORD("local_port", cur_net_local_port);
|
Loading…
Reference in a new issue