Skip to main content

EtherNet/IP

Pull

Synopsis​

Director reads one controller that speaks EtherNet/IP: the tags of a Rockwell Automation ControlLogix or CompactLogix, of a Micro800, or of another controller that reads its tags by their names over CIP. Nothing is installed on the controller or beside it: Director connects as an HMI or a data collector would, over TCP (port 44818), sends read requests, and writes what comes back as ECS records. It never writes to the controller: the only services it sends read a tag, read who the controller is, or open and close the connection the reads go over.

One device, one controller. Monitoring twelve controllers takes twelve devices. The device holds one session with its controller, and one connection to its CPU, and sends its requests over them one at a time. A controller has few connections to spare.

What to read is declared by datasets. A controller's tags have names, and a client reads them by name, so the device's datasets are your own, each a table of tags read on the dataset's own interval. For example, the line's count, the DINT Line1_Count; a tank's level, the REAL Tank3.Level; or a program's speed, Program:MainProgram.Speed. Each tag is declared with the type it is read as, and a tag of another type is left out rather than read as what it is not.

The device dials the controller and binds no port, so any number of EtherNet/IP devices, on one Director or several, can name port 44818, and none of them blocks a listener. The device runs on Director only; no agent runs it.

It is the counterpart, for Rockwell controllers, of the Siemens S7 device.

note

The EtherNet/IP device needs Director 2.4.1 or later. With no Director or cluster at that version selected, the wizard shows EtherNet/IP devices are unavailable on directors or clusters below version 2.4.1 and the device cannot be created.

Schema​

- id: <numeric>
name: <string>
description: <string>
type: ethernet_ip
tags: <string[]>
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
port: <numeric>
route: <string>
connected_messaging: <boolean>
connection_size: <numeric>
timeout: <numeric>
max_tags_per_request: <numeric>
definitions: <definition[]>

Configuration​

The following fields are used to define the device:

Device​

FieldRequiredDefaultDescription
idY-Unique numeric identifier
nameY-Device name
descriptionN-Optional description
typeY-Must be ethernet_ip
tagsN-Optional tags
pipelinesN-Optional pre-processor pipelines
statusNtrueEnable/disable the device

Connection​

FieldRequiredDefaultDescription
addressY-Host name or IP address of the controller's Ethernet module. An IPv6 address can be written as it is or in brackets. A wildcard address (0.0.0.0, ::) is refused, and so is a port written into the address: the port is its own field.
portN44818EtherNet/IP's port for explicit messages, from 1 to 65535
routeN1,0The way from the Ethernet module to the CPU, as a Logix path writes it: pairs of a port and a link address, or direct (also none) for no route. Left out or empty is 1,0. See Routes.
connected_messagingNtrueReads over a CIP connection to the CPU, falling back to unconnected messages when the controller refuses one. false reads with unconnected messages from the start. See Connected and Unconnected Messaging.
connection_sizeN4002The size of the connection the device asks for, in bytes, from 500 to 4002. A controller that refuses a Large Forward Open is asked for 504. Not used with connected_messaging: false, and the device's log says so.
timeoutN10Seconds a connect and each request wait for their answer, from 1 to 300
max_tags_per_requestN200How many tags one request reads at most, from 1 to 200, for a controller that takes fewer. The size of a message may make it fewer still. See Requests.

A device that fails these checks does not start, and its state is Configuration error with the reason. Examples are a missing or wildcard address, a route that is not pairs of a port and a link address, or a connection size or a timeout out of range. The device stops before it dials anything.

Connection​

Routes​

Director dials the controller's Ethernet module and registers an EtherNet/IP session. The module that answers is not always the CPU: in a ControlLogix chassis the Ethernet module is one card and the CPU another. So a request names the route from the one to the other, as a Logix path does: pairs of a port of the module the request leaves by and the link address it goes to on that port.

routeWhat it reaches
1,0Port 1, the backplane, and the CPU in slot 0: a CompactLogix's CPU, and most often a ControlLogix's. The default.
1,3The CPU in slot 3 of the chassis
directNo route: the Ethernet port is the controller's own. A Micro800.
1,3,2,10.20.0.5,1,0Through the Ethernet module in slot 3, out of its port 2 to the module at 10.20.0.5, and to the CPU in slot 0 of that chassis

