.. _ofp-operation:
OpenFlow Plugin Operation
=========================
Overview
--------
The OpenFlow standard describes a communications protocol that allows
an external application, such as an SDN Controller, to access and
configure the forwarding plane of a network device normally called
the OpenFlow-enabled switch.
The switch and the controller communicate by exchanging OpenFlow
protocol messages, which the controller uses to add, modify, and delete
flows in the switch. By using OpenFlow, it is possible to control
various aspects of the network, such as traffic forwarding, topology
discovery, Quality of Service, and so on.
For more information about OpenFlow, refer to the Open Networking
Foundation website openflow-specs_.
The OpenFlow Plugin provides the following RESTCONF APIs:
- OpenFlow Topology
- OpenFlow Statistics
- OpenFlow Programming
OpenFlow Topology
-----------------
The controller provides a centralized logical view of the OpenFlow network.
The controller uses Link Layer Discovery Protocol (LLDP) messages to discover
the links between the connected OpenFlow devices. The topology manager
stores and manages the information (nodes and links) in the controller
data stores.
This works as follows:
- LLDP speaker application sends LLDP packets to all the node connectors of
all the switches that are connected.
- LLDP speaker application also monitors status events for a node connector.
If the status of a node connector for the connected switch changes from up
to down, the LLDP speaker does not send packets out to that node connector.
If the status changes from down to up, the LLDP speaker sends packets to
that node connector.
- The LLDP discovery application monitors the LLDP packets that are sent by a
switch to the controller and notifies the topology manager of a new
link-discovery event. The information includes: source node, source node
connector, destination node, and destination node connector, from the
received LLDP packets.
- The LLDP discovery application also checks for an expired link and notifies
the topology manager. A link expires when it does not receive an update from
the switch for the three LLDP speaker cycles.
Retrieving topology details by using RESTCONF
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can retrieve OpenFlow topology information (nodes and links) from the
controller by sending a RESTCONF request. The controller fetches the topology
data from the operational datastore and returns it in response to the RESTCONF
request.
To view the topology data for all the connected nodes, send the following
request to the controller:
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operational/network-topology:network-topology/topology/flow:1``
**Method:** GET
**Sample output:**
.. code-block:: none
flow:1openflow:1/a:nodes/a:node[a:id='openflow:1']openflow:1:1/a:nodes/a:node[a:id='openflow:1']/a:node-connector[a:id='openflow:1:1']openflow:1:LOCAL/a:nodes/a:node[a:id='openflow:1']/a:node-connector[a:id='openflow:1:LOCAL']openflow:1:2/a:nodes/a:node[a:id='openflow:1']/a:node-connector[a:id='openflow:1:2']openflow:2/a:nodes/a:node[a:id='openflow:2']openflow:2:2/a:nodes/a:node[a:id='openflow:2']/a:node-connector[a:id='openflow:2:2']openflow:2:LOCAL/a:nodes/a:node[a:id='openflow:2']/a:node-connector[a:id='openflow:2:LOCAL']openflow:2:1/a:nodes/a:node[a:id='openflow:2']/a:node-connector[a:id='openflow:2:1']openflow:2:2openflow:1openflow:1:2openflow:1:2openflow:2openflow:2:2
.. note:: In the example above the OpenFlow node is represented as openflow:1
where 1 is the datapath ID of the OpenFlow-enabled device.
.. note:: In the example above the OpenFlow node connector is represented as
openflow:1:2 where 1 is the datapath ID and 2 is the port ID of the
OpenFlow-enabled device.
OpenFlow Statistics
-------------------
The controller provides the following information for the connected
OpenFlow devices:
**Inventory information:**
- **Node description:** Description of the OpenFlow-enabled device, such as
the switch manufacturer, hardware revision, software revision, serial number,
and so on.
- **Flow table features:** Features supported by flow tables of the switch.
- **Port description:** Properties supported by each node connector of the
node.
- **Group features:** Features supported by the group table of the switch.
- **Meter features:** Features supported by the meter table of the switch.
**Statistics:**
- **Individual flow statistics:** Statistics related to individual flow
installed in the flow table.
- **Aggregate flow statistics:** Statistics related to aggregate flow for
each table level.
- **Flow table statistics:** Statistics related to the individual flow table
of the switch.
- **Port statistics:** Statistics related to all node connectors of the node.
- **Group description:** Description of the groups installed in the switch
group table.
- **Group statistics:** Statistics related to an individual group installed
in the group table.
- **Meter configuration:** Statistics related to the configuration of the
meters installed in the switch meter table.
- **Meter statistics:** Statistics related to an individual meter installed
in the switch meter table.
- **Queue statistics:** Statistics related to the queues created on each
node connector of the switch.
The controller fetches both inventory and statistics information whenever a
node connects to the controller. After that the controller fetches statistics
periodically within a time interval of three seconds. The controller augments
inventory information and statistics fetched from each connected node to its
respective location in the operational data store. The controller also cleans
the stale statistics at periodic intervals.
You can retrieve the inventory information (nodes, ports, and tables) and
statistics (ports, flows, groups and meters) by sending a RESTCONF request.
The controller fetches the inventory data from the operational data store
and returns it in response to the RESTCONF request.
The following sections provide a few examples for retrieving inventory and
statistics information.
Example of node inventory data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To view the inventory data of a connected node, send the following request to
the controller:
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operational/opendaylight-inventory:nodes/node/openflow:1``
**Method:** ``GET``
**Sample output:**
.. code-block:: none
Open vSwitchNone2540flow-feature-capability-queue-statsflow-feature-capability-table-statsflow-feature-capability-flow-statsflow-feature-capability-port-statsflow-feature-capability-group-statsNicira, Inc.None2.8.1192.168.0.24
--- Omitted output —--
.. note:: In the example above the OpenFlow node is represented as openflow:1
where 1 is the datapath ID of the OpenFlow-enabled device.
Example of port description and port statistics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To view the port description and port statistics of a connected node, send the
following request to the controller:
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/node-connector/openflow:1:2``
**Method:** ``GET``
**Sample output:**
.. code-block:: none
openflow:1:224e:92:4a:c8:4c:faten-gb-fd copper0update10000000s1-eth2falsefalsetrue0444444000037708377080021815500000000
.. note:: In the example above the OpenFlow node connector is represented as
openflow:1:2 where 1 is the datapath ID and 2 is the port ID of the
OpenFlow-enabled device.
.. _example-of-table-statistics:
Example of flow table and aggregated statistics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To view the flow table and flow aggregated statistics for a connected node,
send the following request to the controller:
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/0/``
**Method:** ``GET``
**Sample output:**
.. code-block:: none
03548535
--- Omitted output —--
.. note:: In the example above the OpenFlow node table is 0.
.. _example-of-individual-flow-statistics:
Example of flow description and flow statistics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To view the individual flow statistics, send the following request to the
controller:
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/fm-sr-link-discovery``
**Method:** ``GET``
**Sample output:**
.. code-block:: none
fm-sr-link-discovery536174000000268145560990003502010000000000000010065535CONTROLLER0
.. note:: In the example above the flow ID fm-sr-link-discovery is internal to
the controller and has to match the datastore configured flow ID.
For more information see flow ID match section
:ref:`flow-id-match-function`.
.. _example-of-group-description-and-group-statistics:
Example of group description and group statistics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To view the group description and group statistics, send the following request
to the controller:
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/group/2``
**Method:** ``GET``
**Sample output:**
.. code-block:: none
20102034887429496729502group-ff00020041167460000001
.. note:: In the example above the group ID 2 matches the switch stored
group ID.
.. _example-of-meter-description-and-meter-statistics:
Example of meter description and meter statistics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To view the meter description and meter statistics, send the following request
to the controller:
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/meter/2``
**Method:** ``GET``
**Sample output:**
.. code-block:: none
2meter-kbps000003640000001142001000ofpmbt-drop0100
.. note:: In the example above the meter ID 2 matches the switch stored
meter ID.
.. _openflow-programming-overview:
OpenFlow Programming
--------------------
The controller provides interfaces that can be used to program the connected
OpenFlow devices. These interfaces interact with the OpenFlow southbound plugin
that uses OpenFlow modification messages to program flows, groups and meters
in the switch.
The controller provides the following RESTCONF interfaces:
- **Configuration Datastore:** allows user to configure flows, groups and
meters. The configuration is stored in the controller datastore, persisted
in disk and replicated in the controller cluster. The OpenFlow southbound
plugin reads the configuration and sends the appropriate OpenFlow
modification messages to the connected devices.
- **RPC Operations:** allows user to configure flows, groups and meters
overriding the datastore. In this case the OpenFlow southbound plugin
translates the use configuration straight into an OpenFlow modification
message that is sent to the connected device.
Example of flow programming by using config datastore
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example programs a flow that matches IPv4 packets (ethertype 0x800)
with destination address in the 10.0.10.0/24 subnet and sends them to port 1.
The flow is installed in table 0 of the switch with datapath ID 1.
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1``
**Method:** ``PUT``
**Request body:**
.. code-block:: none
0012flow1204810.0.10.0/2410010
.. note:: In the example above the flow ID 1 is internal to the controller and
the same ID can be found when retrieving the flow statistics if
controller finds a match between the configured flow and the flow
received from switch. For more information see flow ID match section
:ref:`flow-id-match-function`.
.. note:: To use a different flow ID or table ID, ensure that the URL and the
request body are synchronized.
.. note:: For more examples of flow programming using datastore, refer to
the OpenDaylight OpenFlow plugin :ref:`ofp-flow-examples`.
For more information about flow configuration options check the
opendaylight_models_.
To verify that the flow has been correctly programmed in the switch, issue the
RESTCONF request as provided in :ref:`example-of-individual-flow-statistics`.
Deleting flows from config datastore:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example deletes the flow with ID 1 in table 0 of the switch with datapath
ID 1.
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1``
**Method:** ``DELETE``
You can also use the below URL to delete all flows in table 0 of the switch
with datapath ID 1:
**URL:** ``/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0``
To verify that the flow has been correctly removed in the switch, issue the
RESTCONF request as provided in :ref:`example-of-table-statistics`.
Example of flow programming by using RPC operation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example programs a flow that matches IPv4 packets (ethertype 0x800)
with destination address in the 10.0.10.0/24 subnet and sends them to port 1.
The flow is installed in table 0 of the switch with datapath ID 1.
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operations/sal-flow:add-flow``
**Method:** ``POST``
**Request body:**
.. code-block:: none
/inv:nodes/inv:node[inv:id="openflow:1"]02204810.0.1.0/24010
.. note:: This payload does not require flow ID as this value is internal to
controller and only used to store flows in the datastore. When
retrieving flow statistics users will see an alien flow ID for flows
created this way. For more information see flow ID match section
:ref:`flow-id-match-function`.
To verify that the flow has been correctly programmed in the switch, issue the
RESTCONF request as provided in :ref:`example-of-table-statistics`.
Deleting flows from switch using RPC operation:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example removes a flow that matches IPv4 packets (ethertype 0x800)
with destination address in the 10.0.10.0/24 subnet from table 0 of the switch
with datapath ID 1.
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operations/sal-flow:remove-flow``
**Method:** ``POST``
**Request body:**
.. code-block:: none
/inv:nodes/inv:node[inv:id="openflow:1"]02true204810.0.10.0/24
To verify that the flow has been correctly programmed in the switch, issue the
RESTCONF request as provided in :ref:`example-of-table-statistics`.
Example of a group programming by using config datastore
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example programs a select group to equally load balance traffic across
port 1 and port 2 in switch with datapath ID 1.
**Headers:**
- **Content-type:** ``application/json``
- **Accept:** ``application/json``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/config/opendaylight-inventory:nodes/node/openflow:1/group/1``
**Method:** ``PUT``
**Request body:**
.. code-block:: none
group-select11111212falseSelectGroup1
.. note:: In the example above the group ID 1 will be stored in the switch
and will be used by the switch to report group statistics.
.. note:: To use a different group ID, ensure that the URL and the request
body are synchronized.
For more information about group configuration options check the
opendaylight_models_.
To verify that the group has been correctly programmed in the switch,
issue the RESTCONF request as provided in
:ref:`example-of-group-description-and-group-statistics`.
To add a group action in a flow just add this statement in the flow body:
.. code-block:: none
11
Deleting groups from config datastore
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example deletes the group ID 1 in the switch with datapath ID 1.
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/config/opendaylight-inventory:nodes/node/openflow:1/group/1``
**Method:** ``DELETE``
Example of a meter programming by using config datastore
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example programs a meter to drop traffic exceeding 256 kbps with a burst
size of 512 in switch with datapath ID 1.
**Headers:**
- **Content-type:** ``application/json``
- **Accept:** ``application/json``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/config/opendaylight-inventory:nodes/node/openflow:1/meter/1``
**Method:** ``PUT``
**Request body:**
.. code-block:: none
meter-kbps0256512ofpmbt-drop1Foo
.. note:: In the example above the meter ID 1 will be stored in the switch
and will be used by the switch to report group statistics.
.. note:: To use a different meter ID, ensure that the URL and the request
body are synchronized.
For more information about meter configuration options check the
opendaylight_models_.
To verify that the meter has been correctly programmed in the switch,
issue the RESTCONF request as provided in
:ref:`example-of-meter-description-and-meter-statistics`.
To add a meter instruction in a flow just add this statement in the flow body:
.. code-block:: none
11
Deleting meters from config datastore
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example deletes the meter ID 1 in the switch with datapath ID 1.
**Headers:**
- **Content-type:** ``application/xml``
- **Accept:** ``application/xml``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/config/opendaylight-inventory:nodes/node/openflow:1/meter/1``
**Method:** ``DELETE``
.. _flow-id-match-function:
Flow ID match function
----------------------
When the controller receives flow information from a switch, this information
is compared with all flows stored in the configuration datastore, in case of
a match the flow ID in the flow configuration is automatically added to the
flow operational information. This way we can easily relate flows stored
in controller with flows received from the switch.
However in case of flows added via RPC or in general when the controller
cannot match received flow information with any flow in datastore, it adds
an alien ID in the flow operational information like in the example below.
.. code-block:: none
#UF$TABLE*0-555522764200000026132444295990003502010000000000000010065535CONTROLLER0
OpenFlow clustering
-------------------
For high availability, it is recommended a three-node cluster setup in
which each switch is connected to all nodes in the controller cluster.
.. note:: Normal OpenFlow operations, such as adding a flow, can be done on
any cluster member. For more information about OpenFlow operations,
refer to :ref:`openflow-programming-overview`.
In OpenFlow 1.3, one of the following roles is assigned to each
switch-controller connection:
- Master: All synchronous and asynchronous messages are sent to the
master controller. This controller has write privileges on the
switch.
- Slave: Only synchronous messages are sent to this controller. Slave
controllers have only read privileges on the switch.
- Equal: When the equal role is assigned to a controller, it has the
same privileges as the master controller. By default, a controller is
assigned the equal role when it first connects to the switch.
A switch can be connected to one or more controllers. Each controller
communicates the OpenFlow channel role through an OFTP\_ROLE\_REQUEST
message. The switch must retain the role of each switch connection; a
controller may change this role at any time.
If a switch connects to multiple controllers in the cluster, the cluster
selects one controller as the master controller; the remaining
controllers assume the slave role. The election of a master controller
proceeds as follows.
#. Each controller in the cluster that is handling switch connections
registers to the Entity Ownership Service (EOS) as a candidate for
switch ownership.
.. note:: The EOS is a clustering service that plays the role of the
arbiter to elect an owner (master) of an entity from a registered
set of candidates.
#. The EOS then selects one controller as the owner.
.. note:: Master ownership is for each device; each individual controller
can be a master for a set of connected devices and a slave for the
remaining set of connected devices.
#. The selected owner then sends an OFTP\_ROLE\_REQUEST message to the
switch to set the connection to the master role, and the other
controllers send the role message to set the slave role.
When the switch master connection goes down, the election of a new
master controller proceeds as follows.
#. The related controller deregisters itself as a candidate for Entity
Ownership from the EOS.
#. The EOS then selects a new owner from the remaining candidates.
#. The new owner accordingly sends an OFTP\_ROLE\_REQUEST message to the
switch to set the connection to the master role.
If a controller that currently has the master role is shut down, a new
master from the remaining candidate controllers is selected.
Verifying the EOS owner and candidates by using RESTCONF
--------------------------------------------------------
To verify the EOS owner and candidates in an OpenFlow cluster, send the
following request to the controller:
**Headers:**
- **Content-type:** ``application/json``
- **Accept:** ``application/json``
- **Authentication:** ``admin:admin``
**URL:** ``/restconf/operational/entity-owners:entity-owners``
**Method:** ``GET``
**Sample output:**
.. code-block:: none
{
"entity-owners":{
"entity-type":[
{
"type":"org.opendaylight.mdsal.ServiceEntityType",
"entity":[
{
"id":"/odl-general-entity:entity[odl-general-entity:name='openflow:1']",
"candidate":[
{
"name":"member-3"
},
{
"name":"member-2"
},
{
"name":"member-1"
}
],
"owner":"member-3"
},
{
"id":"/odl-general-entity:entity[odl-general-entity:name='openflow:2']",
"candidate":[
{
"name":"member-1"
},
{
"name":"member-3"
},
{
"name":"member-2"
}
],
"owner":"member-1"
},
{
"id":"/odl-general-entity:entity[odl-general-entity:name='openflow:3']",
"candidate":[
{
"name":"member-1"
},
{
"name":"member-2"
},
{
"name":"member-3"
}
],
"owner":"member-1"
}
]
},
{
"type":"org.opendaylight.mdsal.AsyncServiceCloseEntityType",
"entity":[
{
"id":"/odl-general-entity:entity[odl-general-entity:name='openflow:1']",
"candidate":[
{
"name":"member-3"
}
],
"owner":"member-3"
},
{
"id":"/odl-general-entity:entity[odl-general-entity:name='openflow:2']",
"candidate":[
{
"name":"member-1"
}
],
"owner":"member-1"
},
{
"id":"/odl-general-entity:entity[odl-general-entity:name='openflow:3']",
"candidate":[
{
"name":"member-1"
}
],
"owner":"member-1"
}
]
}
]
}
}
In the above sample output, ``member 3`` is the master controller
(EOS owner) for the OpenFlow device with datapath ID ``1``, and
``member-1`` is the master controller (EOS owner) for the OpenFlow
devices with the datapath IDs of ``2`` and ``3``.
Configuring the OpenFlow Plugin
-------------------------------
OpenFlow plugin configuration file is in the opendaylight /etc folder:
``opendaylight-0.9.0/etc/org.opendaylight.openflowplugin.cfg``
The ``org.opendaylight.openflowplugin.cfg`` file can be modified at any
time, however a controller restart is required for the changes to take
effect.
This configuration is local to a given node. You must repeat these steps
on each node to enable the same functionality across the cluster.
.. _ofp-tls-guide:
Configuring OpenFlow TLS
------------------------
This section describes how to secure OpenFlow connections between
controller and OpenFlow devices using Transport Layer Security (TLS).
TLS Concepts
~~~~~~~~~~~~
TLS uses digital certificates to perform remote peer authentication,
message integrity and data encryption. Public Key Infrastructure (PKI)
is required to create, manage and verify digital certificates.
For OpenFlow symmetric authentication (controller authenticates device
and device authenticates controller) both controller and device require:
#. A private key: used to generate own public certificate and therefore
required for own authentication at the other end.
#. A public certificate or a chain of certificates if public certificate
is signed by an intermediate (not root) CA: the chain contains the public
certificate as well as all the intermediate CA certificates used to
validate the public certificate, this public information is sent to the
other peer during the TLS negotiation and it is used for own
authentication at the other end.
#. A list of root CA certificates: this contains the root CA certificate
that signed the remote peer certificate or the remote peer intermediate
CA certificate (in case of certificate chain). This public information
is used to authenticate the other end.
.. note:: Some devices like Open vSwitch (OVS) do not support certificate
chains, this means controller can only send its own certificate
and receive the switch certificate without any intermediate CA
certificates. For TLS negotiation to be successful in this scenario
both ends need to store all intermediate CA certificates used by
the other end (in addition to the remote peer root CA certificate).
Generate Controller Private Key and Certificate
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You may skip this step if you already have the required key and certificate
from an external Public Key Infrastructure (PKI). In the examples below we
use openSSL tool to generate private key and certificates for controller.
#. Generate controller private key
The command below generates 2048 bytes RSA key:
.. code-block:: none
openssl genrsa -out controller.key 2048
This will generate the private key file controller.key
#. Generate controller certificate
The command below creates a certificate sign request:
.. code-block:: none
openssl req -new -sha256 -key controller.key -out controller.csr
This will generate the certificate signing request file controller.csr
Submit the file to the desired Certificate Authority (CA) and get the CA
signed certificate along with any intermediate CA certificate in the file
controller.crt (X.509 format).
The following is not recommended for production but if you want to just
check the TLS communication you can create a "self-signed" certificate for
the controller using below command:
.. code-block:: none
openssl req -new -x509 -nodes -sha1 -days 1825 -key controller.key -out controller.crt
Create Controller Key Stores
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Controller requires 2 Key Stores for OpenFlow TLS:
- Keystore: Used for controller authentication in the remote device. This
contains the controller private key (controller.key) and the controller
certificate or the controller certificate chain (controller.crt) in case
of an intermediate CA signs the controller certificate.
- Truststore: Used to authenticate remote devices. This contains the root
CA certificates signing the OpenFlow devices certificates or the
intermediate CA certificates (in case of certificate chain).
You may skip this step if you already generated the Key Stores from a
previous TLS installation. In the examples below we will use openSSL and
Java keytool tooling to create the Key Stores.
#. Create the controller Keystore
The command below generates the controller Keystore in PKCS12 format:
.. code-block:: none
openssl pkcs12 -export -in controller.crt -inkey controller.key -out keystore.p12 -name controller
When asked for a password select 'opendaylight' (or anything else).
This will generate the keystore.p12 file.
.. note:: If device (e.g. Open vSwitch) does not support certificate chains,
make sure controller.crt only contains the controller certificate
with no extra intermediate CA certificates.
#. Create the controller Truststore
The command below generates the controller Truststore in PKCS12 format
and adds the device root CA certificates rootca1.crt and rootca2.crt:
.. code-block:: none
keytool -importcert -storetype pkcs12 -file rootca1.crt -keystore truststore.p12 -storepass opendaylight -alias root-ca-1
keytool -importcert -storetype pkcs12 -file rootca2.crt -keystore truststore.p12 -storepass opendaylight -alias root-ca-2
Note in the examples we use 'opendaylight' as the store password.
This will generate the truststore.p12 file.
.. note:: If device (e.g. Open vSwitch) does not support certificate chains,
make sure you add all device intermediate CA certificates in the
controller Truststore.
Enable Controller TLS
~~~~~~~~~~~~~~~~~~~~~
Controller listens for OpenFlow connections on ports 6633 and 6653 (TCP).
You can enable TLS in both or just one of the ports.
#. Copy the Key Stores to a controller folder (e.g. opendaylight /etc folder)
#. Enable TLS on port 6633:
Create file legacy-openflow-connection-config.xml with following content:
.. code-block:: none
openflow-switch-connection-provider-legacy-impl6633TLSetc/keystore.p12PKCS12PATHopendaylightetc/truststore.p12PKCS12PATHopendaylightopendaylight
.. note:: Change password 'opendaylight' above if you used different password.
.. note:: Change the path above of you used different folder than opendaylight /etc.
Copy the file to opendaylight folder: /etc/opendaylight/datastore/initial/config
#. Enable TLS on port 6653:
Create file default-openflow-connection-config.xml with following content:
.. code-block:: none
openflow-switch-connection-provider-default-impl6653TLSetc/keystore.p12PKCS12PATHopendaylightetc/truststore.p12PKCS12PATHopendaylightopendaylight
.. note:: Change password 'opendaylight' above if you used different password.
.. note:: Change the path above of you used different folder than opendaylight /etc.
Copy the file to opendaylght folder /etc/opendaylight/datastore/initial/config
#. Restart Controller
For changes to take effect, controller has to be restarted.
Troubleshooting
---------------
Controller log is in opendaylight /data/log folder:
``opendaylight-0.9.0/data/log/karaf.log``
Logs can be also displayed on karaf console:
.. code-block:: none
log:display
To troubleshoot OpenFlow plugin enable this TRACE in karaf console:
.. code-block:: none
log:set TRACE org.opendaylight.openflowplugin.openflow.md.core
log:set TRACE org.opendaylight.openflowplugin.impl
To restore log settings:
.. code-block:: none
log:set INFO org.opendaylight.openflowplugin.openflow.md.core
log:set INFO org.opendaylight.openflowplugin.impl
.. _openflow-specs: https://www.opennetworking.org/software-defined-standards/specifications
.. _opendaylight_models: https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Model_Reference