-=== Service Function Scheduler
-TBD
+=== Service Function Scheduling Algorithms
==== Overview
-TBD
+When creating the Rendered Service Path, the origin SFC controller chose
+the first available service function from a list of service function names.
+This may result in many issues such as overloaded service functions
+and a longer service path as SFC has no means to understand the status of
+service functions and network topology. The service function selection
+framework supports at least four algorithms (Random, Round Robin,
+Load Balancing and Shortest Path) to select the most appropriate service
+function when instantiating the Rendered Service Path. In addition, it is an
+extensible framework that allows 3rd party selection algorithm to be plugged in.
==== Architecture
-TBD
+The following figure illustrates the service function selection framework
+and algorithms.
+
+.SF Selection Architecture
+image::sfc/sf-selection-arch.png["SF Selection Architecture",width=500]
+
+A user has three different ways to select one service function selection
+algorithm:
+
+. Integrated RESTCONF Calls. OpenStack and/or other administration system
+ could provide plugins to call the APIs to select one scheduling algorithm.
+. Command line tools. Command line tools such as curl or browser plugins
+ such as POSTMAN (for Google Chrome) and RESTClient (for Mozilla Firefox)
+ could select schedule algorithm by making RESTCONF calls.
+. SFC-UI. Now the SFC-UI provides an option for choosing a selection algorithm
+ when creating a Rendered Service Path.
+
+The RESTCONF northbound SFC API provides GUI/RESTCONF interactions for choosing
+the service function selection algorithm.
+MD-SAL data store provides all supported service function selection algorithms,
+and provides APIs to enable one of the provided service function selection
+algorithms.
+Once a service function selection algorithm is enabled, the service function
+selection algorithm will work when creating a Rendered Service Path.
==== Select SFs with Scheduler
-TBD
+Administrator could use both the following ways to select one of the selection
+algorithm when creating a Rendered Service Path.
+
+* Command line tools. Command line tools includes Linux commands curl or even
+ browser plugins such as POSTMAN(for Google Chrome) or RESTClient(for Mozilla
+ Firefox). In this case, the following JSON content is needed at the moment:
+ Service_function_schudule_type.json
++
+ {
+ "service-function-scheduler-types": {
+ "service-function-scheduler-type": [
+ {
+ "name": "random",
+ "type": "service-function-scheduler-type:random",
+ "enabled": false
+ },
+ {
+ "name": "roundrobin",
+ "type": "service-function-scheduler-type:round-robin",
+ "enabled": true
+ },
+ {
+ "name": "loadbalance",
+ "type": "service-function-scheduler-type:load-balance",
+ "enabled": false
+ },
+ {
+ "name": "shortestpath",
+ "type": "service-function-scheduler-type:shortest-path",
+ "enabled": false
+ }
+ ]
+ }
+ }
++
+If using the Linux curl command, it could be:
++
+ curl -i -H "Content-Type: application/json" -H "Cache-Control: no-cache" --data '$${Service_function_schudule_type.json}'
+ -X PUT --user admin:admin http://localhost:8181/restconf/config/service-function-scheduler-type:service-function-scheduler-types/
++
+Here is also a snapshot for using the RESTClient plugin:
+
+.Mozilla Firefox RESTClient
+image::sfc/RESTClient-snapshot.png["Mozilla Firefox RESTClient",width=500]
+
+* SFC-UI.SFC-UI provides a drop down menu for service function selection
+ algorithm. Here is a snapshot for the user interaction from SFC-UI when
+ creating a Rendered Service Path.
+
+.Karaf Web UI
+image::sfc/karaf-webui-select-a-type.png["Karaf Web UI",width=500]
+NOTE: Some service function selection algorithms in the drop list are not
+ implemented yet. Only the first three algorithms are committed at the
+ moment.
===== Random
-TBD
+Select Service Function from the name list randomly.
====== Overview
-An overview of the use case.
+The Random algorithm is used to select one Service Function from the name list
+which it gets from the Service Function Type randomly.
====== Prerequisites
-TBD
+* Service Function information are stored in datastore.
+* Either no algorithm or the Random algorithm is selected.
====== Target Environment
-TBD
+The Random algorithm will work either no algorithm type is selected or the
+Random algorithm is selected.
====== Instructions
-TBD
+Once the plugins are installed into Karaf successfully, a user can use his
+favorite method to select the Random scheduling algorithm type.
+There are no special instructions for using the Random algorithm.
===== Round Robin
-TBD
+Select Service Function from the name list in Round Robin manner.
====== Overview
-TBD
+The Round Robin algorithm is used to select one Service Function from the name
+list which it gets from the Service Function Type in a Round Robin manner, this
+will balance workloads to all Service Functions. However, this method cannot
+help all Service Functions load the same workload because it's flow-based
+Round Robin.
====== Prerequisites
-TBD
+* Service Function information are stored in datastore.
+* Round Robin algorithm is selected
====== Target Environment
-TBD
+The Round Robin algorithm will work one the Round Robin algorithm is selected.
====== Instructions
-TBD
+Once the plugins are installed into Karaf successfully, a user can use his
+favorite method to select the Round Robin scheduling algorithm type.
+There are no special instructions for using the Round Robin algorithm.
-===== Load Balance
-TBD
+===== Load Balance Algorithm
+Select appropriate Service Function by actual CPU utilization.
====== Overview
-An overview of the use case.
+The Load Balance Algorithm is used to select appropriate Service Function
+by actual CPU utilization of service functions. The CPU utilization of
+service function obtained from monitoring information reported via NETCONF.
====== Prerequisites
-TBD
-
-====== Target Environment
-TBD
+* CPU-utilization for Service Function.
+* NETCONF server.
+* NETCONF client.
+* Each VM has a NETCONF server and it could work with NETCONF client well.
====== Instructions
-TBD
+Set up VMs as Service Functions. enable NETCONF server in VMs.
+Ensure that you specify them separately. For example:
+
+.1 *Setting up the VM*
+.. Set up 4 VMs include 2 SFs' type are Firewall, Others are Napt44. Name them
+ as firewall-1, firewall-2, napt44-1, napt44-2 as Service Function.
+ The four VMs can run either the same server or different servers.
+.. Install NETCONF server on every VM and enable it.
+ More information on NETCONF can be found on the OpenDaylight wiki here:
+ https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Examples:Netconf:Manual_netopeer_installation
+.. Get Monitoring data from NETCONF server.
+ These monitoring data should be get from the NETCONF server which is running
+ in VMs. The following static XML data is an example:
+
+static XML data like this:
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<service-function-description-monitor-report>
+ <SF-description>
+ <number-of-dataports>2</number-of-dataports>
+ <capabilities>
+ <supported-packet-rate>5</supported-packet-rate>
+ <supported-bandwidth>10</supported-bandwidth>
+ <supported-ACL-number>2000</supported-ACL-number>
+ <RIB-size>200</RIB-size>
+ <FIB-size>100</FIB-size>
+ <ports-bandwidth>
+ <port-bandwidth>
+ <port-id>1</port-id>
+ <ipaddress>10.0.0.1</ipaddress>
+ <macaddress>00:1e:67:a2:5f:f4</macaddress>
+ <supported-bandwidth>20</supported-bandwidth>
+ </port-bandwidth>
+ <port-bandwidth>
+ <port-id>2</port-id>
+ <ipaddress>10.0.0.2</ipaddress>
+ <macaddress>01:1e:67:a2:5f:f6</macaddress>
+ <supported-bandwidth>10</supported-bandwidth>
+ </port-bandwidth>
+ </ports-bandwidth>
+ </capabilities>
+ </SF-description>
+ <SF-monitoring-info>
+ <liveness>true</liveness>
+ <resource-utilization>
+ <packet-rate-utilization>10</packet-rate-utilization>
+ <bandwidth-utilization>15</bandwidth-utilization>
+ <CPU-utilization>12</CPU-utilization>
+ <memory-utilization>17</memory-utilization>
+ <available-memory>8</available-memory>
+ <RIB-utilization>20</RIB-utilization>
+ <FIB-utilization>25</FIB-utilization>
+ <power-utilization>30</power-utilization>
+ <SF-ports-bandwidth-utilization>
+ <port-bandwidth-utilization>
+ <port-id>1</port-id>
+ <bandwidth-utilization>20</bandwidth-utilization>
+ </port-bandwidth-utilization>
+ <port-bandwidth-utilization>
+ <port-id>2</port-id>
+ <bandwidth-utilization>30</bandwidth-utilization>
+ </port-bandwidth-utilization>
+ </SF-ports-bandwidth-utilization>
+ </resource-utilization>
+ </SF-monitoring-info>
+</service-function-description-monitor-report>
+----
+
+.2 *Start SFC*
+.. Unzip SFC release tarball.
+.. Run SFC: ${SFC}/bin/karaf.
+More information on Service Function Chaining can be found on the OpenDaylight
+SFC's wiki page:
+https://wiki.opendaylight.org/view/Service_Function_Chaining:Main
-===== Shortest Path
-TBD
+.3 *Verify the Load Balance Algorithm*
+.. Deploy the SFC2 (firewall-abstract2=>napt44-abstract2) and click button to
+ Create Rendered Service Path in SFC UI (http://localhost:8181/sfc/index.html).
+.. Verify the Rendered Service Path to ensure the CPU utilization of the
+ selected hop is the minimum one among all the service functions with same
+ type.
+The correct RSP is firewall-1=>napt44-2
+
+===== Shortest Path Algorithm
+Select appropriate Service Function by Dijkstra's algorithm. Dijkstra's
+algorithm is an algorithm for finding the shortest paths between nodes in a
+graph.
====== Overview
-An overview of the use case.
+The Shortest Path Algorithm is used to select appropriate Service Function by
+actual topology.
====== Prerequisites
-TBD
-
-====== Target Environment
-TBD
+* Depolyed topology (include SFFs, SFs and their links).
+* Dijkstra's algorithm. More information on Dijkstra's algorithm can be found
+on the wiki here:
+http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
====== Instructions
-TBD
+.1 *Start SFC*
+.. Unzip SFC release tarball.
+.. Run SFC: ${SFC}/bin/karaf.
+.. Depoly SFFs and SFs. import the service-function-forwarders.json and
+ service-functions.json in UI (http://localhost:8181/sfc/index.html#/sfc/config)
+
+service-function-forwarders.json:
+----
+{
+ "service-function-forwarders": {
+ "service-function-forwarder": [
+ {
+ "name": "SFF-br1",
+ "service-node": "OVSDB-test01",
+ "rest-uri": "http://localhost:5001",
+ "sff-data-plane-locator": [
+ {
+ "name": "eth0",
+ "service-function-forwarder-ovs:ovs-bridge": {
+ "uuid": "4c3778e4-840d-47f4-b45e-0988e514d26c",
+ "bridge-name": "br-tun"
+ },
+ "data-plane-locator": {
+ "port": 5000,
+ "ip": "192.168.1.1",
+ "transport": "service-locator:vxlan-gpe"
+ }
+ }
+ ],
+ "service-function-dictionary": [
+ {
+ "sff-sf-data-plane-locator": {
+ "port": 10001,
+ "ip": "10.3.1.103"
+ },
+ "name": "napt44-1",
+ "type": "service-function-type:napt44"
+ },
+ {
+ "sff-sf-data-plane-locator": {
+ "port": 10003,
+ "ip": "10.3.1.102"
+ },
+ "name": "firewall-1",
+ "type": "service-function-type:firewall"
+ }
+ ],
+ "connected-sff-dictionary": [
+ {
+ "name": "SFF-br3"
+ }
+ ]
+ },
+ {
+ "name": "SFF-br2",
+ "service-node": "OVSDB-test01",
+ "rest-uri": "http://localhost:5002",
+ "sff-data-plane-locator": [
+ {
+ "name": "eth0",
+ "service-function-forwarder-ovs:ovs-bridge": {
+ "uuid": "fd4d849f-5140-48cd-bc60-6ad1f5fc0a1",
+ "bridge-name": "br-tun"
+ },
+ "data-plane-locator": {
+ "port": 5000,
+ "ip": "192.168.1.2",
+ "transport": "service-locator:vxlan-gpe"
+ }
+ }
+ ],
+ "service-function-dictionary": [
+ {
+ "sff-sf-data-plane-locator": {
+ "port": 10002,
+ "ip": "10.3.1.103"
+ },
+ "name": "napt44-2",
+ "type": "service-function-type:napt44"
+ },
+ {
+ "sff-sf-data-plane-locator": {
+ "port": 10004,
+ "ip": "10.3.1.101"
+ },
+ "name": "firewall-2",
+ "type": "service-function-type:firewall"
+ }
+ ],
+ "connected-sff-dictionary": [
+ {
+ "name": "SFF-br3"
+ }
+ ]
+ },
+ {
+ "name": "SFF-br3",
+ "service-node": "OVSDB-test01",
+ "rest-uri": "http://localhost:5005",
+ "sff-data-plane-locator": [
+ {
+ "name": "eth0",
+ "service-function-forwarder-ovs:ovs-bridge": {
+ "uuid": "fd4d849f-5140-48cd-bc60-6ad1f5fc0a4",
+ "bridge-name": "br-tun"
+ },
+ "data-plane-locator": {
+ "port": 5000,
+ "ip": "192.168.1.2",
+ "transport": "service-locator:vxlan-gpe"
+ }
+ }
+ ],
+ "service-function-dictionary": [
+ {
+ "sff-sf-data-plane-locator": {
+ "port": 10005,
+ "ip": "10.3.1.104"
+ },
+ "name": "test-server",
+ "type": "service-function-type:dpi"
+ },
+ {
+ "sff-sf-data-plane-locator": {
+ "port": 10006,
+ "ip": "10.3.1.102"
+ },
+ "name": "test-client",
+ "type": "service-function-type:dpi"
+ }
+ ],
+ "connected-sff-dictionary": [
+ {
+ "name": "SFF-br1"
+ },
+ {
+ "name": "SFF-br2"
+ }
+ ]
+ }
+ ]
+ }
+}
+----
+
+service-functions.json:
+----
+{
+ "service-functions": {
+ "service-function": [
+ {
+ "rest-uri": "http://localhost:10001",
+ "ip-mgmt-address": "10.3.1.103",
+ "sf-data-plane-locator": [
+ {
+ "name": "preferred",
+ "port": 10001,
+ "ip": "10.3.1.103",
+ "service-function-forwarder": "SFF-br1"
+ }
+ ],
+ "name": "napt44-1",
+ "type": "service-function-type:napt44",
+ "nsh-aware": true
+ },
+ {
+ "rest-uri": "http://localhost:10002",
+ "ip-mgmt-address": "10.3.1.103",
+ "sf-data-plane-locator": [
+ {
+ "name": "master",
+ "port": 10002,
+ "ip": "10.3.1.103",
+ "service-function-forwarder": "SFF-br2"
+ }
+ ],
+ "name": "napt44-2",
+ "type": "service-function-type:napt44",
+ "nsh-aware": true
+ },
+ {
+ "rest-uri": "http://localhost:10003",
+ "ip-mgmt-address": "10.3.1.103",
+ "sf-data-plane-locator": [
+ {
+ "name": "1",
+ "port": 10003,
+ "ip": "10.3.1.102",
+ "service-function-forwarder": "SFF-br1"
+ }
+ ],
+ "name": "firewall-1",
+ "type": "service-function-type:firewall",
+ "nsh-aware": true
+ },
+ {
+ "rest-uri": "http://localhost:10004",
+ "ip-mgmt-address": "10.3.1.103",
+ "sf-data-plane-locator": [
+ {
+ "name": "2",
+ "port": 10004,
+ "ip": "10.3.1.101",
+ "service-function-forwarder": "SFF-br2"
+ }
+ ],
+ "name": "firewall-2",
+ "type": "service-function-type:firewall",
+ "nsh-aware": true
+ },
+ {
+ "rest-uri": "http://localhost:10005",
+ "ip-mgmt-address": "10.3.1.103",
+ "sf-data-plane-locator": [
+ {
+ "name": "3",
+ "port": 10005,
+ "ip": "10.3.1.104",
+ "service-function-forwarder": "SFF-br3"
+ }
+ ],
+ "name": "test-server",
+ "type": "service-function-type:dpi",
+ "nsh-aware": true
+ },
+ {
+ "rest-uri": "http://localhost:10006",
+ "ip-mgmt-address": "10.3.1.103",
+ "sf-data-plane-locator": [
+ {
+ "name": "4",
+ "port": 10006,
+ "ip": "10.3.1.102",
+ "service-function-forwarder": "SFF-br3"
+ }
+ ],
+ "name": "test-client",
+ "type": "service-function-type:dpi",
+ "nsh-aware": true
+ }
+ ]
+ }
+}
+----
+
+The depolyed topology like this:
+----
+
+ +----+ +----+ +----+
+ |sff1|+----------|sff3|---------+|sff2|
+ +----+ +----+ +----+
+ | |
+ +--------------+ +--------------+
+ | | | |
+ +----------+ +--------+ +----------+ +--------+
+ |firewall-1| |napt44-1| |firewall-2| |napt44-2|
+ +----------+ +--------+ +----------+ +--------+
+
+----
+
+.2 *Verify the Shortest Path Algorithm*
+** Deploy the SFC2(firewall-abstract2=>napt44-abstract2), select "Shortest
+ Path" as schedule type and click button to Create Rendered Service Path in
+ SFC UI (http://localhost:8181/sfc/index.html).
+
+.select schedule type
+image::sfc/sf-schedule-type.png["select schedule type",width=500]
+
+** Verify the Rendered Service Path to ensure the selected hops are linked in
+ one SFF. The correct RSP is firewall-1=>napt44-1 or firewall-2=>napt44-2.
+ The first SF type is Firewall in Service Function Chain. So the algorithm
+ will select first Hop randomly among all the SFs type is Firewall.
+ Assume the first selected SF is firewall-2.
+ All the path from firewall-1 to SF which type is Napt44 are list:
+
+* Path1: firewall-2 -> sff2 -> napt44-2
+* Path2: firewall-2 -> sff2 -> sff3 -> sff1 -> napt44-1
+The shortest path is Path1, so the selected next hop is napt44-2.
+
+.rendered service path
+image::sfc/sf-rendered-service-path.png["rendered service path",width=500]