A port is a number from 1 to 65535. A link address is a number from 0 to 255 (a slot, a node) or, for a port on an Ethernet network, an IP address or a host name. A route has at most 8 hops and takes at most 64 bytes of a request.

tip

The route is the setting most often wrong. A ControlLogix CPU is a card of its own, so its route names its slot (1,<slot>); a CompactLogix's is 1,0; a Micro800 takes direct.

Who the Controller Is​

Once the session stands, the device reads the controller's Identity object, the way its tags are read. The answer names the controller in the device's log, for example the controller is a 1756-L83E/B, revision 32.11, and proves the route: a route that leads nowhere is found here, before any tag is read, and is a Connection error that says to check the route.

Connected and Unconnected Messaging​

  • Connected (the default). The device opens a class 3 connection to the CPU along the route and reads over it. It first asks for a Large Forward Open of connection_size bytes (4002, the largest a Logix controller takes), and for a Forward Open of 504 bytes when the controller refuses that, as a Micro800 and older firmware do. A connection_size of 511 or less is asked for with a Forward Open at once. The connection is closed, and the session ended, when the device stops, so the controller is not left a connection to time out.
  • Unconnected. A controller that refuses a connection altogether, because it has none to spare or none at all, is read with unconnected messages instead, each carried along the route by the controller's Connection Manager. The device's log says so, with the controller's reason. connected_messaging: false reads this way from the start.
note

A controller's connections are a budget. A connected device takes one of the controller's CIP connections for as long as it runs. With connected_messaging: false it takes none, at the cost of smaller messages (504 bytes) and so more requests for a large table.

Idle and Lost Connections​

  • Idle connections. A controller gives up a connection it has not heard on for about two minutes, and answers a request on it with nothing. So the device reopens a connection it has not used for 96 seconds before it sends. A dataset read every five minutes costs two extra short requests a reading, and never a timeout; datasets read every minute or faster keep their connection.
  • Lost sessions. A session the controller closed between two readings is opened again and the reading tried once more, so a reading is not lost to the controller having hung up. A controller that cannot be connected to is tried again at every reading, without limit. The failure is logged once for as long as it lasts, and again when it is over.

External Access​

A Logix controller answers only for tags whose External Access is Read/Write or Read Only. A tag set to None is refused with "access is denied" (status 0x0F), and the device's log says what to change.

Datasets​

The device's definitions are its datasets. In a configuration file each dataset is a definition named ethernet_ip_tag_collector, the device's one dataset type:

DatasetDefinitionDefinition IDKindOne record per
tagethernet_ip_tag_collector32150metricreading of the dataset's table
  • Any number of datasets. Each dataset is a table of its own, read on its own interval, so a device reads as many as are assigned: for example, the line's values every 10 seconds and its alarm bits every 5.
  • Pipelines. A dataset's records enter the pre-processing pipeline the dataset selects, or the device's when it selects none.
  • Nothing assigned is allowed. The device then only checks, every minute, that its controller takes a session, and a connection when it reads over one, so its connection state stays current, and writes nothing.
  • A dataset that cannot be read is left out, with a warning in the device's log that names it and says why: no table, a tag or a type that is missing, or a field named twice. The rest of the device runs. With every dataset assigned to it left out, the device stops with Configuration error.

Dataset Properties​

FieldRequiredDefaultDescription
tableY-The name the dataset's fields sit under in a record (see Records): letters, digits, and underscores, at most 64, not starting with a digit. table is reserved.
intervalN60Seconds between readings, 1 or more. A duration such as 5m is also read.
labelsN-An object of names and values written on every record as ECS labels. At most 32; a name is letters, digits, underscores, and hyphens, and a value is text, a number, or a switch of at most 256 characters.
pipeline_nameNthe device'sThe pre-processing pipeline the dataset's records enter

Fields​

A dataset's inputs are its fields, at most 512. Each needs a name, unique in the table: letters, digits, and underscores, at most 64, not starting with a digit. An input with status: false is left out, and not validated.

