Merge "Bring in SFC support"
diff --git a/.kitchen.yml b/.kitchen.yml
index 22dc4e7..222d4e0 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -158,6 +158,11 @@
       pillars-from-files:
         neutron.sls: tests/pillar/control_bgpvpn.sls
 
+  - name: control_sfc
+    provisioner:
+      pillars-from-files:
+        neutron.sls: tests/pillar/control_sfc.sls
+
   - name: gateway_dvr
     provisioner:
       pillars-from-files:
diff --git a/README.rst b/README.rst
index 620e100..f108a5b 100644
--- a/README.rst
+++ b/README.rst
@@ -961,6 +961,27 @@
         provider_mappings: physnet1:br-floating
 
 
+Service Function Chaining Extension (SFC)
+----------------
+
+.. code-block:: yaml
+
+    neutron:
+      server:
+        sfc:
+          enabled: true
+          sfc_drivers:
+            - ovs # valid options: ovs, odl, ovn (not implemented yet)
+          flow_classifier_drivers:
+            - ovs # valid options: see above
+      ....
+      compute:
+        backend:
+          ovs_extension:
+            sfc:
+              enabled: True
+
+
 Neutron Server
 --------------
 
diff --git a/neutron/files/queens/neutron-server.conf b/neutron/files/queens/neutron-server.conf
index 2edcdab..28eff23 100644
--- a/neutron/files/queens/neutron-server.conf
+++ b/neutron/files/queens/neutron-server.conf
@@ -69,6 +69,7 @@
 {%- if server.get('vlan_aware_vms', False) -%},trunk{%- endif -%}
 {%- if server.l2gw is defined and server.l2gw.get('enabled', False) -%},networking_l2gw.services.l2gateway.plugin.L2GatewayPlugin{%- endif -%}
 {%- if server.get('bgp_vpn', {}).get('enabled', False) -%},bgpvpn{%- endif -%}
+{%- if server.get('sfc', {}).get('enabled', False) -%},flow_classifier,sfc{%- endif -%}
 
 {% endif %}
 {%- endif %}
@@ -564,3 +565,7 @@
 {% if server.bgp_vpn is defined -%}
 {%- include "neutron/files/queens/bgpvpn.conf" %}
 {% endif %}
+
+{% if server.sfc is defined -%}
+{%- include "neutron/files/queens/plugins/sfc.conf" %}
+{% endif %}
diff --git a/neutron/files/queens/plugins/sfc.conf b/neutron/files/queens/plugins/sfc.conf
new file mode 100644
index 0000000..5d4dcf9
--- /dev/null
+++ b/neutron/files/queens/plugins/sfc.conf
@@ -0,0 +1,9 @@
+{%- if server.sfc.enabled|default(False) %}
+[sfc]
+# Ordered list of sfc drivers
+drivers = {{ server.sfc.sfc_drivers|join(',') }}
+
+[flowclassifier]
+# Ordered list of flow classifier drivers
+drivers = {{ server.sfc.flow_classifier_drivers|join(',') }}
+{%- endif %}
diff --git a/neutron/map.jinja b/neutron/map.jinja
index 69c7144..d4004a1 100644
--- a/neutron/map.jinja
+++ b/neutron/map.jinja
@@ -96,10 +96,16 @@
     },
 }, merge=pillar.neutron.get('gateway', {}), base='BaseDefaults') %}
 
+{%- set sfc_enabled = pillar.neutron.get('server', {}).get('sfc', {}).get('enabled', False) %}
+{%- set server_pkgs_list = ['neutron-server','python-neutron-lbaas', 'gettext-base', 'python-pycadf'] %}
+{%- if sfc_enabled %}
+{%- do server_pkgs_list.append('python-networking-sfc') %}
+{%- endif %}
+
 {% set server = salt['grains.filter_by']({
     'BaseDefaults': default_params,
     'Debian': {
-        'pkgs': ['neutron-server','python-neutron-lbaas', 'gettext-base', 'python-pycadf'],
+        'pkgs': server_pkgs_list,
         'pkgs_ovn': ['python-networking-ovn', 'ovn-common', 'ovn-central'],
         'pkgs_ml2': ['neutron-plugin-ml2'],
         'pkgs_l2gw': ['python-networking-l2gw'],
diff --git a/tests/pillar/control_sfc.sls b/tests/pillar/control_sfc.sls
new file mode 100644
index 0000000..81a4bc2
--- /dev/null
+++ b/tests/pillar/control_sfc.sls
@@ -0,0 +1,21 @@
+include:
+  - .control_nodvr
+
+neutron:
+  server:
+    version: queens
+    sfc:
+      enabled: true
+      sfc_drivers:
+        - ovs
+      flow_classifier_drivers:
+        - ovs
+
+linux:
+  system:
+    enabled: true
+    repo:
+      mirantis_openstack_queens:
+        source: "deb http://mirror.fuel-infra.org/mcp-repos/queens/xenial queens main"
+        architectures: amd64
+        key_url: "http://mirror.fuel-infra.org/mcp-repos/queens/xenial/archive-mcpqueens.key"