|
|
Rocker Network Switch Register Programming Guide
|
|
|
************************************************
|
|
|
|
|
|
..
|
|
|
Copyright (c) Scott Feldman <sfeldma@gmail.com>
|
|
|
Copyright (c) Neil Horman <nhorman@tuxdriver.com>
|
|
|
Version 0.11, 12/29/2014
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
(at your option) any later version.
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
Introduction
|
|
|
============
|
|
|
|
|
|
Overview
|
|
|
--------
|
|
|
|
|
|
This document describes the hardware/software interface for the Rocker switch
|
|
|
device. The intended audience is authors of OS drivers and device emulation
|
|
|
software.
|
|
|
|
|
|
Notations and Conventions
|
|
|
-------------------------
|
|
|
|
|
|
* In register descriptions, [n:m] indicates a range from bit n to bit m,
|
|
|
inclusive.
|
|
|
* Use of leading 0x indicates a hexadecimal number.
|
|
|
* Use of leading 0b indicates a binary number.
|
|
|
* The use of RSVD or Reserved indicates that a bit or field is reserved for
|
|
|
future use.
|
|
|
* Field width is in bytes, unless otherwise noted.
|
|
|
* Register are (R) read-only, (R/W) read/write, (W) write-only, or (COR) clear
|
|
|
on read
|
|
|
* TLV values in network-byte-order are designated with (N).
|
|
|
|
|
|
|
|
|
PCI Configuration Registers
|
|
|
===========================
|
|
|
|
|
|
PCI Configuration Space
|
|
|
-----------------------
|
|
|
|
|
|
Each switch instance registers as a PCI device with PCI configuration space::
|
|
|
|
|
|
offset width description value
|
|
|
---------------------------------------------
|
|
|
0x0 2 Vendor ID 0x1b36
|
|
|
0x2 2 Device ID 0x0006
|
|
|
0x4 4 Command/Status
|
|
|
0x8 1 Revision ID 0x01
|
|
|
0x9 3 Class code 0x2800
|
|
|
0xC 1 Cache line size
|
|
|
0xD 1 Latency timer
|
|
|
0xE 1 Header type
|
|
|
0xF 1 Built-in self test
|
|
|
0x10 4 Base address low
|
|
|
0x14 4 Base address high
|
|
|
0x18-28 Reserved
|
|
|
0x2C 2 Subsystem vendor ID *
|
|
|
0x2E 2 Subsystem ID *
|
|
|
0x30-38 Reserved
|
|
|
0x3C 1 Interrupt line
|
|
|
0x3D 1 Interrupt pin 0x00
|
|
|
0x3E 1 Min grant 0x00
|
|
|
0x3D 1 Max latency 0x00
|
|
|
0x40 1 TRDY timeout
|
|
|
0x41 1 Retry count
|
|
|
0x42 2 Reserved
|
|
|
|
|
|
* Assigned by sub-system implementation
|
|
|
|
|
|
Memory-Mapped Register Space
|
|
|
============================
|
|
|
|
|
|
There are two memory-mapped BARs. BAR0 maps device register space and is
|
|
|
0x2000 in size. BAR1 maps MSI-X vector and PBA tables and is also 0x2000 in
|
|
|
size, allowing for 256 MSI-X vectors.
|
|
|
|
|
|
All registers are 4 or 8 bytes long. It is assumed host software will access 4
|
|
|
byte registers with one 4-byte access, and 8 byte registers with either two
|
|
|
4-byte accesses or a single 8-byte access. In the case of two 4-byte accesses,
|
|
|
access must be lower and then upper 4-bytes, in that order.
|
|
|
|
|
|
BAR0 device register space is organized as follows::
|
|
|
|
|
|
offset description
|
|
|
------------------------------------------------------
|
|
|
0x0000-0x000f Bogus registers to catch misbehaving
|
|
|
drivers. Writes do nothing. Reads
|
|
|
back as 0xDEADBABE.
|
|
|
0x0010-0x00ff Test registers
|
|
|
0x0300-0x03ff General purpose registers
|
|
|
0x1000-0x1fff Descriptor control
|
|
|
|
|
|
Holes in register space are reserved. Writes to reserved registers do nothing.
|
|
|
Reads to reserved registers read back as 0.
|
|
|
|
|
|
No fancy stuff like write-combining is enabled on any of the registers.
|
|
|
|
|
|
BAR1 MSI-X register space is organized as follows::
|
|
|
|
|
|
offset description
|
|
|
------------------------------------------------------
|
|
|
0x0000-0x0fff MSI-X vector table (256 vectors total)
|
|
|
0x1000-0x1fff MSI-X PBA table
|
|
|
|
|
|
|
|
|
Interrupts, DMA, and Endianness
|
|
|
===============================
|
|
|
|
|
|
PCI Interrupts
|
|
|
--------------
|
|
|
|
|
|
The device supports only MSI-X interrupts. BAR1 memory-mapped region contains
|
|
|
the MSI-X vector and PBA tables, with support for up to 256 MSI-X vectors.
|
|
|
|
|
|
The vector assignment is::
|
|
|
|
|
|
vector description
|
|
|
-----------------------------------------------------
|
|
|
0 Command descriptor ring completion
|
|
|
1 Event descriptor ring completion
|
|
|
2 Test operation completion
|
|
|
3 RSVD
|
|
|
4-255 Tx and Rx descriptor ring completion
|
|
|
Tx vector is even
|
|
|
Rx vector is odd
|
|
|
|
|
|
A MSI-X vector table entry is 16 bytes::
|
|
|
|
|
|
field offset width description
|
|
|
-------------------------------------------------------------
|
|
|
lower_addr 0x0 4 [31:2] message address[31:2]
|
|
|
[1:0] Rsvd (4 byte alignment
|
|
|
required)
|
|
|
upper_addr 0x4 4 [31:19] Rsvd
|
|
|
[14:0] message address[46:32]
|
|
|
data 0x8 4 message data[31:0]
|
|
|
control 0xc 4 [31:1] Rsvd
|
|
|
[0] mask (0 = enable,
|
|
|
1 = masked)
|
|
|
|
|
|
Software should install the Interrupt Service Routine (ISR) before any ports
|
|
|
are enabled or any commands are issued on the command ring.
|
|
|
|
|
|
DMA Operations
|
|
|
--------------
|
|
|
|
|
|
DMA operations are used for packet DMA to/from the CPU, command and event
|
|
|
processing. Command processing includes statistical counters and table dumps,
|
|
|
table insertion/deletion, and more. Event processing provides an async
|
|
|
notification method for device-originating events. Each DMA operation has a
|
|
|
set of control registers to manage a descriptor ring. The descriptor rings are
|
|
|
allocated from contiguous host DMA-able memory and registers specify the rings
|
|
|
base address, size and current head and tail indices. Software always writes
|
|
|
the head, and hardware always writes the tail.
|
|
|
|
|
|
The higher-order bit of DMA_DESC_COMP_ERR is used to mark hardware completion
|
|
|
of a descriptor. Software will clear this bit when posting a descriptor to the
|
|
|
ring, and hardware will set this bit when the descriptor is complete.
|
|
|
|
|
|
Descriptor ring sizes must be a power of 2 and range from 2 to 64K entries.
|
|
|
Descriptor rings' base address must be 8-byte aligned. Descriptors must be
|
|
|
packed within ring. Each descriptor in each ring must also be aligned on an 8
|
|
|
byte boundary. Each descriptor ring will have these registers::
|
|
|
|
|
|
DMA_DESC_xxx_BASE_ADDR, offset 0x1000 + (x * 32), 64-bit, (R/W)
|
|
|
DMA_DESC_xxx_SIZE, offset 0x1008 + (x * 32), 32-bit, (R/W)
|
|
|
DMA_DESC_xxx_HEAD, offset 0x100c + (x * 32), 32-bit, (R/W)
|
|
|
DMA_DESC_xxx_TAIL, offset 0x1010 + (x * 32), 32-bit, (R)
|
|
|
DMA_DESC_xxx_CTRL, offset 0x1014 + (x * 32), 32-bit, (W)
|
|
|
DMA_DESC_xxx_CREDITS, offset 0x1018 + (x * 32), 32-bit, (R/W)
|
|
|
DMA_DESC_xxx_RSVD1, offset 0x101c + (x * 32), 32-bit, (R/W)
|
|
|
|
|
|
Where x is descriptor ring index::
|
|
|
|
|
|
index ring
|
|
|
--------------------
|
|
|
0 CMD
|
|
|
1 EVENT
|
|
|
2 TX (port 0)
|
|
|
3 RX (port 0)
|
|
|
4 TX (port 1)
|
|
|
5 RX (port 1)
|
|
|
.
|
|
|
.
|
|
|
.
|
|
|
124 TX (port 61)
|
|
|
125 RX (port 61)
|
|
|
126 Resv
|
|
|
127 Resv
|
|
|
|
|
|
Writing BASE_ADDR or SIZE will reset HEAD and TAIL to zero. HEAD cannot be
|
|
|
written past TAIL. To do so would wrap the ring. An empty ring is when HEAD
|
|
|
== TAIL. A full ring is when HEAD is one position behind TAIL. Both HEAD and
|
|
|
TAIL increment and modulo wrap at the ring size.
|
|
|
|
|
|
CTRL register bits::
|
|
|
|
|
|
bit name description
|
|
|
------------------------------------------------------------------------
|
|
|
[0] CTRL_RESET Reset the descriptor ring
|
|
|
[1:31] Reserved
|
|
|
|
|
|
All descriptor types share some common fields::
|
|
|
|
|
|
field width description
|
|
|
-------------------------------------------------------------------
|
|
|
DMA_DESC_BUF_ADDR 8 Phys addr of desc payload, 8-byte
|
|
|
aligned
|
|
|
DMA_DESC_COOKIE 8 Desc cookie for completion matching,
|
|
|
upper-most bit is reserved
|
|
|
DMA_DESC_BUF_SIZE 2 Desc payload size in bytes
|
|
|
DMA_DESC_TLV_SIZE 2 Desc payload total size in bytes
|
|
|
used for TLVs. Must be <=
|
|
|
DMA_DESC_BUF_SIZE.
|
|
|
DMA_DESC_COMP_ERR 2 Completion status of associated
|
|
|
desc payload. High order bit is
|
|
|
clear on new descs, toggled by
|
|
|
hw for completed items.
|
|
|
|
|
|
To support forward- and backward-compatibility, descriptor and completion
|
|
|
payloads are specified in TLV format. Fields are packed with Type=field name,
|
|
|
Length=field length, and Value=field value. Software will ignore unknown fields
|
|
|
filled in by the switch. Likewise, the switch will ignore unknown fields
|
|
|
filled in by software.
|
|
|
|
|
|
Descriptor payload buffer is 8-byte aligned and TLVs are 8-byte aligned. The
|
|
|
value within a TLV is also 8-byte aligned. The (packed, 8 byte) TLV header is::
|
|
|
|
|
|
field width description
|
|
|
-----------------------------
|
|
|
type 4 TLV type
|
|
|
len 2 TLV value length
|
|
|
pad 2 Reserved
|
|
|
|
|
|
The alignment requirements for descriptors and TLVs are to avoid unaligned
|
|
|
access exceptions in software. Note that the payload for each TLV is also
|
|
|
8 byte aligned.
|
|
|
|
|
|
Figure 1 shows an example descriptor buffer with two TLVs::
|
|
|
|
|
|
<------- 8 bytes ------->
|
|
|
|
|
|
8-byte +––––+ +–––––––––––+–––––+–––––+ +–+
|
|
|
align | type | len | pad | TLV#1 hdr |
|
|
|
+–––––––––––+–––––+–––––+ (len=22) |
|
|
|
| | |
|
|
|
| value | TVL#1 value |
|
|
|
| | (padded to 8-byte |
|
|
|
| +–––––+ alignment) |
|
|
|
| |/////| |
|
|
|
8-byte +––––+ +–––––––––––+–––––––––––+ |
|
|
|
align | type | len | pad | TLV#2 hdr DESC_BUF_SIZE
|
|
|
+–––––+–––––+–––––+–––––+ (len=2) |
|
|
|
|value|/////////////////| TLV#2 value |
|
|
|
+–––––+/////////////////| |
|
|
|
|///////////////////////| |
|
|
|
|///////////////////////| |
|
|
|
|///////////////////////| |
|
|
|
|////////unused/////////| |
|
|
|
|////////space//////////| |
|
|
|
|///////////////////////| |
|
|
|
|///////////////////////| |
|
|
|
|///////////////////////| |
|
|
|
+–––––––––––––––––––––––+ +–+
|
|
|
|
|
|
fig. 1
|
|
|
|
|
|
TLVs can be nested within the NEST TLV type.
|
|
|
|
|
|
Interrupt credits
|
|
|
^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
MSI-X vectors used for descriptor ring completions use a credit mechanism for
|
|
|
efficient device, PCIe bus, OS and driver operations. Each descriptor ring has
|
|
|
a credit count which represents the number of outstanding descriptors to be
|
|
|
processed by the driver. As the device marks descriptors complete, the credit
|
|
|
count is incremented. As the driver processes those outstanding descriptors,
|
|
|
it returns credits back to the device. This way, the device knows the driver's
|
|
|
progress and can make decisions about when to fire the next interrupt or not.
|
|
|
When the credit count is zero, and the first descriptors are posted for the
|
|
|
driver, a single interrupt is fired. Once the interrupt is fired, the
|
|
|
interrupt is disabled (auto-masked*). In response to the interrupt, the driver
|
|
|
will process descriptors and PIO write a returned credit value for that
|
|
|
descriptor ring. If the driver returns all credits (the driver caught up with
|
|
|
the device and there is no outstanding work), then the interrupt is unmasked,
|
|
|
but not fired. If only partial credits are returned, the interrupt remains
|
|
|
masked but the device generates an interrupt, signaling the driver that more
|
|
|
outstanding work is available.
|
|
|
|
|
|
(* this masking is unrelated to the MSI-X interrupt mask register)
|
|
|
|
|
|
Endianness
|
|
|
----------
|
|
|
|
|
|
Device registers are hard-coded to little-endian (LE). The driver should
|
|
|
convert to/from host endianness to LE for device register accesses.
|
|
|
|
|
|
Descriptors are LE. Descriptor buffer TLVs will have LE type and length
|
|
|
fields, but the value field can either be LE or network-byte-order, depending
|
|
|
on context. TLV values containing network packet data will be in network-byte
|
|
|
order. A TLV value containing a field or mask used to compare against network
|
|
|
packet data is network-byte order. For example, flow match fields (and masks)
|
|
|
are network-byte-order since they're matched directly, byte-by-byte, against
|
|
|
network packet data. All non-network-packet TLV multi-byte values will be LE.
|
|
|
|
|
|
TLV values in network-byte-order are designated with (N).
|
|
|
|
|
|
|
|
|
Test Registers
|
|
|
==============
|
|
|
|
|
|
Rocker has several test registers to support troubleshooting register access,
|
|
|
interrupt generation, and DMA operations::
|
|
|
|
|
|
TEST_REG, offset 0x0010, 32-bit (R/W)
|
|
|
TEST_REG64, offset 0x0018, 64-bit (R/W)
|
|
|
TEST_IRQ, offset 0x0020, 32-bit (R/W)
|
|
|
TEST_DMA_ADDR, offset 0x0028, 64-bit (R/W)
|
|
|
TEST_DMA_SIZE, offset 0x0030, 32-bit (R/W)
|
|
|
TEST_DMA_CTRL, offset 0x0034, 32-bit (R/W)
|
|
|
|
|
|
Reads to TEST_REG and TEST_REG64 will read a value equal to twice the last
|
|
|
value written to the register. The 32-bit and 64-bit versions are for testing
|
|
|
32-bit and 64-bit host accesses.
|
|
|
|
|
|
A vector can be written to TEST_IRQ and the device will generate an interrupt
|
|
|
for that vector.
|
|
|
|
|
|
To test basic DMA operations, allocate a DMA-able host buffer and put the
|
|
|
buffer address into TEST_DMA_ADDR and size into TEST_DMA_SIZE. Then, write to
|
|
|
TEST_DMA_CTRL to manipulate the buffer contents. TEST_DMA_CTRL operations are::
|
|
|
|
|
|
operation value description
|
|
|
-----------------------------------------------------------
|
|
|
TEST_DMA_CTRL_CLEAR 1 clear buffer
|
|
|
TEST_DMA_CTRL_FILL 2 fill buffer bytes with 0x96
|
|
|
TEST_DMA_CTRL_INVERT 4 invert bytes in buffer
|
|
|
|
|
|
Various buffer address and sizes should be tested to verify no address boundary
|
|
|
issue exists. In particular, buffers that start on odd-8-byte boundary and/or
|
|
|
span multiple PAGE sizes should be tested.
|
|
|
|
|
|
|
|
|
Ports
|
|
|
=====
|
|
|
|
|
|
Physical and Logical Ports
|
|
|
------------------------------------
|
|
|
|
|
|
The switch supports up to 62 physical (front-panel) ports. Register
|
|
|
PORT_PHYS_COUNT returns the actual number of physical ports available::
|
|
|
|
|
|
PORT_PHYS_COUNT, offset 0x0304, 32-bit, (R)
|
|
|
|
|
|
In addition to front-panel ports, the switch supports logical ports for
|
|
|
tunnels.
|
|
|
|
|
|
Front-panel ports and logical tunnel ports are mapped into a single 32-bit port
|
|
|
space. A special CPU port is assigned port 0. The front-panel ports are
|
|
|
mapped to ports 1-62. A special loopback port is assigned port 63. Logical
|
|
|
tunnel ports are assigned ports 0x0001000-0x0001ffff.
|
|
|
To summarize the port assignments::
|
|
|
|
|
|
port mapping
|
|
|
-------------------------------------------------------
|
|
|
0 CPU port (for packets to/from host CPU)
|
|
|
1-62 front-panel physical ports
|
|
|
63 loopback port
|
|
|
64-0x0000ffff RSVD
|
|
|
0x00010000-0x0001ffff logical tunnel ports
|
|
|
0x00020000-0xffffffff RSVD
|
|
|
|
|
|
Physical Port Mode
|
|
|
------------------
|
|
|
|
|
|
Switch front-panel ports operate in a mode. Currently, the only mode is
|
|
|
OF-DPA. OF-DPA[1] mode is based on OpenFlow Data Plane Abstraction (OF-DPA)
|
|
|
Abstract Switch Specification, Version 1.0, from Broadcom Corporation. To
|
|
|
set/get the mode for front-panel ports, see port settings, below.
|
|
|
|
|
|
Port Settings
|
|
|
-------------
|
|
|
|
|
|
Link status for all front-panel ports is available via PORT_PHYS_LINK_STATUS::
|
|
|
|
|
|
PORT_PHYS_LINK_STATUS, offset 0x0310, 64-bit, (R)
|
|
|
|
|
|
Value is port bitmap. Bits 0 and 63 always read 0. Bits 1-62
|
|
|
read 1 for link UP and 0 for link DOWN for respective front-panel ports.
|
|
|
|
|
|
Other properties for front-panel ports are available via DMA CMD descriptors::
|
|
|
|
|
|
Get PORT_SETTINGS descriptor:
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------
|
|
|
PORT_SETTINGS 2 CMD_GET
|
|
|
PPORT 4 Physical port #
|
|
|
|
|
|
Get PORT_SETTINGS completion:
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------
|
|
|
PPORT 4 Physical port #
|
|
|
SPEED 4 Current port interface speed, in Mbps
|
|
|
DUPLEX 1 1 = Full, 0 = Half
|
|
|
AUTONEG 1 1 = enabled, 0 = disabled
|
|
|
MACADDR 6 Port MAC address
|
|
|
MODE 1 0 = OF-DPA
|
|
|
LEARNING 1 MAC address learning on port
|
|
|
1 = enabled
|
|
|
0 = disabled
|
|
|
PHYS_NAME <var> Physical port name (string)
|
|
|
|
|
|
Set PORT_SETTINGS descriptor:
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------
|
|
|
PORT_SETTINGS 2 CMD_SET
|
|
|
PPORT 4 Physical port #
|
|
|
SPEED 4 Port interface speed, in Mbps
|
|
|
DUPLEX 1 1 = Full, 0 = Half
|
|
|
AUTONEG 1 1 = enabled, 0 = disabled
|
|
|
MACADDR 6 Port MAC address
|
|
|
MODE 1 0 = OF-DPA
|
|
|
|
|
|
Port Enable
|
|
|
-----------
|
|
|
|
|
|
Front-panel ports are initially disabled, which means port ingress and egress
|
|
|
packets will be dropped. To enable or disable a port, use PORT_PHYS_ENABLE::
|
|
|
|
|
|
PORT_PHYS_ENABLE: offset 0x0318, 64-bit, (R/W)
|
|
|
|
|
|
Value is bitmap of first 64 ports. Bits 0 and 63 are ignored
|
|
|
and always read as 0. Write 1 to enable port; write 0 to disable it.
|
|
|
Default is 0.
|
|
|
|
|
|
|
|
|
Switch Control
|
|
|
==============
|
|
|
|
|
|
This section covers switch-wide register settings.
|
|
|
|
|
|
Control
|
|
|
-------
|
|
|
|
|
|
This register is used for low level control of the switch::
|
|
|
|
|
|
CONTROL: offset 0x0300, 32-bit, (W)
|
|
|
|
|
|
bit name description
|
|
|
------------------------------------------------------------------------
|
|
|
[0] CONTROL_RESET If set, device will perform reset
|
|
|
[1:31] Reserved
|
|
|
|
|
|
Switch ID
|
|
|
---------
|
|
|
|
|
|
The switch has a SWITCH_ID to be used by software to uniquely identify the
|
|
|
switch::
|
|
|
|
|
|
SWITCH_ID: offset 0x0320, 64-bit, (R)
|
|
|
|
|
|
Value is opaque to switch software and no special encoding is implied.
|
|
|
|
|
|
|
|
|
Events
|
|
|
======
|
|
|
|
|
|
Non-I/O asynchronous events from the device are notified to the host using the
|
|
|
event ring. The TLV structure for events is::
|
|
|
|
|
|
field width description
|
|
|
---------------------------------------------------
|
|
|
TYPE 4 Event type, one of:
|
|
|
1: LINK_CHANGED
|
|
|
2: MAC_VLAN_SEEN
|
|
|
INFO <nest> Event info (details below)
|
|
|
|
|
|
Link Changed Event
|
|
|
------------------
|
|
|
|
|
|
When link status changes on a physical port, this event is generated::
|
|
|
|
|
|
field width description
|
|
|
---------------------------------------------------
|
|
|
INFO <nest>
|
|
|
PPORT 4 Physical port
|
|
|
LINKUP 1 Link status:
|
|
|
0: down
|
|
|
1: up
|
|
|
|
|
|
MAC VLAN Seen Event
|
|
|
-------------------
|
|
|
|
|
|
When a packet ingresses on a port and the source MAC/VLAN isn't known to the
|
|
|
device, the device will generate this event. In response to the event, the
|
|
|
driver should install to the device the MAC/VLAN on the port into the bridge
|
|
|
table. Once installed, the MAC/VLAN is known on the port and this event will
|
|
|
no longer be generated.
|
|
|
|
|
|
::
|
|
|
|
|
|
field width description
|
|
|
---------------------------------------------------
|
|
|
INFO <nest>
|
|
|
PPORT 4 Physical port
|
|
|
MAC 6 MAC address
|
|
|
VLAN 2 VLAN ID
|
|
|
|
|
|
|
|
|
CPU Packet Processing
|
|
|
=====================
|
|
|
|
|
|
Ingress packets directed to the host CPU for further processing are delivered
|
|
|
in the DMA RX ring. Likewise, host CPU originating packets destined to egress
|
|
|
on switch ports are scheduled by software using the DMA TX ring.
|
|
|
|
|
|
Tx Packet Processing
|
|
|
--------------------
|
|
|
|
|
|
Software schedules packets for egress on switch ports using the DMA TX ring. A
|
|
|
TX descriptor buffer describes the packet location and size in host DMA-able
|
|
|
memory, the destination port, and any hardware-offload functions (such as L3
|
|
|
payload checksum offload). Software then bumps the descriptor head to signal
|
|
|
hardware of new Tx work. In response, hardware will DMA read Tx descriptors up
|
|
|
to head, DMA read descriptor buffer and packet data, perform offloading
|
|
|
functions, and finally frame packet on wire (network). Once packet processing
|
|
|
is complete, hardware will writeback status to descriptor(s) to signal to
|
|
|
software that Tx is complete and software resources (e.g. skb) backing packet
|
|
|
can be released.
|
|
|
|
|
|
Figure 2 shows an example 3-fragment packet queued with one Tx descriptor. A
|
|
|
TLV is used for each packet fragment::
|
|
|
|
|
|
pkt frag 1
|
|
|
+–––––––+ +–+
|
|
|
+–––+ | |
|
|
|
desc buf | | | |
|
|
|
+––––––––+ | | | |
|
|
|
Tx ring +–––+ +–––––+ | | |
|
|
|
+–––––––––+ | | TLVs | +–––––––+ |
|
|
|
| +–––+ +––––––––+ pkt frag 2 |
|
|
|
| desc 0 | | +–––––+ +–––––––+ |
|
|
|
+–––––––––+ | TLVs | +–––+ | |
|
|
|
head+–+ | +––––––––+ | | |
|
|
|
| desc 1 | | +–––––+ +–––––––+ |pkt
|
|
|
+–––––––––+ | TLVs | | |
|
|
|
| | +––––––––+ | pkt frag 3 |
|
|
|
| | | +–––––––+ |
|
|
|
+–––––––––+ +–––+ | |
|
|
|
| | | | |
|
|
|
| | | | |
|
|
|
+–––––––––+ | | |
|
|
|
| | | | |
|
|
|
| | | | |
|
|
|
+–––––––––+ | | |
|
|
|
| | +–––––––+ +–+
|
|
|
| |
|
|
|
+–––––––––+
|
|
|
|
|
|
fig 2.
|
|
|
|
|
|
The TLVs for Tx descriptor buffer are::
|
|
|
|
|
|
field width description
|
|
|
---------------------------------------------------------------------
|
|
|
PPORT 4 Destination physical port #
|
|
|
TX_OFFLOAD 1 Hardware offload modes:
|
|
|
0: no offload
|
|
|
1: insert IP csum (ipv4 only)
|
|
|
2: insert TCP/UDP csum
|
|
|
3: L3 csum calc and insert
|
|
|
into csum offset (TX_L3_CSUM_OFF)
|
|
|
16-bit 1's complement csum value.
|
|
|
IPv4 pseudo-header and IP
|
|
|
already calculated by OS
|
|
|
and inserted.
|
|
|
4: TSO (TCP Segmentation Offload)
|
|
|
TX_L3_CSUM_OFF 2 For L3 csum offload mode, the offset,
|
|
|
from the beginning of the packet,
|
|
|
of the csum field in the L3 header
|
|
|
TX_TSO_MSS 2 For TSO offload mode, the
|
|
|
Maximum Segment Size in bytes
|
|
|
TX_TSO_HDR_LEN 2 For TSO offload mode, the
|
|
|
length of ethernet, IP, and
|
|
|
TCP/UDP headers, including IP
|
|
|
and TCP options.
|
|
|
TX_FRAGS <array> Packet fragments
|
|
|
TX_FRAG <nest> Packet fragment
|
|
|
TX_FRAG_ADDR 8 DMA address of packet fragment
|
|
|
TX_FRAG_LEN 2 Packet fragment length
|
|
|
|
|
|
Possible status return codes in descriptor on completion are::
|
|
|
|
|
|
DESC_COMP_ERR reason
|
|
|
--------------------------------------------------------------------
|
|
|
0 OK
|
|
|
-ROCKER_ENXIO address or data read err on desc buf or packet
|
|
|
fragment
|
|
|
-ROCKER_EINVAL bad pport or TSO or csum offloading error
|
|
|
-ROCKER_ENOMEM no memory for internal staging tx fragment
|
|
|
|
|
|
Rx Packet Processing
|
|
|
--------------------
|
|
|
|
|
|
For packets ingressing on switch ports that are not forwarded by the switch but
|
|
|
rather directed to the host CPU for further processing are delivered in the DMA
|
|
|
RX ring. Rx descriptor buffers are allocated by software and placed on the
|
|
|
ring. Hardware will fill Rx descriptor buffers with packet data, write the
|
|
|
completion, and signal to software that a new packet is ready. Since Rx packet
|
|
|
size is not known a-priori, the Rx descriptor buffer must be allocated for
|
|
|
worst-case packet size. A single Rx descriptor will contain the entire Rx
|
|
|
packet data in one RX_FRAG. Other Rx TLVs describe and hardware offloads
|
|
|
performed on the packet, such as checksum validation.
|
|
|
|
|
|
The TLVs for Rx descriptor buffer are::
|
|
|
|
|
|
field width description
|
|
|
---------------------------------------------------
|
|
|
PPORT 4 Source physical port #
|
|
|
RX_FLAGS 2 Packet parsing flags:
|
|
|
(1 << 0): IPv4 packet
|
|
|
(1 << 1): IPv6 packet
|
|
|
(1 << 2): csum calculated
|
|
|
(1 << 3): IPv4 csum good
|
|
|
(1 << 4): IP fragment
|
|
|
(1 << 5): TCP packet
|
|
|
(1 << 6): UDP packet
|
|
|
(1 << 7): TCP/UDP csum good
|
|
|
(1 << 8): Offload forward
|
|
|
RX_CSUM 2 IP calculated checksum:
|
|
|
IPv4: IP payload csum
|
|
|
IPv6: header and payload csum
|
|
|
(Only valid is RX_FLAGS:csum calc is set)
|
|
|
RX_FRAG_ADDR 8 DMA address of packet fragment
|
|
|
RX_FRAG_MAX_LEN 2 Packet maximum fragment length
|
|
|
RX_FRAG_LEN 2 Actual packet fragment length after receive
|
|
|
|
|
|
Offload forward RX_FLAG indicates the device has already forwarded the packet
|
|
|
so the host CPU should not also forward the packet.
|
|
|
|
|
|
Possible status return codes in descriptor on completion are::
|
|
|
|
|
|
DESC_COMP_ERR reason
|
|
|
--------------------------------------------------------------------
|
|
|
0 OK
|
|
|
-ROCKER_ENXIO address or data read err on desc buf
|
|
|
-ROCKER_ENOMEM no memory for internal staging desc buf
|
|
|
-ROCKER_EMSGSIZE Rx descriptor buffer wasn't big enough to contain
|
|
|
packet data TLV and other TLVs.
|
|
|
|
|
|
|
|
|
OF-DPA Mode
|
|
|
===========
|
|
|
|
|
|
OF-DPA mode allows the switch to offload flow packet processing functions to
|
|
|
hardware. An OpenFlow controller would communicate with an OpenFlow agent
|
|
|
installed on the switch. The OpenFlow agent would (directly or indirectly)
|
|
|
communicate with the Rocker switch driver, which in turn would program switch
|
|
|
hardware with flow functionality, as defined in OF-DPA. The block diagram is::
|
|
|
|
|
|
+–––––––––––––––----–––+
|
|
|
| OF |
|
|
|
| Remote Controller |
|
|
|
+––––––––+––----–––––––+
|
|
|
|
|
|
|
|
|
|
|
+––––––––+–––––––––+
|
|
|
| OF |
|
|
|
| Local Agent |
|
|
|
+––––––––––––––––––+
|
|
|
| |
|
|
|
| Rocker Driver |
|
|
|
+––––––––––––––––––+
|
|
|
<this spec>
|
|
|
+––––––––––––––––––+
|
|
|
| |
|
|
|
| Rocker Switch |
|
|
|
+––––––––––––––––––+
|
|
|
|
|
|
To participate in flow functions, ports must be configure for OF-DPA mode
|
|
|
during switch initialization.
|
|
|
|
|
|
OF-DPA Flow Table Interface
|
|
|
---------------------------
|
|
|
|
|
|
There are commands to add, modify, delete, and get stats of flow table entries.
|
|
|
The commands are issued using the DMA CMD descriptor ring. The following
|
|
|
commands are defined::
|
|
|
|
|
|
CMD_ADD: add an entry to flow table
|
|
|
CMD_MOD: modify an entry in flow table
|
|
|
CMD_DEL: delete an entry from flow table
|
|
|
CMD_GET_STATS: get stats for flow entry
|
|
|
|
|
|
TLVs for add and modify commands are::
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------------
|
|
|
OF_DPA_CMD 2 CMD_[ADD|MOD]
|
|
|
OF_DPA_TBL 2 Flow table ID
|
|
|
0: ingress port
|
|
|
10: vlan
|
|
|
20: termination mac
|
|
|
30: unicast routing
|
|
|
40: multicast routing
|
|
|
50: bridging
|
|
|
60: ACL policy
|
|
|
OF_DPA_PRIORITY 4 Flow priority
|
|
|
OF_DPA_HARDTIME 4 Hard timeout for flow
|
|
|
OF_DPA_IDLETIME 4 Idle timeout for flow
|
|
|
OF_DPA_COOKIE 8 Cookie
|
|
|
|
|
|
Additional TLVs based on flow table ID:
|
|
|
|
|
|
Table ID 0: ingress port::
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------------
|
|
|
OF_DPA_IN_PPORT 4 ingress physical port number
|
|
|
OF_DPA_GOTO_TBL 2 goto table ID; zero to drop
|
|
|
|
|
|
Table ID 10: vlan::
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------------
|
|
|
OF_DPA_IN_PPORT 4 ingress physical port number
|
|
|
OF_DPA_VLAN_ID 2 (N) vlan ID
|
|
|
OF_DPA_VLAN_ID_MASK 2 (N) vlan ID mask
|
|
|
OF_DPA_GOTO_TBL 2 goto table ID; zero to drop
|
|
|
OF_DPA_NEW_VLAN_ID 2 (N) new vlan ID
|
|
|
|
|
|
Table ID 20: termination mac::
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------------
|
|
|
OF_DPA_IN_PPORT 4 ingress physical port number
|
|
|
OF_DPA_IN_PPORT_MASK 4 ingress physical port number mask
|
|
|
OF_DPA_ETHERTYPE 2 (N) must be either 0x0800 or 0x86dd
|
|
|
OF_DPA_DST_MAC 6 (N) destination MAC
|
|
|
OF_DPA_DST_MAC_MASK 6 (N) destination MAC mask
|
|
|
OF_DPA_VLAN_ID 2 (N) vlan ID
|
|
|
OF_DPA_VLAN_ID_MASK 2 (N) vlan ID mask
|
|
|
OF_DPA_GOTO_TBL 2 only acceptable values are
|
|
|
unicast or multicast routing
|
|
|
table IDs
|
|
|
OF_DPA_OUT_PPORT 2 if specified, must be
|
|
|
controller, set zero otherwise
|
|
|
|
|
|
Table ID 30: unicast routing::
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------------
|
|
|
OF_DPA_ETHERTYPE 2 (N) must be either 0x0800 or 0x86dd
|
|
|
OF_DPA_DST_IP 4 (N) destination IPv4 address.
|
|
|
Must be unicast address
|
|
|
OF_DPA_DST_IP_MASK 4 (N) IP mask. Must be prefix mask
|
|
|
OF_DPA_DST_IPV6 16 (N) destination IPv6 address.
|
|
|
Must be unicast address
|
|
|
OF_DPA_DST_IPV6_MASK 16 (N) IPv6 mask. Must be prefix mask
|
|
|
OF_DPA_GOTO_TBL 2 goto table ID; zero to drop
|
|
|
OF_DPA_GROUP_ID 4 data for GROUP action must
|
|
|
be an L3 Unicast group entry
|
|
|
|
|
|
Table ID 40: multicast routing::
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------------
|
|
|
OF_DPA_ETHERTYPE 2 (N) must be either 0x0800 or 0x86dd
|
|
|
OF_DPA_VLAN_ID 2 (N) vlan ID
|
|
|
OF_DPA_SRC_IP 4 (N) source IPv4. Optional,
|
|
|
can contain IPv4 address,
|
|
|
must be completely masked
|
|
|
if not used
|
|
|
OF_DPA_SRC_IP_MASK 4 (N) IP Mask
|
|
|
OF_DPA_DST_IP 4 (N) destination IPv4 address.
|
|
|
Must be multicast address
|
|
|
OF_DPA_SRC_IPV6 16 (N) source IPv6 Address. Optional.
|
|
|
Can contain IPv6 address,
|
|
|
must be completely masked
|
|
|
if not used
|
|
|
OF_DPA_SRC_IPV6_MASK 16 (N) IPv6 mask.
|
|
|
OF_DPA_DST_IPV6 16 (N) destination IPv6 Address. Must
|
|
|
be multicast address
|
|
|
Must be multicast address
|
|
|
OF_DPA_GOTO_TBL 2 goto table ID; zero to drop
|
|
|
OF_DPA_GROUP_ID 4 data for GROUP action must
|
|
|
be an L3 multicast group entry
|
|
|
|
|
|
Table ID 50: bridging::
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------------
|
|
|
OF_DPA_VLAN_ID 2 (N) vlan ID
|
|
|
OF_DPA_TUNNEL_ID 4 tunnel ID
|
|
|
OF_DPA_DST_MAC 6 (N) destination MAC
|
|
|
OF_DPA_DST_MAC_MASK 6 (N) destination MAC mask
|
|
|
OF_DPA_GOTO_TBL 2 goto table ID; zero to drop
|
|
|
OF_DPA_GROUP_ID 4 data for GROUP action must
|
|
|
be a L2 Interface, L2
|
|
|
Multicast, L2 Flood,
|
|
|
or L2 Overlay group entry
|
|
|
as appropriate
|
|
|
OF_DPA_TUNNEL_LPORT 4 unicast Tenant Bridging
|
|
|
flows specify a tunnel
|
|
|
logical port ID
|
|
|
OF_DPA_OUT_PPORT 2 data for OUTPUT action,
|
|
|
restricted to CONTROLLER,
|
|
|
set to 0 otherwise
|
|
|
|
|
|
Table ID 60: acl policy::
|
|
|
|
|
|
field width description
|
|
|
----------------------------------------------------
|
|
|
OF_DPA_IN_PPORT 4 ingress physical port number
|
|
|
OF_DPA_IN_PPORT_MASK 4 ingress physical port number mask
|
|
|
OF_DPA_ETHERTYPE 2 (N) ethertype
|
|
|
OF_DPA_VLAN_ID 2 (N) vlan ID
|
|
|
OF_DPA_VLAN_ID_MASK 2 (N) vlan ID mask
|
|
|
OF_DPA_VLAN_PCP 2 (N) vlan Priority Code Point
|
|
|
OF_DPA_VLAN_PCP_MASK 2 (N) vlan Priority Code Point mask
|
|
|
OF_DPA_SRC_MAC 6 (N) source MAC
|
|
|
OF_DPA_SRC_MAC_MASK 6 (N) source MAC mask
|
|
|
OF_DPA_DST_MAC 6 (N) destination MAC
|
|
|
OF_DPA_DST_MAC_MASK 6 (N) destination MAC mask
|
|
|
OF_DPA_TUNNEL_ID 4 tunnel ID
|
|
|
OF_DPA_SRC_IP 4 (N) source IPv4. Optional,
|
|
|
can contain IPv4 address,
|
|
|
must be completely masked
|
|
|
if not used
|
|
|
OF_DPA_SRC_IP_MASK 4 (N) IP Mask
|
|
|
OF_DPA_DST_IP 4 (N) destination IPv4 address.
|
|
|
Must be multicast address
|
|
|
OF_DPA_DST_IP_MASK 4 (N) IP Mask
|
|
|
OF_DPA_SRC_IPV6 16 (N) source IPv6 Address. Optional.
|
|
|
Can contain IPv6 address,
|
|
|
must be completely masked
|
|
|
if not used
|
|
|
OF_DPA_SRC_IPV6_MASK 16 (N) IPv6 mask
|
|
|
OF_DPA_DST_IPV6 16 (N) destination IPv6 Address. Must
|
|
|
be multicast address.
|
|
|
OF_DPA_DST_IPV6_MASK 16 (N) IPv6 mask
|
|
|
OF_DPA_SRC_ARP_IP 4 (N) source IPv4 address in the ARP
|
|
|
payload. Only used if ethertype
|
|
|
== 0x0806.
|
|
|
OF_DPA_SRC_ARP_IP_MASK 4 (N) IP Mask
|
|
|
OF_DPA_IP_PROTO 1 IP protocol
|
|
|
OF_DPA_IP_PROTO_MASK 1 IP protocol mask
|
|
|
OF_DPA_IP_DSCP 1 DSCP
|
|
|
OF_DPA_IP_DSCP_MASK 1 DSCP mask
|
|
|
OF_DPA_IP_ECN 1 ECN
|
|
|
OF_DPA_IP_ECN_MASK 1 ECN mask
|
|
|
OF_DPA_L4_SRC_PORT 2 (N) L4 source port, only for
|
|
|
TCP, UDP, or SCTP
|
|
|
OF_DPA_L4_SRC_PORT_MASK 2 (N) L4 source port mask
|
|
|
OF_DPA_L4_DST_PORT 2 (N) L4 source port, only for
|
|
|
TCP, UDP, or SCTP
|
|
|
OF_DPA_L4_DST_PORT_MASK 2 (N) L4 source port mask
|
|
|
OF_DPA_ICMP_TYPE 1 ICMP type, only if IP
|
|
|
protocol is 1
|
|
|
OF_DPA_ICMP_TYPE_MASK 1 ICMP type mask
|
|
|
OF_DPA_ICMP_CODE 1 ICMP code
|
|
|
OF_DPA_ICMP_CODE_MASK 1 ICMP code mask
|
|
|
OF_DPA_IPV6_LABEL 4 (N) IPv6 flow label
|
|
|
OF_DPA_IPV6_LABEL_MASK 4 (N) IPv6 flow label mask
|
|
|
OF_DPA_GROUP_ID 4 data for GROUP action
|
|
|
OF_DPA_QUEUE_ID_ACTION 1 write the queue ID
|
|
|
OF_DPA_NEW_QUEUE_ID 1 queue ID
|
|
|
OF_DPA_VLAN_PCP_ACTION 1 write the VLAN priority
|
|
|
OF_DPA_NEW_VLAN_PCP 1 VLAN priority
|
|
|
OF_DPA_IP_DSCP_ACTION 1 write the DSCP
|
|
|
OF_DPA_NEW_IP_DSCP 1 new DSCP
|
|
|
OF_DPA_TUNNEL_LPORT 4 restrct to valid tunnel
|
|
|
logical port, set to 0
|
|
|
otherwise.
|
|
|
OF_DPA_OUT_PPORT 2 data for OUTPUT action,
|
|
|
restricted to CONTROLLER,
|
|
|
set to 0 otherwise
|
|
|
OF_DPA_CLEAR_ACTIONS 4 if 1 packets matching flow are
|
|
|
dropped (all other instructions
|
|
|
ignored)
|
|
|
|
|
|
TLVs for flow delete and get stats command are::
|
|
|
|
|
|
field width description
|
|
|
---------------------------------------------------
|
|
|
OF_DPA_CMD 2 CMD_[DEL|GET_STATS]
|
|
|
OF_DPA_COOKIE 8 Cookie
|
|
|
|
|
|
On completion of get stats command, the descriptor buffer is written back with
|
|
|
the following TLVs::
|
|
|
|
|
|
field width description
|
|
|
---------------------------------------------------
|
|
|
OF_DPA_STAT_DURATION 4 Flow duration
|
|
|
OF_DPA_STAT_RX_PKTS 8 Received packets
|
|
|
OF_DPA_STAT_TX_PKTS 8 Transmit packets
|
|
|
|
|
|
Possible status return codes in descriptor on completion are::
|
|
|
|
|
|
DESC_COMP_ERR command reason
|
|
|
--------------------------------------------------------------------
|
|
|
0 all OK
|
|
|
-ROCKER_EFAULT all head or tail index outside
|
|
|
of ring
|
|
|
-ROCKER_ENXIO all address or data read err on
|
|
|
desc buf
|
|
|
-ROCKER_EMSGSIZE GET_STATS cmd descriptor buffer wasn't
|
|
|
big enough to contain write-back
|
|
|
TLVs
|
|
|
-ROCKER_EINVAL all invalid parameters passed in
|
|
|
-ROCKER_EEXIST ADD entry already exists
|
|
|
-ROCKER_ENOSPC ADD no space left in flow table
|
|
|
-ROCKER_ENOENT MOD|DEL|GET_STATS cookie invalid
|
|
|
|
|
|
Group Table Interface
|
|
|
---------------------
|
|
|
|
|
|
There are commands to add, modify, delete, and get stats of group table
|
|
|
entries. The commands are issued using the DMA CMD descriptor ring. The
|
|
|
following commands are defined::
|
|
|
|
|
|
CMD_ADD: add an entry to group table
|
|
|
CMD_MOD: modify an entry in group table
|
|
|
CMD_DEL: delete an entry from group table
|
|
|
CMD_GET_STATS: get stats for group entry
|
|
|
|
|
|
TLVs for add and modify commands are::
|
|
|
|
|
|
field width description
|
|
|
-----------------------------------------------------------
|
|
|
FLOW_GROUP_CMD 2 CMD_[ADD|MOD]
|
|
|
FLOW_GROUP_ID 2 Flow group ID
|
|
|
FLOW_GROUP_TYPE 1 Group type:
|
|
|
0: L2 interface
|
|
|
1: L2 rewrite
|
|
|
2: L3 unicast
|
|
|
3: L2 multicast
|
|
|
4: L2 flood
|
|
|
5: L3 interface
|
|
|
6: L3 multicast
|
|
|
7: L3 ECMP
|
|
|
8: L2 overlay
|
|
|
FLOW_VLAN_ID 2 Vlan ID (types 0, 3, 4, 6)
|
|
|
FLOW_L2_PORT 2 Port (types 0)
|
|
|
FLOW_INDEX 4 Index (all types but 0)
|
|
|
FLOW_OVERLAY_TYPE 1 Overlay sub-type (type 8):
|
|
|
0: Flood unicast tunnel
|
|
|
1: Flood multicast tunnel
|
|
|
2: Multicast unicast tunnel
|
|
|
3: Multicast multicast tunnel
|
|
|
FLOW_GROUP_ACTION nest
|
|
|
FLOW_GROUP_ID 2 next group ID in chain (all
|
|
|
types except 0)
|
|
|
FLOW_OUT_PORT 4 egress port (types 0, 8)
|
|
|
FLOW_POP_VLAN_TAG 1 strip outer VLAN tag (type 1
|
|
|
only)
|
|
|
FLOW_VLAN_ID 2 (types 1, 5)
|
|
|
FLOW_SRC_MAC 6 (types 1, 2, 5)
|
|
|
FLOW_DST_MAC 6 (types 1, 2)
|
|
|
|
|
|
TLVs for flow delete and get stats command are::
|
|
|
|
|
|
field width description
|
|
|
-----------------------------------------------------------
|
|
|
FLOW_GROUP_CMD 2 CMD_[DEL|GET_STATS]
|
|
|
FLOW_GROUP_ID 2 Flow group ID
|
|
|
|
|
|
On completion of get stats command, the descriptor buffer is written back with
|
|
|
the following TLVs::
|
|
|
|
|
|
field width description
|
|
|
---------------------------------------------------
|
|
|
FLOW_GROUP_ID 2 Flow group ID
|
|
|
FLOW_STAT_DURATION 4 Flow duration
|
|
|
FLOW_STAT_REF_COUNT 4 Flow reference count
|
|
|
FLOW_STAT_BUCKET_COUNT 4 Flow bucket count
|
|
|
|
|
|
Possible status return codes in descriptor on completion are::
|
|
|
|
|
|
DESC_COMP_ERR command reason
|
|
|
--------------------------------------------------------------------
|
|
|
0 all OK
|
|
|
-ROCKER_EFAULT all head or tail index outside
|
|
|
of ring
|
|
|
-ROCKER_ENXIO all address or data read err on
|
|
|
desc buf
|
|
|
-ROCKER_ENOSPC GET_STATS cmd descriptor buffer wasn't
|
|
|
big enough to contain write-back
|
|
|
TLVs
|
|
|
-ROCKER_EINVAL ADD|MOD invalid parameters passed in
|
|
|
-ROCKER_EEXIST ADD entry already exists
|
|
|
-ROCKER_ENOSPC ADD no space left in flow table
|
|
|
-ROCKER_ENOENT MOD|DEL|GET_STATS group ID invalid
|
|
|
-ROCKER_EBUSY DEL group reference count non-zero
|
|
|
-ROCKER_ENODEV ADD next group ID doesn't exist
|
|
|
|
|
|
|
|
|
|
|
|
References
|
|
|
==========
|
|
|
|
|
|
[1] OpenFlow Data Plane Abstraction (OF-DPA) Abstract Switch Specification,
|
|
|
Version 1.0, from Broadcom Corporation, February 21, 2014.
|