FieldRequiredDescription
tagYThe tag, as the controller's program names it. See Tags.
typeYThe type the tag is read as, which has to be the one the controller holds it as. See Types.

Tags​

WrittenReads
Line1_CountA tag of the controller's scope
Program:MainProgram.SpeedA tag of a program
Tank3.LevelA member of a structure
Counts[4], Grid[1,2]An element of an array, of up to three dimensions
Zones[2].SetpointA member of an element
Status.3One bit of a whole number, the lowest bit 0, up to 63. Its type is bool.

A name is letters, digits, and underscores, not starting with a digit, at most 128 characters; a tag is at most 255 characters. Names are sent as they are written, and a controller reads them in any case.

A field reads one value. An array is read an element a field, and a structure a member a field: a tag that is a whole structure is refused with name the member to read. A Logix STRING is the exception: it is read as text.

Types​

TypeThe controller's typeWritten as
boolBOOLtrue or false
sint, int, dint, lintSINT, INT, DINT, LINTA whole number, signed
usint, uint, udint, ulintUSINT, UINT, UDINT, ULINTA whole number
byte, word, dword, lwordBYTE, WORD, DWORD, LWORDA whole number, the bit string's bits
real, lrealREAL, LREALA number. A REAL is written as the shortest decimal that reads back as it.
stringSTRINGText: a Logix STRING, a string type of the program's own, or a Micro800's
warning

The type has to be the one the controller holds the tag as. Every answer names the tag's type, and the device holds it against the field's: a field declared dint whose tag is a REAL is left out of the record, and the device's log names both types, rather than reading it as a wrong number.

Three things are read out of another type, by design:

  • One bit of a tag (Status.3, type bool) is read out of the whole number the controller answers, of any of the whole-number and bit-string types.
  • An element of a BOOL array (Alarms[37], type bool) is read out of the 32-bit word a Logix controller keeps it in. No setting is needed. A controller that keeps each BOOL on its own is found out, and the element read by its own index from the next reading on.
  • A string is a structure in a Logix controller, a length and its characters, which the device reads as text, so a string type of the program's own is read as a STRING is. Characters are read as ISO 8859-1, a byte each.

A float that is not a number (a NaN or an infinity) holds no value: the field is left out, and the device's log says so.

Requests​

A field is one read of one tag, so a tag the controller refuses is the only one left out. The reads of a dataset are packed into Multiple Service Packets in the order the fields are declared, each holding as many as fit:

  • at most max_tags_per_request;
  • within the size of a message, for the request and for its answer. Over a connection a message is the connection's size less two bytes (4000, or 502); without one it is 504 bytes. Over a large connection, a table of two hundred DINTs is one request.

What the controller says of a request changes how the next ones are cut, in the same reading:

  • A controller that takes no Multiple Service Packet, as a Micro800 does by Rockwell's manuals, says so the first time it is asked for several tags. Its tags are read one a request from then on. No setting is needed, but expect a table of two hundred tags to be two hundred requests a reading there.
  • A request whose answer does not fit a message is read a tag a request from then on.
  • A tag whose value does not fit a message, such as a long string of the program's own, is read whole in as many requests as it takes, up to 64 KiB.

The requests are planned for the limits of the current session, and planned again when a new session has others.

Readings​

  • At start the device reads every dataset once.
  • Each dataset on its own interval after that, from the start of one reading to the start of the next.
  • Datasets due at the same time are read one after the other over the one session. A reading that takes longer than its interval delays the next, which starts a moment after it ends.

Records​

Every record is one ECS 8.11 document with the following fields:

FieldValue
@timestampThe reading's time
ecs.version8.11.0
event.moduleethernet_ip
event.datasetethernet_ip.tag
event.kindmetric
event.category, event.typehost, info
observer.nameThe device's name in the console
observer.hostnameThe Director's host name
observer.vendor, observer.productVirtualMetric, EtherNet/IP
server.address, server.portThe address the device is configured with, and its port
server.ipThe address, when it is an IP address
network.protocol, network.transportenip, tcp
labels.<name>The dataset's labels, when it has any
ethernet_ip.tag.tableThe dataset's table
ethernet_ip.tag.<table>.<field>The value of each field that was read, as Types writes it

