# Rockwell EtherNet/IP

> Connect Allen-Bradley Logix controllers over EtherNet/IP (CIP) - controller tag names, byte offsets, atomic CIP types and network discovery.

The **Rockwell EtherNet/IP** driver talks to Allen-Bradley / Rockwell Logix
controllers (ControlLogix, CompactLogix) over EtherNet/IP with CIP tag
addressing. You address values by the controller tag name declared in the
Logix project — no register map involved. Add a device under the Rockwell
EtherNet/IP driver in the [Connector](connector); the panel shows only the
fields this protocol uses.

## Connection {#connection}

| Field | Meaning | Default |
| --- | --- | --- |
| **Host** | IP address or host name of the controller's Ethernet port. | empty |
| **Slot** | Which position of the chassis the controller is seated in, counted from 0. | 0 |
| **Poll interval (ms)** | Device-wide read period for tags that do not override it. | 1,000 |

There is no port field: EtherNet/IP uses its standard TCP port 44818. The CIP
route is the backplane plus the **Slot**, so a controller seated anywhere in
the chassis is reachable; a discovered controller starts at slot 0 and the
field is where you correct it. There is no rack field: a CIP route carries no
rack number. Requests time out after 10 seconds. The device header shows the
assembled endpoint, for example `eip://192.168.0.10:0`, where the number after
the address is the slot.

Each tag may set its own **Poll interval (ms)**; a tag value of 0 falls back
to the device interval.

## Addressing {#addressing}

A Rockwell tag is addressed by two fields in the tag's Source card:

| Field | Meaning | Accepted values | Default |
| --- | --- | --- | --- |
| **Controller tag** | The tag name as declared in the controller. Required. | free text | empty |
| **Offset in tag (bytes, bits for BOOL)** | Where inside that tag's data the value sits: a byte offset, or a bit offset for Boolean tags. | 0–255 | 0 |

The driver opens the named controller tag and picks the value out of its data
buffer at the offset. For a plain atomic tag the offset stays 0. The offset is
what lets one controller tag serve several channels: a DINT at the start of a
structure is offset 0, the REAL four bytes later is offset 4, and for a
Boolean tag the offset counts bits instead of bytes.

| To read | Controller tag | Offset | Data type |
| --- | --- | --- | --- |
| A controller-scope DINT `Counter` | `Counter` | 0 | Int32 |
| A program-scope DINT in `Main` | `Program:Main.Counter` | 0 | Int32 |
| A REAL array element `Temps[2]` | `Temps[2]` | 0 | Float |
| The second DINT inside structure `Recipe` | `Recipe` | 4 | Int32 |
| Bit 3 of the data in `Flags` | `Flags` | 3 | Boolean |

The name reaches the controller whole, periods included, and a read and a
write of the same tag land in the same place. That is what makes a
program-scoped name such as `Program:Main.Counter` work. A dotted member path
(`MyUdt.Member`) is resolved by the controller when the controller publishes
that member by name; where it does not, name the base controller-scope tag and
reach inside it with the byte offset instead, which always works. The Source
card's read-only **Source address (wire)** line shows the assembled address as
you edit.

## Data types {#data-types}

Every atomic CIP type is available as a tag **Data type**:

| Data type | CIP type | Size |
| --- | --- | --- |
| Boolean | BOOL | 1 bit at the bit offset |
| SByte | SINT | 1 byte |
| Byte | USINT | 1 byte |
| Int16 | INT | 2 bytes |
| UInt16 | UINT | 2 bytes |
| Int32 | DINT | 4 bytes |
| UInt32 | UDINT | 4 bytes |
| Int64 | LINT | 8 bytes |
| UInt64 | ULINT | 8 bytes |
| Float | REAL | 4 bytes |
| Double | LREAL | 8 bytes |

Structures and UDTs are not supported: only the atomic types above can be
read or written, which is why the byte offset exists to reach members inside
them. String is deliberately absent from the picker — a Logix STRING is not an
atomic type but a structure of a length and an 82-byte array, and the driver
can neither read nor write one. Byte order on the wire is CIP's own
little-endian and is handled automatically; there is no byte-order option.

## Writes {#writes}

Tags whose **Access** is Read and write or Write only can be written. A write
reads the controller tag, changes the addressed bytes (or the addressed bit
for Boolean), and writes it back. A new tag starts as Read only.

## Discovery {#discovery}

The Connector's Discover button broadcasts a CIP List Identity request on
**every network this computer is on** and keeps listening until 10 seconds pass
with no new answer. The scan names those networks while it runs, so a result of
zero says where the question actually went: a station with virtual adapters for
machines, WSL or a VPN often has more networks than the operator expects, and
candidates may arrive from one of them.

Interfaces that cannot carry the request are skipped: anything not up, loopback
and tunnel adapters, and an address the interface gave itself because nothing
answered DHCP (169.254.x.x). Only a reply that is a controller's own identity
answer becomes a candidate device, named `eip://` plus its address; anything
else answering on the EtherNet/IP port is ignored and said so in the journal.
For each candidate the scan then reads the controller-scope tag list and offers
its atomic tags as candidate channels, each with offset 0.

Discovery discards what the driver cannot poll: structure and UDT tags
(Logix STRINGs included) are dropped, and `Program:`, `Task:` and `Map:`
entries are skipped. A controller on a network this computer is not on does not
answer the broadcast; add it by hand.

## Good to know {#good-to-know}

- Every request to the controller times out after 10 seconds, and the
  discovery listen window closes after 10 seconds of silence.
- The driver opens each controller tag once and keeps it open while the device
  is connected, so a controller with dozens of tags is read over the sessions it
  already has instead of opening and closing one per reading. A reading that
  fails lets its tag go, and the next one opens it again by name.
- Renaming a tag in the Logix project silently breaks the channel; the tag then
  reads as bad quality until the configured name matches again.
