Documentation
¶
Index ¶
- Variables
- type Backoff
- type ContextLogger
- type FieldLogger
- type Logger
- type Metrics
- type NopMetrics
- func (NopMetrics) OnAbort(string, error)
- func (NopMetrics) OnAlarm(string, string, bool)
- func (NopMetrics) OnConnect(string, time.Duration, error)
- func (NopMetrics) OnRecord(string, string, uint16, time.Duration, error)
- func (NopMetrics) OnRetry(string, int, time.Duration, error)
- func (NopMetrics) OnStateChange(string, string, string, error)
Constants ¶
This section is empty.
Variables ¶
var ( // ErrClosed reports an operation on a controller, device, connection // or port that was closed by the application. ErrClosed = errors.New("profinet: closed") // ErrTimeout reports that the peer did not answer within the // configured time: a DCP request, an RPC call, an alarm that was not // acknowledged, or a cyclic consumer whose watchdog expired. ErrTimeout = errors.New("profinet: timeout") // ErrMalformed reports input that cannot be decoded: a frame, a block // or a document that is truncated, has an invalid length, an invalid // field value or trailing data where none is allowed. Network input // that fails to decode is dropped and counted; it never panics. ErrMalformed = errors.New("profinet: malformed") // ErrUnsupported reports a request for a service, option, block type // or feature this implementation (or, for a remote error, the peer) // does not provide. ErrUnsupported = errors.New("profinet: unsupported") // ErrInvalidConfig reports a configuration value that a controller, // device, port or codec cannot be constructed or used with. ErrInvalidConfig = errors.New("profinet: invalid configuration") // ErrInvalidState reports an operation that is not allowed in the // current state of a state machine, for example a record write on an // application relationship that is not established. ErrInvalidState = errors.New("profinet: invalid state") // ErrRejected reports that the peer answered with an error: a PNIO // status other than OK, a DCP block error or an RPC fault or reject. // The typed error that carries the code wraps or matches it. ErrRejected = errors.New("profinet: rejected by peer") // ErrAborted reports that an application relationship ended without // a release: a watchdog expired, the peer sent an abort, the CM // activity timeout elapsed or the link went down. ErrAborted = errors.New("profinet: application relationship aborted") // ErrNotFound reports that no device answered a DCP request for a // station name or MAC address, or that a slot, subslot, record index // or application relationship does not exist. ErrNotFound = errors.New("profinet: not found") // ErrResourceExhausted reports that a bounded resource is used up: // the number of application relationships, a queue, a reassembly // buffer or the number of concurrent requests. ErrResourceExhausted = errors.New("profinet: resource exhausted") // ErrLinkDown reports that the Ethernet link of a port is down. ErrLinkDown = errors.New("profinet: link down") )
Sentinel errors shared by every package of the module. They are usually wrapped with detail; test with errors.Is. Typed errors that carry a PROFINET error code (a PNIO status, a DCP block error, an RPC fault) match one of these as well, so that a caller can test for the class of a failure without knowing the code.
Functions ¶
This section is empty.
Types ¶
type Backoff ¶ added in v0.6.0
Backoff is an exponential backoff: the wait doubles from Min up to Max, and Jitter (0 to 1) spreads it randomly downward by up to that fraction, so that devices that failed together do not retry together.
type ContextLogger ¶
type ContextLogger interface {
Logger
DebugContext(ctx context.Context, msg string, keysAndValues ...any)
InfoContext(ctx context.Context, msg string, keysAndValues ...any)
WarnContext(ctx context.Context, msg string, keysAndValues ...any)
ErrorContext(ctx context.Context, msg string, keysAndValues ...any)
}
ContextLogger extends Logger with context-aware structured logging, so that a handler can pick trace and span identifiers out of the context. When the Logger also implements ContextLogger, entries that belong to a request are logged with the context the request was called with.
type FieldLogger ¶
type FieldLogger interface {
Logger
// With returns a logger that adds the given fields to every entry.
With(keysAndValues ...any) FieldLogger
DebugKV(msg string, keysAndValues ...any)
InfoKV(msg string, keysAndValues ...any)
WarnKV(msg string, keysAndValues ...any)
ErrorKV(msg string, keysAndValues ...any)
}
FieldLogger extends Logger with structured key-value logging. When the Logger given to a controller or device also implements FieldLogger, the library logs through it: every entry is a constant message plus fields such as "component", "station", "ar" and "error", instead of one formatted string. NewSlogLogger returns such a logger.
keysAndValues alternate string keys and values, as in log/slog.
func NewSlogFieldLogger ¶
func NewSlogFieldLogger(h slog.Handler) FieldLogger
NewSlogFieldLogger is NewSlogLogger with the result typed as a FieldLogger, for callers that want to add fields with With before handing the logger to a controller or device. A nil handler returns a no-op logger.
type Logger ¶
type Logger interface {
Debugf(format string, args ...any)
Infof(format string, args ...any)
Warnf(format string, args ...any)
Errorf(format string, args ...any)
}
Logger is the logging interface accepted by controllers, devices and the protocol engines. Implement it to integrate any logging library.
Logging is silent by default. Methods are invoked synchronously on the protocol path and must not block.
func NewSlogLogger ¶
NewSlogLogger wraps a slog.Handler. The result implements FieldLogger and ContextLogger, so the library logs structured fields through it; messages are only built when the handler is enabled for their level. A nil handler returns a no-op logger.
func NewStdLogger ¶
NewStdLogger wraps a standard library logger. Each message is prefixed with its level. A nil l logs to os.Stderr with the standard flags.
type Metrics ¶ added in v0.6.0
type Metrics interface {
// OnStateChange is called for every state change of a controller's
// device lifecycle or of a device's AR. err is the failure that
// caused it, if any.
OnStateChange(station, from, to string, err error)
// OnConnect is called when a Connect completed: on a controller when
// the device answered (or the call failed), on a device when it
// answered a controller. d is the time the Connect took; err is nil
// when the AR was established.
OnConnect(station string, d time.Duration, err error)
// OnAbort is called when an AR ended without a release: a watchdog,
// an abort by the peer, a CM activity timeout, a lost link. err
// matches [ErrAborted] or [ErrTimeout].
OnAbort(station string, err error)
// OnRecord is called after a record access: on a controller a
// ReadRecord, WriteRecord or WriteMultiple call, on a device a request
// it served. op is "read" or "write"; d the time it took; err nil when
// it succeeded.
OnRecord(station, op string, index uint16, d time.Duration, err error)
// OnAlarm is called for every alarm a controller received or a device
// sent; typ is the alarm type's name, high its priority.
OnAlarm(station, typ string, high bool)
// OnRetry is called when a controller schedules the next connection
// attempt to a device after a failure: attempt counts the attempts
// since the device last ran, wait is the backoff before it.
OnRetry(station string, attempt int, wait time.Duration, err error)
}
Metrics is an optional callback interface for observing the application relationships of a controller or a device: their state changes, connects, aborts, record accesses, alarms and reconnection attempts. A nil Metrics disables collection. The counters of each component (OBSERVABILITY.md) complement it.
station names the peer: on a controller the device's NameOfStation, on a device the controller's (CMInitiatorStationName). States are the names the controller's State and the device's ARState print.
The methods are called synchronously on the protocol path, possibly from several goroutines at once; implementations must be safe for concurrent use and must not block (increment a counter, send on a buffered channel). Embed NopMetrics to implement only the callbacks you need and to stay compatible when methods are added.
type NopMetrics ¶ added in v0.6.0
type NopMetrics struct{}
NopMetrics is a Metrics that does nothing. Embed it in your own type.
func (NopMetrics) OnAbort ¶ added in v0.6.0
func (NopMetrics) OnAbort(string, error)
OnAbort does nothing.
func (NopMetrics) OnAlarm ¶ added in v0.6.0
func (NopMetrics) OnAlarm(string, string, bool)
OnAlarm does nothing.
func (NopMetrics) OnConnect ¶ added in v0.6.0
func (NopMetrics) OnConnect(string, time.Duration, error)
OnConnect does nothing.
func (NopMetrics) OnStateChange ¶ added in v0.6.0
func (NopMetrics) OnStateChange(string, string, string, error)
OnStateChange does nothing.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package alarm implements the acyclic real-time transport of PROFINET alarms (RTA, IEC 61158-6-10): the codec of RTA PDUs and the alarm protocol machines of one AR — a sender (APMS) and a receiver (APMR) per priority, with sequence numbers, acknowledgement, retransmission and the ERR PDU that aborts an AR.
|
Package alarm implements the acyclic real-time transport of PROFINET alarms (RTA, IEC 61158-6-10): the codec of RTA PDUs and the alarm protocol machines of one AR — a sender (APMS) and a receiver (APMR) per priority, with sequence numbers, acknowledgement, retransmission and the ERR PDU that aborts an AR. |
|
Package controller implements a PROFINET IO-Controller (conformance class A, RT_CLASS_1/2): it finds its devices by station name with DCP, optionally assigns their IP address, establishes an application relationship with each, parameterizes it, exchanges cyclic IO data, acknowledges alarms, reads and writes records and re-establishes the AR after a failure.
|
Package controller implements a PROFINET IO-Controller (conformance class A, RT_CLASS_1/2): it finds its devices by station name with DCP, optionally assigns their IP address, establishes an application relationship with each, parameterizes it, exchanges cyclic IO data, acknowledges alarms, reads and writes records and re-establishes the AR after a failure. |
|
Package dcp implements the PROFINET Discovery and basic Configuration Protocol (IEC 61158-6-10): the codec of DCP frames and blocks, a requester (Identify, Get, Set, Hello) and a responder for IO-Devices.
|
Package dcp implements the PROFINET Discovery and basic Configuration Protocol (IEC 61158-6-10): the codec of DCP frames and blocks, a requester (Identify, Get, Set, Hello) and a responder for IO-Devices. |
|
Package device implements a PROFINET IO-Device (conformance class A, RT_CLASS_1/2): the DCP responder, the RPC server for Connect, Read, Write, Control and Release, application relationships with their explicit state machine, cyclic input production and output consumption, alarms, diagnosis and identification and maintenance records.
|
Package device implements a PROFINET IO-Device (conformance class A, RT_CLASS_1/2): the DCP responder, the RPC server for Connect, Read, Write, Control and Release, application relationships with their explicit state machine, cyclic input production and output consumption, alarms, diagnosis and identification and maintenance records. |
|
Package ethernet encodes and decodes Ethernet II frames with an optional IEEE 802.1Q tag: the layer every PROFINET frame (DCP, LLDP, RT, alarms) travels on.
|
Package ethernet encodes and decodes Ethernet II frames with an optional IEEE 802.1Q tag: the layer every PROFINET frame (DCP, LLDP, RT, alarms) travels on. |
|
examples
|
|
|
alarms
command
Command alarms shows diagnosis alarms: the device reports a wire break on channel 2 of its input module, the controller receives and acknowledges the alarm and reads the diagnosis, then the diagnosis disappears.
|
Command alarms shows diagnosis alarms: the device reports a wire break on channel 2 of its input module, the controller receives and acknowledges the alarm and reads the diagnosis, then the diagnosis disappears. |
|
chaos
command
Command chaos runs an AR over a virtual network with injected faults (loss, duplication, reordering, corruption, jitter), pulls the cable for a while and shows the controller re-establish the AR and the counters of what happened.
|
Command chaos runs an AR over a virtual network with injected faults (loss, duplication, reordering, corruption, jitter), pulls the cable for a while and shows the controller re-establish the AR and the counters of what happened. |
|
controller
command
Command controller runs an IO-Controller on a real network interface and connects the example device (examples/device, or any device with the same configuration):
|
Command controller runs an IO-Controller on a real network interface and connects the example device (examples/device, or any device with the same configuration): |
|
device
command
Command device runs the example IO-Device on a real network interface:
|
Command device runs the example IO-Device on a real network interface: |
|
discovery
command
Command discovery starts three IO-Devices on a virtual network, one of them without a name or address, finds them with DCP Identify, names and addresses the new one explicitly, and shows the LLDP neighbors.
|
Command discovery starts three IO-Devices on a virtual network, one of them without a name or address, finds them with DCP Identify, names and addresses the new one explicitly, and shows the LLDP neighbors. |
|
gsdml
command
Command gsdml writes the GSDML file of the example device to standard output: the file an engineering tool imports to configure the device.
|
Command gsdml writes the GSDML file of the example device to standard output: the file an engineering tool imports to configure the device. |
|
gsdmlimport
command
Command gsdmlimport reads a GSDML file, validates it and converts its device access point into a device model, the expected configuration a controller connects with:
|
Command gsdmlimport reads a GSDML file, validates it and converts its device access point into a device model, the expected configuration a controller connects with: |
|
gsdx
command
Command gsdx inspects an OPC container holding a GSDML file: it builds a small package in a temporary directory (the example device's GSDML, a content types stream and a package relationship), opens it with gsdx, lists its parts and checks the GSDML part.
|
Command gsdx inspects an OPC container holding a GSDML file: it builds a small package in a temporary directory (the example device's GSDML, a content types stream and a package relationship), opens it with gsdx, lists its parts and checks the GSDML part. |
|
hello
command
Command hello shows DCP Hello: the IO-Controller is configured for a device that is not there yet, gives up and waits 30 s before its next attempt.
|
Command hello shows DCP Hello: the IO-Controller is configured for a device that is not there yet, gives up and waits 30 s before its next attempt. |
|
internal/vnetenv
Package vnetenv wires endpoints of a virtual network for the examples: each node is a vnet endpoint with a Layer 2 mux and the module's IP stack, which is all a controller or a device needs.
|
Package vnetenv wires endpoints of a virtual network for the examples: each node is a vnet endpoint with a Layer 2 mux and the module's IP stack, which is all a controller or a device needs. |
|
mrp
command
Command mrp builds a ring of three stations on virtual cables: each has a two-port bridge and an MRP entity; the first is the ring manager, the others are clients.
|
Command mrp builds a ring of three stations on virtual cables: each has a two-port bridge and an MRP entity; the first is the ring manager, the others are clients. |
|
observability
command
Command observability wires a controller and a device to log/slog and to a profinet.Metrics that keeps Prometheus-style counters, pulls the cable and shows the abort, the jittered reconnection backoff and the counters.
|
Command observability wires a controller and a device to log/slog and to a profinet.Metrics that keeps Prometheus-style counters, pulls the cable and shows the abort, the jittered reconnection backoff and the counters. |
|
quickstart
command
Command quickstart runs an IO-Controller and an IO-Device on a virtual Ethernet network in one process: the controller finds the device with DCP, establishes an application relationship, writes a parameter and exchanges cyclic data, then releases the AR.
|
Command quickstart runs an IO-Controller and an IO-Device on a virtual Ethernet network in one process: the controller finds the device with DCP, establishes an application relationship, writes a parameter and exchanges cyclic data, then releases the AR. |
|
records
command
Command records shows the acyclic services an engineering tool and a controller use: ReadImplicit without an AR (I&M0, the real configuration), a device access AR to write I&M1 and a parameter record, and, within a controller's AR, WriteMultiple and the diagnosis.
|
Command records shows the acyclic services an engineering tool and a controller use: ReadImplicit without an AR (I&M0, the real configuration), a device access AR to write I&M1 and a parameter record, and, within a controller's AR, WriteMultiple and the diagnosis. |
|
topology
command
Command topology starts three IO-Devices that learn their neighbors with LLDP, then reads the port data (PDRealData, index 0xF841) of each with ReadImplicit, as an engineering tool draws the topology.
|
Command topology starts three IO-Devices that learn their neighbors with LLDP, then reads the port data (PDRealData, index 0xF841) of each with ReadImplicit, as an engineering tool draws the topology. |
|
Package gsdml reads, validates and writes GSDML (General Station Description Markup Language) files, the XML device descriptions of PROFINET IO devices, and converts between them and the device models of package model.
|
Package gsdml reads, validates and writes GSDML (General Station Description Markup Language) files, the XML device descriptions of PROFINET IO devices, and converts between them and the device models of package model. |
|
gsdx
Package gsdx inspects GSDX containers: Open Packaging Conventions (OPC) packages, ISO/IEC 29500-2 / Ecma-376 Part 2, which are public.
|
Package gsdx inspects GSDX containers: Open Packaging Conventions (OPC) packages, ISO/IEC 29500-2 / Ecma-376 Part 2, which are public. |
|
internal
|
|
|
cmd/gengsdml
command
Command gengsdml generates the GSDML document types of package gsdml (gsdml/zz_generated.go) and their reference (gsdml/SCHEMA.md) from the catalog gsdml/schema/catalog.json.
|
Command gengsdml generates the GSDML document types of package gsdml (gsdml/zz_generated.go) and their reference (gsdml/SCHEMA.md) from the catalog gsdml/schema/catalog.json. |
|
cmd/l2bench
command
Command l2bench measures go-profinet's Linux transport on a veth pair (scripts/l2-bench.sh creates one in a container): it is a measurement tool, not a test, and it asserts nothing.
|
Command l2bench measures go-profinet's Linux transport on a veth pair (scripts/l2-bench.sh creates one in a container): it is a measurement tool, not a test, and it asserts nothing. |
|
xsd
Package xsd reads the element and attribute declarations of a set of XML Schema files: which attributes each element name has (and whether they are required) and which child elements it may contain.
|
Package xsd reads the element and attribute declarations of a set of XML Schema files: which attributes each element name has (and whether they are required) and which child elements it may contain. |
|
interop
|
|
|
otfnode
command
Command otfnode is go-profinet's side of the interoperability tests: it runs in a Linux container on the same network as a reference stack of otfabric/profinet-interop and acts as IO-Controller, IO-Device or DCP tool on a real interface (AF_PACKET), printing JSON.
|
Command otfnode is go-profinet's side of the interoperability tests: it runs in a Linux container on the same network as a reference stack of otfabric/profinet-interop and acts as IO-Controller, IO-Device or DCP tool on a real interface (AF_PACKET), printing JSON. |
|
Package l2 defines the Layer 2 port abstraction PROFINET runs on and a demultiplexer that shares one port between the protocol engines (DCP, LLDP, cyclic RT, alarms, the IP stack of a virtual network).
|
Package l2 defines the Layer 2 port abstraction PROFINET runs on and a demultiplexer that shares one port between the protocol engines (DCP, LLDP, cyclic RT, alarms, the IP stack of a virtual network). |
|
afpacket
Package afpacket is the Linux backend of l2.Port: a raw AF_PACKET socket bound to one network interface.
|
Package afpacket is the Linux backend of l2.Port: a raw AF_PACKET socket bound to one network interface. |
|
bpf
Package bpf is the macOS, FreeBSD, NetBSD and DragonFly backend of l2.Port: a Berkeley Packet Filter device (/dev/bpf*) attached to one network interface.
|
Package bpf is the macOS, FreeBSD, NetBSD and DragonFly backend of l2.Port: a Berkeley Packet Filter device (/dev/bpf*) attached to one network interface. |
|
bridge
Package bridge is the switch of a multiport device: a learning Ethernet bridge between its physical ports, with the device's interface attached as one more port (the "CPU port").
|
Package bridge is the switch of a multiport device: a learning Ethernet bridge between its physical ports, with the device's interface attached as one more port (the "CPU port"). |
|
npcap
Package npcap is the Windows backend of l2.Port, on the Npcap driver (https://npcap.com), which must be installed separately (its licence does not allow redistributing it).
|
Package npcap is the Windows backend of l2.Port, on the Npcap driver (https://npcap.com), which must be installed separately (its licence does not allow redistributing it). |
|
osport
Package osport opens an l2.Port on a network interface with the backend of the operating system: AF_PACKET on Linux (package l2/afpacket), BPF on macOS and the BSDs (package l2/bpf) and Npcap on Windows (package l2/npcap).
|
Package osport opens an l2.Port on a network interface with the backend of the operating system: AF_PACKET on Linux (package l2/afpacket), BPF on macOS and the BSDs (package l2/bpf) and Npcap on Windows (package l2/npcap). |
|
Package lldp implements the Link Layer Discovery Protocol (IEEE 802.1AB) with the organizationally specific TLVs PROFINET uses (IEC 61158-6-10: OUI 00-0E-CF) and the IEEE 802.3 MAC/PHY TLV: the frame codec, and an agent that announces the local port and keeps a table of neighbors with expiry.
|
Package lldp implements the Link Layer Discovery Protocol (IEEE 802.1AB) with the organizationally specific TLVs PROFINET uses (IEC 61158-6-10: OUI 00-0E-CF) and the IEEE 802.3 MAC/PHY TLV: the frame codec, and an agent that announces the local port and keeps a table of neighbors with expiry. |
|
Package model describes a PROFINET IO device in Go: its identity, the device access point, the modules plugged into its slots and the submodules with their IO data and parameter records.
|
Package model describes a PROFINET IO device in Go: its identity, the device access point, the modules plugged into its slots and the submodules with their IO data and parameter records. |
|
Package mrp encodes and decodes the frames of the Media Redundancy Protocol (IEC 62439-2) that PROFINET rings use: MRP_Test, MRP_TopologyChange, MRP_LinkDown and MRP_LinkUp with MRP_Common and MRP_Option.
|
Package mrp encodes and decodes the frames of the Media Redundancy Protocol (IEC 62439-2) that PROFINET rings use: MRP_Test, MRP_TopologyChange, MRP_LinkDown and MRP_LinkUp with MRP_Common and MRP_Option. |
|
Package netstack is a minimal IPv4 stack (ARP, IPv4 without fragments, UDP) on an l2.Mux.
|
Package netstack is a minimal IPv4 stack (ARP, IPv4 without fragments, UDP) on an l2.Mux. |
|
Package pcap writes and reads capture files in the classic libpcap format with the Ethernet link type, so that traffic of the virtual network (and of the real backends) can be inspected with Wireshark or tshark.
|
Package pcap writes and reads capture files in the classic libpcap format with the Ethernet link type, so that traffic of the virtual network (and of the real backends) can be inspected with Wireshark or tshark. |
|
Package pnio encodes and decodes the PROFINET IO application layer (IEC 61158-6-10): the blocks of the connect, control, release, read and write services, the NDR argument headers they travel in over RPC, the PNIO status, identification and maintenance records, diagnosis data, alarm notifications and identification data.
|
Package pnio encodes and decodes the PROFINET IO application layer (IEC 61158-6-10): the blocks of the connect, control, release, read and write services, the NDR argument headers they travel in over RPC, the PNIO status, identification and maintenance records, diagnosis data, alarm notifications and identification data. |
|
Package ptcp encodes and decodes the delay frames of the Precision Transparent Clock Protocol (PTCP, IEC 61158-6-10): DelayReq and the delay responses with which neighbors measure the line delay of a link.
|
Package ptcp encodes and decodes the delay frames of the Precision Transparent Clock Protocol (PTCP, IEC 61158-6-10): DelayReq and the delay responses with which neighbors measure the line delay of a link. |
|
Package rpc implements the connectionless DCE RPC protocol (DCE 1.1 RPC, chapter 12, "CL") that PROFINET IO uses for its acyclic services over UDP: the packet header, fragmentation and reassembly, a client with retransmission and an at-most-once server with a response cache.
|
Package rpc implements the connectionless DCE RPC protocol (DCE 1.1 RPC, chapter 12, "CL") that PROFINET IO uses for its acyclic services over UDP: the packet header, fragmentation and reassembly, a client with retransmission and an at-most-once server with a response cache. |
|
Package rt implements cyclic real-time PROFINET IO (RT_CLASS_1/2, unsynchronized): the codec of cyclic frames, the layout of the IO data in a frame, providers and consumers with their watchdog, and the scheduler that drives them.
|
Package rt implements cyclic real-time PROFINET IO (RT_CLASS_1/2, unsynchronized): the codec of cyclic frames, the layout of the IO data in a frame, providers and consumers with their watchdog, and the scheduler that drives them. |
|
Package snmp implements a read-only SNMPv1/SNMPv2c agent (RFC 1157, RFC 1901, RFC 3416) with the BER codec of its messages (RFC 3417) and helpers for the MIB modules a PROFINET device of conformance class B offers: the system, interfaces and snmp groups of MIB-II (RFC 1213, RFC 3418, RFC 2863) and the LLDP-MIB of IEEE 802.1AB-2005.
|
Package snmp implements a read-only SNMPv1/SNMPv2c agent (RFC 1157, RFC 1901, RFC 3416) with the BER codec of its messages (RFC 3417) and helpers for the MIB modules a PROFINET device of conformance class B offers: the system, interfaces and snmp groups of MIB-II (RFC 1213, RFC 3418, RFC 2863) and the LLDP-MIB of IEEE 802.1AB-2005. |
|
Package store is the optional persistence of go-profinet: the values a device must keep across a restart (its permanent station name and IP suite, its I&M records) are saved in a Store under a key.
|
Package store is the optional persistence of go-profinet: the values a device must keep across a restart (its permanent station name and IP suite, its I&M records) are saved in a Store under a key. |
|
Package vnet is an in-memory Ethernet network: a switch with any number of endpoints, each an [l2.Port] with its own MAC address, that carries serialized Ethernet frames between them.
|
Package vnet is an in-memory Ethernet network: a switch with any number of endpoints, each an [l2.Port] with its own MAC address, that carries serialized Ethernet frames between them. |