The values sit under the table's name, so two tables can name a field alike with different types without one mapping conflicting with the other.

{
"@timestamp": "2026-10-14T12:00:00Z",
"ecs": { "version": "8.11.0" },
"event": {
"module": "ethernet_ip",
"dataset": "ethernet_ip.tag",
"kind": "metric",
"category": ["host"],
"type": ["info"]
},
"observer": {
"vendor": "VirtualMetric",
"product": "EtherNet/IP",
"name": "packaging-line-plc",
"hostname": "director01"
},
"server": { "address": "192.0.2.50", "ip": "192.0.2.50", "port": 44818 },
"network": { "protocol": "enip", "transport": "tcp" },
"labels": { "machine": "packer-1" },
"ethernet_ip": {
"tag": {
"table": "line",
"line": {
"speed": 12.5,
"packs": 48211,
"running": true,
"recipe": "cola"
}
}
}
}

A field with no value is absent from that record: a tag the controller refused, one of another type than the field declares, or one whose bytes hold no value of its type. The device's log says so once, with the reason, for as long as it lasts. A record with no field is not written.

Device State​

The connection state follows the controller, and the first of these that holds is the state:

  • Connected while the controller answers any tag of the device's datasets with a value. A device with no dataset assigned is Connected while its controller takes a session, and a connection when the device reads over one.
  • Configuration error while the controller answers the device's requests, but with no value for any tag of any dataset: tags it does not have, types it does not hold them as, External Access set to None, or a route that ends at the wrong module. The message names the refusal and what to change. A configuration that cannot run is a Configuration error too (see Configuration).
  • Connection error while the controller cannot be connected to, its route leads nowhere, or it answered none of the requests of any dataset at its latest reading.

The state follows every dataset's latest reading, not only the datasets of the reading in progress. A record that could not be written, or a failure inside one dataset, affects that dataset alone and does not change the device's state.

What the controller answers a tag with, and what to do about it:

StatusSaidTo do
0x04, 0x05It does not understand the path, or the path names nothingCheck the tag's spelling, its scope (Program:<program>.<tag>), and its index.
0x0FAccess is deniedThe tag's External Access is None, or the controller's security does not let it be read.
0x08It does not have the serviceThe route has to end at the CPU of a Logix or a Micro800 controller.
0xFF, extended 0x2105The element is past the end of the tagThe index is past the end of the array.
0x01, extended 0x0204, 0x0311, 0x0312, 0x0315, 0x0318The request could not be carried along the routeCheck the route: 1 and the CPU's slot, or direct.
note

The EtherNet/IP device is not simulated. A dataset's records are the values of your own tags, a shape a generated sample cannot stand in for.

Not Supported​

  • Implicit (class 1) I/O, and anything over UDP, such as port 2222.
  • PCCC controllers: PLC-5, SLC 500, and MicroLogix, which have no tags to read by name.
  • Reading a whole structure or a whole array as one field; reading a tag list or a structure's template from the controller; times and dates as their own types.
  • CIP Security (TLS on port 2221).
  • Writing: no tag is written, and no service that changes the controller is sent.

Compatibility​

The device follows The CIP Networks Library and Rockwell's Logix 5000 Data Access manual. When a controller does not accept a request the device prefers, such as a Multiple Service Packet or a Large Forward Open on a Micro800, the device falls back to a simpler request. A controller that answers in a way the device does not expect is read more slowly, or the device reports why it cannot read a tag. It does not return a wrong value.

Console​

In the console, go to Fleet Management > Devices > EtherNet/IP, listed under Protocols beside ctrlX CORE and Siemens S7, and click Add new device. The wizard's steps are:

  1. General settings, as on every device.
  2. Connection settings: Address, Port, Route to the CPU, and Connected messaging.
    • Route to the CPU is a choice, and writes route as the table below shows.
    • Connected messaging is a toggle, enabled by default. Connection size shows only while it is enabled, and connection_size is not written while it is disabled.
  3. Advanced settings: Timeout and Maximum tags per request.
  4. Data collection: the EtherNet/IP datasets the device reads.
  5. Review and create.
Route to the CPUShowsWrites
Backplane slot (the default)Slot, 0 by defaultroute: "1,<slot>"
No routeNothingroute: direct
Custom routeRouteThe route as typed, such as 1,3,2,192.0.2.60,1,0

The device's page has the same tabs, and Data collection. A device whose stored route is 1,3 opens on Backplane slot with Slot 3, and one that names no route opens on Backplane slot with Slot 0; one stored with direct or none opens on No route; any other route opens on Custom route.

An EtherNet/IP dataset is created in Fleet Management > Datasets as the type EtherNet/IP Tags; see Management. Its settings are Table name, Interval (Optional), Tags, Labels, and Pre-processing pipeline (Optional). A tag's row is Field (the name its value is written under), Data type, and Tag. The Data type list shows the types as the controller's software writes them (BOOL, SINT, INT, DINT, LINT, USINT, UINT, UDINT, ULINT, REAL, LREAL, BYTE, WORD, DWORD, LWORD, STRING) and writes them in lower case (type: dint); see Types.

The console refuses two addresses the Director would take: a host name whose labels are not letters, digits, and hyphens, and an IPv6 address with a zone. Its checks of routes and tags are otherwise the Director's.

Examples​

ControlLogix​

Reading the packaging line's values every 10 seconds and its alarm bits every 5, from a ControlLogix whose CPU is in slot 2...

- id: 685200101
name: packaging-line-plc
description: ControlLogix of the packaging line
type: ethernet_ip
status: true
properties:
address: "192.0.2.50"
route: "1,2"
timeout: 10
definitions:
- name: ethernet_ip_tag_collector
status: true
properties:
table: line
interval: 10
labels:
machine: packer-1
location: hall-b
inputs:
- name: speed
properties: { tag: "Program:MainProgram.Speed", type: real }
- name: packs
properties: { tag: Line1_Count, type: dint }
- name: running
properties: { tag: Line1_Status.0, type: bool }
- name: total_energy
properties: { tag: Energy.Total, type: lreal }
- name: recipe
properties: { tag: Recipe_Name, type: string }
- name: zone_2_setpoint
properties: { tag: "Zones[2].Setpoint", type: real }
- name: ethernet_ip_tag_collector
status: true
properties:
table: alarms
interval: 5
inputs:
- name: door_open
properties: { tag: "Alarms[0]", type: bool }
- name: overtemperature
properties: { tag: "Alarms[1]", type: bool }
- name: alarm_word
properties: { tag: Alarm_Word, type: dint }

Micro800​

Reading a Micro850, whose Ethernet port is the controller's own, so it is reached with no route. It reads one tag a request, which the device finds out...

- id: 685200102
name: pump-station-micro850
description: Micro850 of the pump station
type: ethernet_ip
status: true
properties:
address: "192.0.2.60"
route: direct
timeout: 5
definitions:
- name: ethernet_ip_tag_collector
status: true
properties:
table: pumps
interval: 15
inputs:
- name: pump_1_on
properties: { tag: Pump1_Run, type: bool }
- name: level
properties: { tag: Tank_Level, type: real }
- name: starts
properties: { tag: Pump1_Starts, type: udint }

Second Chassis, Unconnected​

Reading a CPU in a second chassis, through the Ethernet module in slot 3 of the chassis Director connects to, with unconnected messages alone, so it takes none of that controller's connections...

- id: 685200103
name: boiler-house-plc
description: ControlLogix of the boiler house, behind the line's chassis
type: ethernet_ip
status: true
properties:
address: "plc-line.plant.example.com"
route: "1,3,2,10.20.0.5,1,0"
connected_messaging: false
definitions:
- name: ethernet_ip_tag_collector
status: true
properties:
table: boiler
interval: 30
inputs:
- name: steam_pressure
properties: { tag: "Program:Boiler.Steam_Pressure", type: real }
- name: burner_on
properties: { tag: "Program:Boiler.Burner.Run", type: bool }