From 018cfe5a27a5e48c70f98286d8862906c3320b73 Mon Sep 17 00:00:00 2001 From: Johnson Li Date: Wed, 20 May 2015 15:57:32 +0800 Subject: [PATCH] SF scheduler and monitoring documents - I am submitting for Johnson Li, as they are having problems with git in China. - Patch Set 2: Colin wrapped long lines to 80 characters and also fixed some formatting issues. - Patch Set 3: Small fixes with Colin's comments. Change-Id: Ic7bcb029918ce8e319c0ac4db807794941f845f4 Signed-off-by: Johnson Li --- .../sfc/odl-sfc-sf-scheduler-dev.adoc | 51 +- .../odl-sfc-sf-selection-algorithm-dev.adoc | 19 - .../src/main/asciidoc/sfc/sfc.adoc | 2 - .../images/sfc-sf-selection-arch.png | Bin 0 -> 23664 bytes .../sfc/odl-sfc-sf-scheduler-user.adoc | 523 ++++++++++++++++-- .../odl-sfc-sf-selection-algorithm-user.adoc | 394 ------------- .../user-guide/src/main/asciidoc/sfc/sfc.adoc | 2 - .../images/sfc/RESTClient-snapshot.png | Bin 0 -> 27533 bytes .../images/sfc/karaf-webui-select-a-type.png | Bin 0 -> 14544 bytes .../images/sfc/sf-selection-arch.png | Bin 0 -> 36004 bytes 10 files changed, 536 insertions(+), 455 deletions(-) delete mode 100644 manuals/developer-guide/src/main/asciidoc/sfc/odl-sfc-sf-selection-algorithm-dev.adoc create mode 100644 manuals/developer-guide/src/main/resources/images/sfc-sf-selection-arch.png delete mode 100644 manuals/user-guide/src/main/asciidoc/sfc/odl-sfc-sf-selection-algorithm-user.adoc create mode 100644 manuals/user-guide/src/main/resources/images/sfc/RESTClient-snapshot.png create mode 100644 manuals/user-guide/src/main/resources/images/sfc/karaf-webui-select-a-type.png create mode 100644 manuals/user-guide/src/main/resources/images/sfc/sf-selection-arch.png diff --git a/manuals/developer-guide/src/main/asciidoc/sfc/odl-sfc-sf-scheduler-dev.adoc b/manuals/developer-guide/src/main/asciidoc/sfc/odl-sfc-sf-scheduler-dev.adoc index f3ffafad9..d13ad5bc4 100644 --- a/manuals/developer-guide/src/main/asciidoc/sfc/odl-sfc-sf-scheduler-dev.adoc +++ b/manuals/developer-guide/src/main/asciidoc/sfc/odl-sfc-sf-scheduler-dev.adoc @@ -1,16 +1,53 @@ -=== Service Function Scheduler +=== Service Function Scheduling Algorithms ==== Overview -TBD +When creating the Rendered Service Path (RSP), the earlier release of SFC +chose the first available service function from a list of service function +names. Now a new API is introduced to allow developers to develop their own +schedule algorithms when creating the RSP. There are four scheduling algorithms +(Random, Round Robin, Load Balance and Shortest Path) are provided as examples +for the API definition. This guide gives a simple introduction of how to develop +service function scheduling algorithms based on the current extensible framework. ==== Architecture -TBD +The following figure illustrates the service function selection framework and +algorithms. + +.SF Scheduling Algorithm framework Architecture +image::sfc-sf-selection-arch.png["SF Selection Architecture",width=500] + +The YANG Model defines the Service Function Scheduling Algorithm type +identities and how they are stored in the MD-SAL data store for the scheduling +algorithms. + +The MD-SAL data store stores all informations for the scheduling algorithms, +including their types, names, and status. + +The API provides some basic APIs to manage the informations stored in the +MD-SAL data store, like putting new items into it, getting all scheduling +algorithms, etc. + +The RESTCONF API provides APIs to manage the informations stored in the MD-SAL +data store through RESTful calls. + +The Service Function Chain Renderer gets the enabled scheduling algorithm type, +and schedules the service functions with scheduling algorithm implementation. ==== Key APIs and Interfaces -TBD +While developing a new Service Function Scheduling Algorithm, a new class +should be added and it should extend the base schedule class +SfcServiceFunctionSchedulerAPI. And the new class should implement the abstract +function: + ++public List scheduleServiceFuntions(ServiceFunctionChain chain, int serviceIndex)+. + +.input +* *+ServiceFunctionChain chain+*: the chain which will be rendered +* *+int serviceIndex+*: the initial service index for this rendered service path -===== API Group 1 -TBD +.output +* *+List+*: a list of service funtion names which scheduled by the +Service Function Scheduling Algorithm. ==== API Reference Documentation -TBD +Please refer the API docs generated in the mdsal-apidocs. diff --git a/manuals/developer-guide/src/main/asciidoc/sfc/odl-sfc-sf-selection-algorithm-dev.adoc b/manuals/developer-guide/src/main/asciidoc/sfc/odl-sfc-sf-selection-algorithm-dev.adoc deleted file mode 100644 index d6e7d99c1..000000000 --- a/manuals/developer-guide/src/main/asciidoc/sfc/odl-sfc-sf-selection-algorithm-dev.adoc +++ /dev/null @@ -1,19 +0,0 @@ -=== Service Function Selection Algorithm Developer Guide - -==== Overview -The service function selection framework supports at least four algorithms (e.g. Random, Round Robin, Load Balancing, Shortest Path) to choose the most appropriate service function when instantiating the RSP. In addition, it is an extensible framework that allows 3rd party scheduler with optimized algorithms to be plugged in. - -==== Service Function Selection Algorithm Architecture -Provide information about Service Function Selection Algorithm components and how they work together. -Also include information about how the Service Function Selection Algorithm integrates withOpenDaylight. - -==== Key APIs and Interfaces - -===== RESTConf -RESTConf Northbound SFC API provides GUI/REST interactions for choosing the service function selection algorithm. - -===== MD-SAL -MD-SAL Datastore provides all supported service function selection algorithms, and provides APIs to enable one of the provided service function selection algorithm. - -==== API Reference Documentation -Provide links to JavaDoc, REST API documentation, etc. diff --git a/manuals/developer-guide/src/main/asciidoc/sfc/sfc.adoc b/manuals/developer-guide/src/main/asciidoc/sfc/sfc.adoc index db65104f9..97c532ab8 100644 --- a/manuals/developer-guide/src/main/asciidoc/sfc/sfc.adoc +++ b/manuals/developer-guide/src/main/asciidoc/sfc/sfc.adoc @@ -14,5 +14,3 @@ include::odl-sfc-sf-scheduler-dev.adoc[Service Function selection scheduler] include::odl-sfc-sf-monitoring-dev.adoc[Service Function Monitoring] -include::odl-sfc-sf-selection-algorithm-dev.adoc[Service Function Selection Algorithm guide] - diff --git a/manuals/developer-guide/src/main/resources/images/sfc-sf-selection-arch.png b/manuals/developer-guide/src/main/resources/images/sfc-sf-selection-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..357bf599207b1565b68dac6fadba3e3adf64284f GIT binary patch literal 23664 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 HijweO8I1YJ literal 0 HcmV?d00001 diff --git a/manuals/user-guide/src/main/asciidoc/sfc/odl-sfc-sf-scheduler-user.adoc b/manuals/user-guide/src/main/asciidoc/sfc/odl-sfc-sf-scheduler-user.adoc index b76202964..293bdb687 100644 --- a/manuals/user-guide/src/main/asciidoc/sfc/odl-sfc-sf-scheduler-user.adoc +++ b/manuals/user-guide/src/main/asciidoc/sfc/odl-sfc-sf-scheduler-user.adoc @@ -1,71 +1,532 @@ -=== 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: +---- + + + + 2 + + 5 + 10 + 2000 + 200 + 100 + + + 1 + 10.0.0.1 + 00:1e:67:a2:5f:f4 + 20 + + + 2 + 10.0.0.2 + 01:1e:67:a2:5f:f6 + 10 + + + + + + true + + 10 + 15 + 12 + 17 + 8 + 20 + 25 + 30 + + + 1 + 20 + + + 2 + 30 + + + + + +---- + +.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] diff --git a/manuals/user-guide/src/main/asciidoc/sfc/odl-sfc-sf-selection-algorithm-user.adoc b/manuals/user-guide/src/main/asciidoc/sfc/odl-sfc-sf-selection-algorithm-user.adoc deleted file mode 100644 index 7f3798450..000000000 --- a/manuals/user-guide/src/main/asciidoc/sfc/odl-sfc-sf-selection-algorithm-user.adoc +++ /dev/null @@ -1,394 +0,0 @@ -=== Service Function Selection Algorithm User Guide -The user guide contains the service function selection framework how to work. -It supports at least four algorithms (e.g. Random, Round Robin, Load Balancing, Shortest Path) - -==== Overview -When creating the Rendered Service Path, the SFC currently chooses the available service function from a list of available service functions randomly. This may result in lots of issues such as overloaded service functions and longest 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 (e.g. Random, Round Robin, Load Balancing, Shortest Path) to choose the most appropriate service function when instantiating the RSP. - -==== Service Function Selection Algorithm Architecture -Provide information about Service Function Selection Algorithm components and how they work together. -Also include information about how the Service Function Selection Algorithm integrates with -OpenDaylight. An architecture diagram could help. - -.Service Function Selection Algorithm Architecture -image::sfc/sf-selectionalgorithm-observations.png["Service Function Selection Algorithm Architecture",width=500] - -===== Load Balance Algorithm -Select appropriate Service Function by actual CPU utilization. - -====== Overview -The Load Balance Algorithm is used to select appropriate Service Function -by actual CPU utilization of living service functions. The CPU utilization of service function is one -of monitoring information reported via Netconf. - -====== Prerequisites -* CPU-utilization for Service Function. -* Netconf server. -* Netconf client. -* Each Vm has a Netconf server. Netconf client communicate with Netconf server well. - -====== Instructions -set up VMs as Service Functions. enable netconf server in VMs. -Ensure that you specify them separately. For example: - -.1 *Setting up the VM* -.. Setup 4 VMs include 2 SFs' type are Firewall, Others are Napt44. They're named firewall-1, firewall-2, napt44-1, napt44-2 as Service Function. -.. 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 -.. Install tools to monitor CPU utilization or using the static XML data. -Suppose the CPU-utilization in firewall-1 is 12, firewall-2 is 30, napt44-1 is 40, napt44-2 is 30. - -static XML data like this: ----- - - - - 2 - - 5 - 10 - 2000 - 200 - 100 - - - 1 - 10.0.0.1 - 00:1e:67:a2:5f:f4 - 20 - - - 2 - 10.0.0.2 - 01:1e:67:a2:5f:f6 - 10 - - - - - - true - - 10 - 15 - 12 - 17 - 8 - 20 - 25 - 30 - - - 1 - 20 - - - 2 - 30 - - - - - ----- - -.2 *Start SFC* -.. Build SFC. -.. Run SFC: ./sfc-karaf/target/assembly/bin/karaf. -More information on Service Function Chaining can be found on the OpenDaylight wiki here: -https://wiki.opendaylight.org/view/Service_Function_Chaining:Main - -.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 -The Shortest Path Algorithm is used to select appropriate Service Function by actual topology. - -====== Prerequisites -* 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 -.1 *Start SFC* -.. Build SFC. -.. Run SFC: ./sfc-karaf/target/assembly/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 linkd 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. Then the Algorithm will Breadth First Search the linkd SFFs and SFs. -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 shorest 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] - diff --git a/manuals/user-guide/src/main/asciidoc/sfc/sfc.adoc b/manuals/user-guide/src/main/asciidoc/sfc/sfc.adoc index 094396124..bb1c48f84 100644 --- a/manuals/user-guide/src/main/asciidoc/sfc/sfc.adoc +++ b/manuals/user-guide/src/main/asciidoc/sfc/sfc.adoc @@ -16,6 +16,4 @@ include::odl-sfc-sf-scheduler-user.adoc[Service Function selection scheduler] include::odl-sfc-sf-monitoring-user.adoc[Service Function Monitoring] -include::odl-sfc-sf-selection-algorithm-user.adoc[Service Function Selection Algorithm user guide] - include::odl-sfc-load-balance-user.adoc[Service Function Grouping and Load Balancing user guide] diff --git a/manuals/user-guide/src/main/resources/images/sfc/RESTClient-snapshot.png b/manuals/user-guide/src/main/resources/images/sfc/RESTClient-snapshot.png new file mode 100644 index 0000000000000000000000000000000000000000..9ffda8a21d5b5ea763eec3a239e885851dcf190c GIT binary patch literal 27533 zcmeFZ2T)W^7d8lpfFPitq7oI5BuU}`Ll7kg$r)6_NDf1sA&7{GM2V6HB#I=-k|l}6 zfdN6Xl7=C}3_0!feFgl!`gg1L-~G30x7I3w>FL||^y$;*p7WfiZ}1~Ed2-U5qWTX9$s+-*};?Zz~>82 z3Iv$?rhijme}b)^mQcpT~ij9Op}?*ihXI^ zZ)1dNL+)?{-R3a0`fxc&U?x(w$KHQ!cMznL(~~Raw!EP1R!3{@^~1!Cr$}sk6C;q5 zw`wr=3Xgz<>G_`@vxF-gl{buToqPtq`En1FAoJH}X#;!|)PSQx77w5BlJq}6p5wZ% z|NGZJAJg*jFje_iM*kW`8fJCz^d{!4PTr$tlhI!A$#7Y8!34wcqpj?XZ}Iiz&Dq22 z1-w;Be)FHX;zyVa_V!l}qf8FXq^1T^J+(W+h55QEXp<*Of@M7qN*%DZmQjeLwCsx~ zay+&m40qgjcVMXyaF&7j;*7L3Dtr7e6Wd-Phl}>kFA;l#8M`_Ss}u5Wu%6%@cmGL> z>COG@rd~%BR9{VNp&Fd+1!@Jxyq80FIwlJtX+IXc{SGu;f&qDGf)M^Z2?!+P$S?J& zC%AC7Z(10yU3XX8f$ID0Y+w;i^(QCV{PO9%3M?+cJX+{GucO=|3ySO(gHPM|0C_H& zG3*Yap>DZ*{=G+6ij{wm$yf299M=a&z08vpt7fL*ImMQRLj$%IdNl{-x+*#7qxmSr z{Cp3JKQN#^LjjS4Wv8l#?E}}dAy?g}Z%>BCy;hJ^D@~TVk^|Y-5LnO8DBbL} zr%!W}Mk*jD+>kvVsiJG$E?5P>e&7wSdOdu%?iGulh7c5)aeO5$@ML)D^ZrXXyFu$( z#|5X)2l_}kn!@d{x#yP3i{^fVF)q8fT4qC9ZVpg+JP&_;O-nTdIYnLb7PP33i}8X5 zc$1@`fyLjlPe%JPPj;mcPI1Sl*5ke_XIt2+h8QSD^=D6@un7eb_HP^`?7^jXx4#`@jw#%n>h^Hi z>33@P$|lmSY;BiJ&Et=lN5+d3FNX%?m@WHhaSdG(yvu*Fsm5lj%!TX+K47rytdWwb zaUQejY>a)7h=MOV8t z4ux&W4ZN49w*Jy@H0$RT+#^_G3dpHr9-p2ge=Z^d3NtlTs}H$3oHqI8Z6*ofrDw&` z$7+`>mE0>h`1c2xT@&tX>OX8W3S?*SoYPMS!!KSqwDqfsDn*q#J}vi##r5Vo&SeBS zzu6+1$InEMZC`kDZ>zwZpYa7$Z_23rtTC<3wt^BAbm2$V9t{Uc zSOQ$FCRaYz&RDuH^*n4Ts;*}Lc8aeMPEhoqRB=tgn}ztt3=v#igM_K~8opVYO6>y7 ztN@I@jQvQvbSY&VXRAM`I9y9wg+RZF z?WOAzS0y4`DK$r5&bBxXHrr2+2)H|UXnSJ}jYH~RxANNdjb6wdNDn#RglFw0pY(xh zEWYnGhbMbSO3z|3dRf~H2FVx^=u40tz!@KDvsKoXgMDnAkkhFIm!#7I3AU7-H)7d* z97@zI)~ni+<?!`{`bUEvMNQ`#E_l73u87t@faGv#lXQ1On^A=1JLkC zesn%0=RDXl?%TO_Gf;s6jqOE>S&O$lAzLqt#np`$5^1+AxsuuR%T(@PQ~GT7Z{$j!cfr#T2vMt`1Cw`+cRp@RBGwi%L2_G9q;(p~fL)Y5h8 z=6J+(mD#3I^=x2`I4@X3ep;`2{$aPTYT1NlCe_Ev&uKsAT9-a9>6Nv-*_Q32F zX4p7;Tt*{#axe!0KH&&!q;I)O>Vx#qr9)*?&K@~lS9e$sY*sb(_Ot|p_*^!6UIp!A zQceJyqKtKSXPohB#C3GNV^Jp#?zK~+19>q`^Db8x;-}s{(8~`&2M0JZ2iF_d{H!6$ zxI*iDg?G{Db3uq_j3Tmgg3D7suyaw-yvMLl>Wv;!KnRwv^0sDHngUH37|o-(IWT$?56ZTS~zij?Q%29aOMf-0aIq80(2sM?T~d>6(95Li13T zXAy?n+6#N;_TUN3SKEwcWdBJc`|1eII(sYvTKMypB~d3|`qMWksP3f*tVdN9dZ+Ws z_f4^UTf>~Pr24s67g%AJ5~TuT-o50xdBKt)enCskJ)utnA?E$aN^%pz5vV%NU5d%T}sG)@0rh+uI(SWToeOi)=h;1O*eFxvz}3r)3}M?ob{0@o*V?oa6U_$Pq@nIO?bnE2-YDcX^*d`=wlU)6Sx%(f!gS*_EyE4_!ewU@~9nM%3Z}=n%q{By*w(`eZ za3z}IJFkFj9>{Sx38C=(-7iEUM%`+kai4~oU;e+|X$9mve@W^j2KpUdKa%^2c|)Ums(xGJ)e`pNgNV8=p`C z8G0I=1EY43Mj|?uis?_ak4KOR`TBRd~|{orI$BdmO+nB6v{ zWtV=$6;_N_CIxYr%*mIpZa)$RA5TMhXL~5kJTX;%7w=d>^&B!uFKm~rHaKlaKYHZZ zX~cfpttwd9Sat)oa_+L__l@S|jFIk4Cu8taR*k2E<>6)rt_UXBZ#7uXt{R9Dz+ zV4h+aW|EA6cB;!+=+qac;KsK770#cmsWcZMQ6fUCU9^@tk(*-LQP4jn87a&N_MVkq z8-8dTXQ-}0lZ~$3P_?dh(n?HFh0Mxv5ebH!&TNm9?*M0~EAxQ5dEEl)8bQ&9XuYL@ z;E6?GJ1a{*A8UnXqU$LhkjkIT*6`LNX0UiCTl$ib%{cVw3aD5?>`e~lh7CQWU#l}D zb`VSx+wkslzNsAc^Biz5;lJ*6o39sVmz|)hR!(iBQN0X@>3(Tv?U@sJ-38vZ#M5Ly zQ9&=K|F2BQt$X+*E&aF-QoWMhSlV6r4wGw9@6Zn4WwMJ;W)H*+7Y2Z2B~iIx%!wCg zW#!c^Hrt1yKUVzWwdBNnszBw}0t}TrVUb9K4banE?&ve2ORp?i*=vq(n zOzvyfpTfd<6W{iAnSK*zijx69zRe>~SDytR6Vba3nY%I67aNRWi;sXAbn zu3N$4tdcNKN`0FTD`If7yi>@#9Xy!b$KuirEcj1Q*53#Yh7WnW ze+rUmD?FKmwC#DK7{vZev&|dHM$Nk?N_hTUFU=0dgZ(}Xnj9Es^FcvVA9Gwg-E{w* zN3-G2A>dQykQ2Mc^H;lYB?qnM+-q>!giq)KZ1;MESdAl=#1&IFM{r?Ynzc>BZ zrlzK`v9T=W_?}cLzc|{{CBq{y=VWr$yI=Ic?7|lV>uM%25{Wdca+w`0Fj`z(q#gT9 z-0NEY<>lqHA`Wz57_KFlI_f<>h&ui3eJ^W( zFUAY*%rEZ}3wU$pVWm9?Ejo5*q@=`Wf9r66 zJ5|!B+7Kq`u|ns4Vu!$3uBwk02Mgd^OCXmSg>u|o#_XlUD~AtH_WmX5$DMK9H6E*R z-;tRRqH}-E`#eFCh~q@L?NDO?u_7|`>ZytOCla`TNvqmp$4B7(ChSX67%$m(RuIT+ zX>^Hipph1VWBu-2AQ?@^#l|N7ks)%?Jym+=j(?o%vvTPOHV07Zgy`O!k>5tS`L^H3 zIw{oAVuPsmJ5vQDEmg`SY>~TaVY8cJa^`|xU0;%M|Jp#V7FF7Qq7R%mIb-sdhWgND z;E5zdCg@vXzcw)58Em8uYS@Gyqi3b|7RrxtG|PuoxNpZk3n59Fyu0{`xY}E#J@-2dj|0(U8jHs6-SR0%L+h*(+Nd3#!DX*FA!k#Rdp4^Y_G z*=U@z$o9(s&g-&$+&6Dsl_!(;vqNgQUId1|4)*6)M>6i?V*R#TD~{>*f8@wN267RB z2#Kg~4KgLF6KIyF;^%a_WHmsUXi{EUADHB};I?rjB1J^Iv4;Q9GW-+Fr3NYV|VF+U}+Mjii&||iXosu7n zR8h548oQHiHPFxM`OIa+cWxdoQKN97&$JHQPgLqrhlc)&u9}GE^FG#M1-HHT`ivP4 zjl?~&UXcD8z%BHJDmHFXGh(^#`ltTrh2b39{zrLD_X1qT(T;m*g4!9!v*}aUo!B{7 z7AI@{n(t|tb-&4M8_xJ-l@Ru2Gba)OZy|A}P(dONL0uZ2@7|$iheSsiB)#>II`)vq z2gpG5n4Itjk12|Nth}VpY$LDs!S2B?%7a)qS2h?cClwi@xH|nf1N|KN zKOb*KZ~K|*;LIj!SdP7A4+|Mf9QKb~+JdBvios^0TW{YgBH^t4E$bi>WFy!aHb@5Q zBA~>omq$$8tL8i)+Y51cGXL1X1}ORlDHon**L-A&ZfS{5xj($-7g+mSw4F5GqZks3%QTu zr9x1p2ZapxY7Q_ViyKHEKeru!8&$Ebx9VXXW7r8M0{I(yfsjSsCFgM6JPA!dzab8T zoH-^sHb3k{uKUOGm0_&$o0SE3SX_?7-tb~wzXTlErnZ@APvg+GG3X#!HPp|0WuUZ+ zIy!oNQm(^s80y*6v-dqZuz%@Qx?NzYxvY@xY9%Csw7aLEDA$G4?W0vzCYrND=&hEH zppIH>#gI?mGYpBdslH7nn%8$d#BV3aZ)dHU64}+IP1+{ZGotBRNA2+rv3fiZtA4Qm zMv8Nzers7PnBEOGaXhYV{R9?=K?^X(R;T0WmI@h4+^g2B5B4{f;`4+Q>#e+9QBb;6 zH_x6OEqIwesLF-8qp=75wM)>oEWUK0YNZ;2DqS7sP``gTgfA`)UoG1%+-A8Ok64bl zXt){;Q%8!u`I<*O0J>G*pE&mE8lgUQlg*Z1MEbJ;&o@7eJdMK<$3n*xIROO%uY|;w z;W;_YZWPXo9gev+p?XS$HzX39g}ICGRD~EWRw{WI3psH%Q7ow6mM`eoC^EEqWH4~K zw8-YZYmtt5Ns`#jOz9W>>DNlxj#MW#zk~dE*VY$cc5f_7r}5|Jvpg;mrHjWc(Nx}p zVI*cO6{W;WzWUwll}Wj%=fE;*4bEx0GfVdx$7sdgqhRbug?*BRO1ou+7Bk`y?0l}{9>1nOB3No zfgiP{a4DbhC-(x!_>aSox;CideM!)L4CoE=iKlyiDVQ_=`%N)9uOVsiVbQVMh-!+Q zT-rpqFmE;Hamr^1yW>#OYh=!X~rD zH&!1xcfS4(4Y#t2QP~_In;jpYKzaEn$6GffdK!4kk4YVs%Ef^9G;L?P)OKCh{hiE? z4#q2k3`+`vujvOgM83F;TE9HCTrYNBe-)$D13q5RYlx!G>k>O|mO2Ok)h%dqZ!5p+ ziRdXuj?`tNDg8D&+N8{O(Y%zekcA;h+ecpy#U0|SD}U@VE#-ArDHEN3 z?w7>Fl&}K7of6OF+`|B=w+Jm;yO5h-Nt{y~rbX_1t4CUR7H;Lr)J++v3v}iX&3aVj z%uIy=2FuWo?V|)s>=z@y?^iM8mprN*I@;)!mlWBb$5zg6ANoaeE;|komW~}mM0mzi z_8rZ9c=d%3$;uPF*ln6cUf^m=c9EPyiZFg9C=%9JVi3Ai=uW{#mEx3aSn#V$wvEeV zzhMO=mX2{s{tWT%hl)ur;*zOTY^5%Amy<1P=Le~a-qED)3NtD00mTOe37BuR?_yya z(5x+mwIE@5$WNi6-5TdX=?=GEW? zvegjpMbXEb&m}5w-8QOGrlGp93Ty=2#B}>MZJ$fn zTImZfY%h#YpGz>E%voY%sWc3LY<>GwvLajP%~KHl_+nCGL%viadPl;{&7dyC>YM6xndXE**RfCOEM^7;|-t{uIkwXRKmf2MStj9gk2cVA1 zvGm7^id8QyDnB|YeNO;)TWvRl1!spW-CSNt#IUTEj@Ak2Pl(c+>?6%gwv5(aI&b2P zCEAy{1FIGXSFb&%sC1D@+CKL$gn||xfBL=~kc=!$S@z8tTe|hzIZ41t*3-?*TNu6Kc z9jufT*w3=(1pA5Wj8y8t2Dkl049C~WHr4mvBfBQHfAX4e=#h=!7lXAHI@KMHYyiPLp^L(9=^*3hwVK2c3 zd8^0;Pb-w0VXSeFQK`ymqBXev12$$cav>XRgoq{i-lFvxvV^9Unm{d~>m9du(r767 z1T>fM=j@|I4lL_+6iRnsXh($O0|R2cO&%{NACsP&2`l|F<|E^J9)#-#k`6bd>hf)- zzj`JmdNOvBDEh#dNpoS88}I8!vJCRm4&kQgkCFu%QP$WNB{Cd8%BR?X3Q> z$Rf<{Im+&d;{+S2No~eUuua<0{r<54LM>h}JjtVk&h45-$Ofz;P@KkW*`Lkpe0 z1L)qqsPB7D9m)igqX=}|Y$|cRQ2}_{Z*HDg0m=G8KMO}k&29)z06niu=@R+)ZJu1G9sA(p+K!`7kN3O7;^vkr z$>Ca2c73#fqkNQ6huk2$8pY%Od$vjGgSypoay#R)iXxRdPl%LEuG|`zS>*s>)8=jO z&M!)2+TdLKeYbMr>|UvZY>7tw#+E%KBu%jcsxy^qk)7qYG_i;0uLi30?6@lU__V_~ zuq7?TO}^7JMiepC2$d^Nn^;vCq;B&Y#-%#BYsfTje?-^q*1E(6IhhT`S&&$J@CJ_T zp>y-~TMO(v{iUlMR$<@!7;oj;I%Jyaf6Rm!Q~+`7(etzeo(rE*Q{*Y{J5$TyYDmhS ziDS%1DQps?pce=lS#_G?D~^k_V+;-$sSt_&LJziBwG_@neav9=jI2UW zdA528bt>e=AUYe??JZ%2dp!Zmquf6aYg}q-9xP%Bqd+y~PzJg=$qP8ImoZYKO1f%D z&314g%^161xWn30gI^tClSeH}KB+eQ$iB%VLQDeAc;S5Z0k#U&AB8hkN)02r`}25z z<2kL2Tk~awKuZ+XiK6A(;K=G_R8FaVmKOBr>!#Y+6WCD!v6U1~-2ND}XG9r^P()^# zX6)g-e@AtaR^9fEW(-PU5yhk53~hg!m`S?RXUnb=Ja4fvK?wvfQz>v`H7Ero?*GmV zvv3FP!<6OwK{#Vhi?^xzRgM29j(Gm~B%xlgqi*0nJMBPzcc?mtP@aLH1TbEBMenrz z|G_T4c;=v)8`jqoC?&?W7%}I$MBYpb0F&w>6Z;okICts#HtwJ}f%2dR7-Kgq;_W}O zk^`AJA}I-u?G_24{PL*sXPs8=dZXMwScWPIZrX12XF3Gre7q6gkne0bn0ixU<0ztM zZ2!@yUnUKZ6$2ESD4EF}z>@uQ)Klx7e%)WkzrJvd?(mKpam+uWJ-XW)QEFe>SG5&v zR9#V0;gp3m9!a>fR7+*Ix zx0Uj9aNlD}kApe+(S7D+zwI2U`1%>*>nJEA)s2UzXim!I$o$-#RL9Bsy4qUryc7}Z zsxmWmiD-nlfG6e@O69wVPoHKvsEf+Ur*)WCHRM_54ed$q9K-Uxy6$#5)-)>U=l#&cn75SR{FQkg({6Y>SVNCAwDfo!zze4hjAcEVdVrimoAHbx(7gjm1j8$c2 zWvwXmX`O;U_=GI{j^ovCNCeoWG1>;Ri^@`#k6_>~6(qF$tJ7C$>GYzRx#iKy)yW1k zo(L0eaHq$UZ&{S`qi`#oRl^&7@TUew3=H`x!rKJ`LbQ1rVq3FrT7!16P>9 zLodzGX5#<N*b;h|7bIvD^flS>x$aGCh~}|1#H|xd6EIzp7}j2;adSNTQye z?L;vqY1qmane31=Ny&j~Dea5Q>!)V!PeB4$nNuX@_NlnivOqoV6%z;1>Alj<0WB1C z7S;c{px=I|Hxe+sTMBPZ%UYM_p93xDh!c3ulqbj{4f|Up|Ke-S^01XT=bWJv5v7Ij6_HWN-I80Y-$`wD2Q$%ejM9k_|F}Nj2hQM2mk8t#h2E3T z+iA>1*QrmiRkCe=^^w|NVh)DGoHb^pHkO7>J06>zP7$B*4N%5-cwZv?WE59ZCdeMh z8tS&U%V<=o*K_gwY8RK3ukW6Xae0~2QNi)3QGgsP5R5+aDMfz}!IimrmgdAygArp% z$?zU_)ycze(drA;+SXgy4&8N)B_b!ff`NHv0kjzn)D z-xc-m%VlLMLnYE%9E$p{=i!nOT*954_etPnvEI?C_seu0W@6(gI)e*RgqQ;uVh2tu zx1k@U%W-zxaEhF;ZtY?i`{(`#qbl!WP~kpzT5Vb$Ac z4=|ZvqAD`j4QX6uuAN#^M)t?-UU5F+2DiNh8A6{}PJLq3L6!FO_1uo^qGYaaA2Fr4 zCz*P)%T)50#M7d|51(9`8J?Xd6G9Drr(IyrayeQ1$J&H8S&%wT*;(UKiRLkY#?;Rx zg0q8u0*a7b7*wd%z3iG0@YlISTEsAo_eO0?7I$U=zx)YZ0Fq+w(7;z}{_}7DbVr%onI!08Pa2Rp?Ll6CT0zEom4- z#IyqMnPVXO-SqOF+v&_mLWA%yUJ~KVb!RT=`b(hcQpdo*f!A-F;bQuD_HvLt%l)fXB4f6G2NbOmOeMMe@a`p=WE=n=FmR7~H=6{<41*0pa`{qBG{@ zpKTa$>6s+htlqoI!sV#|p+(unr|gT4JSaqqMJ!8?j zcw$<7BtW2%mD%>So9w^D`Escr8`xR8x-hB|=%`yIDgfWTKTHxoB3dYrzc=o|bw#gY zWMfnjp6PoysR@4w{`e^*Caa zUw-+7DxIm4mHOeDTCZBGEi8d(_+xKEf9-}b+Ku2Uk@1CDFnMIM7_Mw)wp-j%?`q2NWa&_$DW_h~f9dNY z2bkDvrJkK%^7x03-&!T-<)qwSe5#!d5G$*x3kziNIcy^Ki4vKN_17h-dQ8xcOLssi zhHf{UUE=+|33~Erhzn$(Tf6f;(+eLr%!GQm@PJL!_87(~1l}emhI_1js%Bi)WXaan z@tmMpp`x)CGtG`XVDbKiTFMfTZ#W*%Qa@e`QkUAq^$E}@%Rx9Q{%hS{#URY|ym*u> z_P4+d>PPRJ-Xo|d1VQwK78l|p)DHsd7uRz`&>6Yr?c-59rpbKJA(^P|VbQCH06~1F z-g<+)+-0U|mWHuml@~$TF)Yac9{qvMlvGJ=$jx*MzT{P-Z(W<9Oquv`B$~a=4=F(0 zG-#Y$oHMNx?$KFR&DgqfyErZQR>j2Z6zyB*f%T_bn$T|=&ySA!1gNq)3uHCUQ~syD zeu+e3w}SWYRIte=WY#j(bu8~Te0J=oG}Xh$)d$nOfSX3ryU$A$u!RLEhCnp^=8;!erKR%#~$;j|o(|_brUFeFq7^f*AU@z3BrB-b*p2A1E`i^8# zXO$|GW8$9M_9l;IOOIJH%-BtS^>$=LLuU5(${#~F<6W7s3} zoDh%K75`=D{=(svbiNt*Rdk0dX~1sfEqA`rClVI8dFfJ9e#Prb9Yvif=;zu- zLapy5PNl9U7&~@1x;>e)4~DG9dEskA`S7KS_VLMD*%Miz?_NR<5iR+}6zGkBi}YRj z@f?}#WQ+5)hdJ`-B2zHjb5%?I@WYHeQ39Nyr8HUWk55hm0dhbRzLV2H6ue2B>^~8S zyt}4j%kToDDTGdrMg)YJX?Lau=+prD{Mxy|K8L>J&U+zi*9s~=x#TBed=DNPFkdcg zreN4_r2S}7_gG)3tAH!zPQc58`!>Dq(TH&u6zgaeh_7!{zO(qy(h!PdZBg+Yd{<GJVbaXww9_3ijTrt1=kgKrJPc_8LPos&Y73|L_XFd?NvNOWux^uBpP> z#VA{+$(M#YYp9n;3Qxqqc|YjAZTNV8M&6wv*E428l@5ynxvm$q#bFrU$;qr^l z+1o@In>3=l`k1uW2-vi9Qrj;at=ge62oY6@Y?>$U)QRpaDEZm+mdzEnWd>>_dURgc z$b&~X1X-(k%YaRswevW%Ce4AZYvm>gre>_7xvCkH0*BW&_Nf3Q^nXKi>4x*K-XY+f z#;VKocWK{(tQKLNJs-mvJ}SodYqtyCyn6S2T*zVT5GYqeF4Y~geJRKLLbCnl>q$ym68_ z0P|Kr&YCkAZ9Po;FToU$K8i1|{IBbusE&;1HCs{smfq`pC9)5-dP{BhR4)Mp-8pF6 zp~5ipt_*db%fQ$FHJ$Dph;{LU^bi`}EmnJt`OhTZNN$O3?_*R?#_0VFJX4|51)0(( zN&s>tIhp4;2~v4~;j_S{O!hf$EPVO_*NIC0FZD|Eg_)X|*vr#cvz|N(ft6PMC%+pm zvD{u652BzqJi%-{R>n{$O=|nJ(^Eo#j3c+0o_PMvitz^0*$nxJ!lI(ejEpj>)1(T| ze}a%@Psw4T-e>>la9=%D62LK#-Q6jo&QqI1W(~fFVmGQQ&oxe*Xcdounfp^k#T^5K zbZmwFsQbzo2fu!HR9+T3F!1~^dhJ&;Z^JIUueuU+=j-m8+Fw zF^-e@A9SYjsVnUfqov6~Cx^JKUHVITDO5~gj|HdxGg_HH0tiOH>%{`6y`*!1mK3ou z*E7Ca8XFLSsCzE~JpVuQ@8tkmawtSn&iF<1iooJiGm4*qAFfJ3OK!6&hFDdA%AlCKt%p|A%B2eDjw z4&&A3_4W0Qf1^qKSM`mIYMiIP_GQScCyU;?Vfgfuh%`D2a$%e*rM=r+?Ed_<6Wu(Q z)|5_P^*={UK`$0_H4Td@?K14l7x-{CXA)O=>Fi`P-(5@axfFyifOM2JFD%%2WX_*4 zN%07{xVT0u9VZ+7jxqf?fMEdyp~lnX4nQM@2rB?lAxH$Xe7LqUa^p!yp<>_PnRbQU za0z_d!2pOptoY7$DbpjSPhQwLlNxt=3C~Dem;M=SApPIW#9II}@qY@U2mp8|skOXr z@R{KSnmVo7f#KqF@=<@m5jeBQ0N+-P;to)+c<|_qjwW64g{dDK4WD+OAD-Vqlp-ac zTIGzl&+fcs+fKyguZFs_X$!QRSrpN2z5yIvs|B(tobUSRdoiUU8(wiqY6S5;?GJ>f z`}?tZByiLN2kPi~a$i`WM@-r11}M?oT{v{QRGhM#|ICV|(;Nw8RgitCkeS;Qwx*!n zNPw<)9~xQwJ!R`-Wc?EjzO!X+J5Q8=NO?(1Je`O!2wIXyjMHY#hchZxpCTkoy?*|e z6_A^{4kW6z?1>>iHvKaHn(LRZd_&;2MQ$5!n@99D?10oaI?k-*+~w;tW6-ZTL@7*m zl6=o#jz~VKq@9WwKKIgjFDCOqrN45>XvF?(*R1d!t8&%Z0FwT?IgloSfSYG(NFz8@ zMK03P`s{h_4@*_A9_`P{>)PXTN#C5QU_Md$361i z!#8e-W&kPVd!{vj#fDF>%UZ7F9!tmt(nZ-_$q0zyS`>4gU*-TWmiIK~L$9PXkL6R9 zTFmBE4o=ooNqRt+$FqK-N&iD|#B++gD8t{P$I@|GZ+%_nlU-DNMxVxdIG73tBr%-7 z8>r+Om(1gDvJm}-l?yqhU*qbtJhfR)7Gk^l4cRo}^&e8P;dyrAon zpE=AVo9FdRvFgclUFtTZ{X_}yI1eDEUF)-zuZC1})x~y4jb-Ut`&-Ob z78M{8%nrYQ|6VzRuKV8q_agEs5kzUQ<|>)S4sZ_ZQ033)E0#uCvkntQ_v$`h;Q%M8 zlXe(F3~t^YHs*}{z>{EN6T6Vb!G_kI^!C`?iT!R~$|Voc3;&N*V85Us7n{lHrK6c= zp{MvM%AB=ZDLdAJmhf5mOIa$%Pre!PRS?LO0r!u{mptDkjykCRR$-ZmbX38Nkz!Q| z(MbN}hXxmBC8W)iL4jKwheJE2iKQ~>KOUjvzuC752?InYdieqv10EkXGi!D-nVBh+OQ1x;SR9fw z3UT8v;G3EC^m4tDLKf5Zx+q^-1>{ESs}1W123KwmwMU2eL?YyE@_YY+oM9M)GhJ;Z zA~v@(zqL^Uidud4mQ1zt`vyQde{>r5`M;(5rUV?5?F7QDx5u!es$1>48wHuhDTwcu zA{HxNw%xI`cfgBe4&UPGI+|>%#sq-_7hg%w4qRMX%Z60lOL>5XuhtDw^ln{UWEobf zkB!OWt?6@u#Zj_!&^UKiUf4rnaWi+SRMnvKfA81N(qiDn`2*XAEnCLjZ}LYw5yw9W zpNaobT4f`S&cX@24diH$>^llQ=NMVE&p`4^q(B}N-qQe3kdFd+y?+I>A$BIV>$mm% zHuc1$X|m9p40;a0k(-z^OUU4fR6tV2Semp9H5_e1Qhl~sY0Sm|YzgUigav9>9fz4{ z4XL;?%2NlMHc2p11!?aHriCI8B`?MN^&}whhw0^G3xHI!gFFsg`BapocuA(vRZZU9a7v zr6(rPfLPiLsq|;JPOOu!2SC$V#gIKcg%3o0ve2!qt+qqg(C8wQI944+u2>-V zNcBTcjXI`Et#@keQ`S0f%wQOg#wmjk2zlM8S7%XMXv1?gB&^<`{*jY4W^Qv)oj_G5?8no=fMP z|9TtT=_U%0ixcaTO^{}!g}fB$HwSwQ(05|(<-6ZBHUBKivP!T_GKSWWG6#j!4G3EO z@g84QfE(nTOQdD(90JAk8kC|WGtr6M9Lq*x;O&}QSw>y2{um{ng?}+%lJ*1V({k8o zlQGN7Uj$<-5;=1;9c^?+nsCOjnE{sEmY%PF`u7t3?r%NsH2mP{?8_>Vy^^c#4*(h~ zwN3ED1M<6^9IEG!FWjygdm-MGv?;`$i&7C-T8^ImK%hb%+)Cg6M&;^)iGRw^DeerB ziw2e>qNZ`KtF90GzMeM;zj0@iAW>Up^ zxbkAk>=bHg+Ok4L&Q!~&?6w%sgx*^Zk66iO7HeM}p9>kTx2<21V@oV_Zt7f;S~*u{ zNHvr?JbV4FA`K&nNAG?OW8LxViPt~uRcAaF=RIr8wm@=!ovsV5`SLj%J>cObzRpIf zsasJpU5LH>VAU?OvdjiEoFFi`s3yV4e^()W(82x9HUw;z-IFi)UBWRwW!zo|J~H70 z*K}n{h9s93Z&FTRghv@)qY)irAdR`m0y`u zx_e}YwL05TQ#V<7t|7r}Sj$Gb3h?BD#o&iKW7llmnG~p0BLT_Cx<+xaBW!(nw>3=uYb!C5NRb*eI%QfN5+mYf~*S+VR47o?Y zg?`j14urn_-VddQB6Dv{=JVU?+o*XO)vgl@b>^U7oV#2phRKKKkJ;L6cB|1aq;&N6 z2C|0FhMY^e|ECrj@kKNn0+$=8v>TG*&xi1Iqkf6U*ny3b6OWuz+ zdpl0E8aGi%Jn;z)S>Nmt30uYqlzQB3d#LU{%sIZ#(9DpPTeZ$4*-6Yl{jKm(bZ1@Z z$Jg$8$%v%7IMJd9C)WDZ-&qBzL80bj6l_o#X*fX3AhW2BYbQ*Ac9Tz9Zcy!V+r2TS zz0C%O^R8Sjyieke6=@%e&(B49{(AM@$~Hw-lx;~JDVzuKaGMQT^VQ0%7CQfY(9Sw^DB#9vJ6fP9%8wBzq)d8Fk5_=g_6w!BzT{;JjH;LFnj zQ_`k#kr5H6XMg-eH$Wmt+RPL@@#A>@&exd05!k*g$3OQ60FM9ZPS+Q4biSJpGvY1h zt3IvSN_d+UYeLgD$1+Pc2lLq%X%)1~g*xw!&P*+LP(;l|7&(vrIH?`UsRLNfPxC0i z0aaSEzc01Q@=-tv8BJjefC{yDo7Ry+=?MlC8uvv%2hy&;uvgn3%^VF+eB+}Ut7R=X znD1KF4;_|4^^PKxe%hTt1sQC7gBVaZ{n4&T{Z>;?|J=lU4Ihh!s*0K#p;^QeADLIA z5n7FYFBEtx*Y?G!CezQlximuQojc4H@+d4DjCJ&qW6cf#K z%$nF!6cV2_*WNXVmAl#!v5!{}*RlzalMc@Pk^~)$M@;xVaD1>-ac86Eczy65PZ?``GOzo;RB%>Hfa?CdP?ECSGploX%sjoD!`8lF^%-NC#f22tOG7Ruw5Ab?sC z(NN-Q;XaFl=b>o^3-1<~7@3+?m-@op4%w0_SAcM2?`LD{z%l}7vWEz4ZLLHiObkXN z53{atC@aOdWVzD>(y+%@X7D2W!qKd$YM7zOGl;o9OGZIm1ycga zw-QGNx(bhaf4Rm0ucZO+%c*VR##+XpHeW?-AJN7oQcqlSthK4}hVh7Aa?VRJut*8t zG@{nZb95K0(#y&b##B+!(Ef{U0cW;M46B|XU+={&@3FngNEn_`qJY13HZJkF>MsPF zY8$_nscT@Acb7^z5;|yZQ2_5zMf%3&EA>D0s!5(t`P#W!Qk0xuo0LdPIaTU?Nnl;3 zbH-&gJtKNskPRHM9KuBZZv>bYCEcd$(86`4c4%zvcvvcNL`7BEhzsAFCT-2+4)5E^ zCR^KY0E?0)O`-6!f?3$@YSBPHWizvqrVqb&$>i-zfls$8tLc^t3%#G5&?tweKH=V( z2;K5pCa)TipITs@$gW1d3w@^oE5tQ5{RtdG3#9e*9731zmu=brUSp2VP00r+s9w;u zL%Dw*4PUO#qdLgL4|hm2o9Z^-y8aMf*CBLDF>|_$bb3gDw&{I_(%BXMWI+91P3`o3Nq7VWz#06?t=>MT|Km>cRxqn! zs4ekb@>9;hE6(0l+}-%mpN6!u^lsXx^p`T7w2*&8{82Ge>of9-vA;t$WD4sfPhWnD zsM`O&`{uX4zuvge_*+CrwXn09{|`I43jP(7A4F!zoyecoN|2(8z@)vKGc@f}3n~0ZlJF!Vk^ISN z2K{&qcv}Gq+NvQBDO@+-J`J(?g)>%H6GunKpxEWy zURUAMrF;dPBktLXfA`tiMd>KR!8vWvtSsH}*HFRdq>hwE`Yj^P=$idZE}mGMteN2U z_B0$HhK*M1$5Oju-F?>23GQDHx%%UOQ5f2st=k=7M0KRbhl}Y&Y8~s23wrdjIwa)O zxk~Np2&8ONIxhgU6?d=C&-K1;oBNNg4d#lfA>$0{_Zf zp--MT`yP$JS4|GT7fncdZ4^wm`FZWE6%YA2uR)|HJq~t)f2TfZG@8-R67y}T1GBA* zn- z6U%tKLm&nQcyvbc=sZ0%dals4>Ym5OjCF8lPy`)(I!tzd>-gy^(sa=Z7T#oek1A=F zsy){dT$Mb=ZOZi4m`Kx$gvF&+tHee{_pk>=y-CTYnKb@p;)1pVzxXMlIL*w2@fxkL zFD)$vjv&|i9)1OmXP4WO-8=L?IuLhk@LA~^g&fbC_0(<-HYAH}4mJh^0UgK6tI*mo z_iSHfrcykYKzn*8+KDE88kMq?;5Rv;kj+5_=l;-;1S{8xqU6mjoO-O_3u z8Y7AKgv8EDJW&#=sZr;Lo$P;eR)GDJ*9=PT=~7XpnA-c%jG-$(%~&h&FbV6ud3e97 z^klaFn56#}z$zMr=07{D6##Fb1Kz|UNigsi+`s@7XyD;jxlgyorR%_GUO(iY@158r zP#^p4IFZHaS!eE}8Hh+J_emZ}oo#+Nu=xjzNgK8@+IY|5=ntY;20w(s9W;kIZFOVzH+lbwGW{KgMm@%H<}DP-&q@Ei;|G9&*rSFdpUaH8l`&%# z8}3v@yB$}kvP}LoZdIdOX+IKSTaoFlXX`jTx=!DE*(m7+{l8bT16rzh$1)ukA8tukEs{`N}OL`Qn5#KX1wnZt6hAz;8WxffM(YomUI56WKhu%Z)@%UUv$D z3TzVD5OQ%H1=YT z##7n|I?;FSL*cG1<_o#M*+>b>m$_`*y2q?TQQJTDqpC@Em`>a?ZZttA5y3GlJ^Eei zHHDHVrncCtb1dY(F}+zCYOJ&8_`55(dBL}gldUOw3x2OE56(055E7i|=3}?o2-d_} zo)m=49}j3^_;`{trfM|mooQ4V116T#k%7y()GfS2=(@^}BV=_hW!33Ac!iMm1Z9Sa zaWA^{>mRPQBs>LF9144-5%-_g1;HAOvcAV^NIf*-+5Bsl@Mi@ z&Llo?qM%`GXeg?tk3ItqZ`Ts^T&#e9uWv}LGT~2LEHKfCwM;Blfv;iN*KGu>E4&`> zb-xjAMg69lJM6c0Y!Ywnc@m{k-Oc_)^WcSHBLQ{Q#QlwLJb8c`o3bC4CDja{tD_Ww zc9$E1X^vgHbKaq*XZDfbrf*b!;g72Cf-6n3HVri}dK&8(y|BvXoZ1#&^HyK2D%s+0 zT#dyQ!+6zVd#6eu08!6Kar+clq{fLvEZEmnUnsG9)*PHJ^UA3#s`N))(Q7e$#k0m| z=nK{AvprUjpS4XXaKg3#*+mnlct=gY`zg?m6pMC@fV;eD_zr6O`|=!!bYi3C}DbA&ZH@f=IK1fC(rt(S(!M zHH->A?ttM*%qrjFx;;hoxAyr+{G#f-bhxj1sR-%pFZjMwtp1m3bmVziUiTw3N?cP3S`lxqf7VQ z*{0x^Y<`Br`(FQpG330e7t=Dq9!b#F;72~AN4YoN(?FkKUnoLp|W zUvkl?n~N@I3TcFm+9!C}^2 z?#y6`iN10CgZCXQ4fgs<^1aRXiDO6=gEM5HL0nWR_ihHAlW9Px8+9MOwu!5ck(vg;=7-^!qZn1TIUm~;`=Iu2ohejgHuz!UE)EUTQ`cN1(00@~s0sg4Bp zZIZ(vQvG;YY+@<)es5UK>d_c_Ro_m4QFo6%0i%koSu05hpV4#b_;|SII)Kpe@^HDZ zYJ{qA0xPK_3(@RS$rT{}`mXC;_>q|X;^=UCL5+mNvMxdMH2YUlly->^`{E)Q>m&5d z$S=Qig}m6~Q`|aYaZCMgipl?~jE1##|JKZW+M8$vk{8WntO{shRa#wC-jabK1@VjI zWw7Sj&ytc57dK z5UYH^uiN)7Ql>8ikkjQZF&=rhAMXq89z2~Cd07l7Nc}oVF)$f1%h{t+eaBwI6f{)4 z@*stgpLod=`_vA+4fl>He(Vgdi};$!4Q~-r1<%O^?$Rjb%wO6D|3IX3wP&Sf+G$Gsas@3S6q7 z!Oe;#rc-$4V8O%%*|O7%xYxO>*kRAkhsG+z31J>(^;|@ z^HfpovaopVKaqyCIMFBbhJwekZVS!Y&(@7%U(CK`wwxEYO%|t`ry3nu8nz05Syajg zrJ+-wzj6d0_Xf**mzdB9vzsq1F8JeSn~gxMvY149^gv@mnKQE0OL!!0dgKkS$Il#! zln!|FbO8RP7wp47u~No?>XT`N=dxz~=4T4+Or0zI2a-xByf98^WzF!Qiix*FtL_Uu zW$+{!+|JQH+CQgX;|59_|8}%r3B)!tl;U8P*ZVPzx&+TcY-%ID8m*GXe^t5pZC5&VmW8pg@#$XiQAiD9 zI)H@aV2>24bA%;AM4x^4W#59%tnRE;@1_K>Z4CBTtyV60Da~_(G!$d^FKH+wc?AOf ziF&m~e`kqS>2?9&mnH3PP17XAc-T_LI~+MAZT>%=tmQJ;-QM{zfxff56?Wx;qvI28 zZKL_pzXM{BhpDcUH!df4F9VW*%l3v-VB-eYQ`p^QP_usI$Rz2E+Y-ti?(Up%; zzvQ{_#~t0H{FnkU{6H~Vgxl6wVvWT+;6bSV2`n=$L|&j2mag27u&c2HLGYVsxevmp%yzQ5i7=jh5B=R*msbO#-u<5;&)h|^+VgJT`pTa zxqTRXHD%K57;ET?k6L!%9tie60>N>^pGJPqA8Ar%`Q9d{a&hnQ|BI0lONdu&f~^Gu zeg>*~qihZ*JL;mb=0Ko@!0FT-P*1c~oJMB?8}+4Cr_?N;waLk%edW+sZhhrDBP6o# zcCl%od>$UyGAg#D=R4-(rx54E$+{(d+{!CRC1z{4t|#&~(suELnZ6afi|gAEZX{=K zFgA+!j(Owcq)aMnb_^)i)F3Hb(k|wRMPr}$qOk=gqS=pBeFu4MjXqtb=!TV^w_}=1 zP)DA@n#!&zvS*kZ;|+e4v5Z1Rv&xME?3T+T8WGely|Bz|@{3;sL(4^3He5yD^>v~p zEG%LM!oRa{+*tO&z zz*u_RByA$Rc~$u7AnIR$v0Fsuc3$0V+6IjX=VBhjGusXJiMJ>;RIzYGprO106ma1B zqI>!_^g!Q+S=EYPv=>H3joco&N4FDG1vbSlOtr7Md;No+qx?NEM^ z2MVQZT?`TvERpeXvk=M6n)k(?d>KPeA(=y4L*m1FUk1ks@v-0da~pNc{zz*pKReoE zu@$_$hmd)jhfLuv<&Y6AlLb8SRz%pdhtHMCnPWZtArz3{z3In*k5{Fo+qgAt$%9+_=(#ep0!8Ok|!S)!&5@ zMzF}Rtz%TjYo9h9PYc8~w4SA=XZP}u?9h9AkvRt4$m5>-+Db;53Q5m$IL8tzO{ktlEIJ+F?o)io7GgSm+kYP-+UN^SDCoG z)^+-P7h-Wa{@T7@tJh7I$BAw|HdxZW*konLDe&95_If&9?Z3p;XPCqnDUXYL#CV|S z!)LM-oaDJ0-Je za{vNIOcC?Rf}0hL%h9m1ea^6u23dj}I_paGX#{M{HkVp70T)DK+|(i_eA7ZNwm@*{ z!U1IcONt!uU-IxcefJS9P-V1n+iva}T=y#iXAB!iuUJjUdL6?VWXY)*0`-dKkdQ92 zU`UNHdcW)O#dZ33K-U469{sv&x&D7hQ9t##sfb?S&#hb;nduAz^SV>PN8Po|cy_bO zDWsqWs!e$iBN~t&Cty&VI!(pl4yH)0Z$YMgT3vR>fLegt_HcTU3w{4cS(&?aTG#SP zHp*CH6CcvLMiwEn(jV(upNW) zw0|slv!tx*Dg4?)biZA`er1s);!4S^KYy;-RDE*j?Uln+_er%2Liig3`c+#sRDz8o zxVOyV){s%T=C`?gfzXF&D`s@oTV@JAJ%n_|bkWM0(%Jf@nT-%^s?#SP8LnbkG+iib z+|l_P9QFLk0lTm2tN#I+&_e-Ttmzxd-hB65Oh;cgkfrPt`%!qt4KiV&>-$>1+3XA=fADlc#wl}*Iv}nr#e_eZNw8TPorGs>oB>r#a z&jghAHox$YO30*R3>GjgKlNx!=I}6V{*g1)G=-dsJGp*jJ1GN4a?ba1DsL-zv(!K3 zaB4LbgquOS<%nt^_V6aDM9xf!xjCd* zSiJUp3;mUq8vN$DiJEM7xaJW>IM-y5LoA05Z8i?;vTGxN|C@j%B(4w;EXlnz)G*e| z%781|DxldILEq?72sn^(R=+;-sB2kc$zKjM0|;j(|4^}(um9;c$xM%&_`{jfED1Ue@tyxLdA zhY8Cg)$;mW)|JK%7oVJQS%c`Zsh~4c4+cM<{UxRFo-4UFJ58f0FWdmqFoWT5(s-uw z_yK&q6!i(nAw&(AyReHnJ`@;_FBy)gYQZ4(6+i0UJ|1YCD-7s@kYERdG_$+PVh ze1CobllC?8PNqRli+NZqkF2^-^a-(?>GXQdD;`i zAtzeY9E$cdFgP|@09_Jj^G1;f2!HwXd=N8vm+ecK=hOAsOTVT}>JQ{hB=G##zih7mRiSid=2vx+4UT{OSna3w$p{Rd z5E9glXul`wdRU+WHc!pYloG&di9fzD9a=6~6?~$|YI_i{>_hsF2mm;^ zC7qA(_s!0E#yAfuRXR6i7-g25JKHJ!44JQ4B5tCh*?^*8is|?cT9S Yl5!PK=UfJVp+zElPf;fCu7S^g0J1vZ!TKZH(W+r~uhDxKxzW(IzOu4HPDD+D`x#3>mhk7JZ;RU6 z>$wucchz5?e+>_Z!O8xabWfS^p%y0^NkMW>CQG>EO~?otmH9hBf=lr^faYNObeH^F z0QSG*4$kU+8Tc7MX&3f1N(ryE*Mrh)2SM%rm0Tl z_a+uUQ=DR-9kP&j8fUv#tl89a$SDnOS) zYt;5rdu-VICb|Z6MHAd+P?&igg(e2sp%X2<`se(T;&sz)R<(buEu6j~OAz(2@S{Jf zjVkU*NVfE!?&NK1A*1xgiY=u$DhTC{cnjAi4?bayi7S-tdH?l+`&VeZRZM`+aE7jK zT{&O=^-nDtn}qCSIyu3@{`8!h$(@dNT8JY;|AV89`s$K~AA}}f+vK_SlQ`>W8h*$l zIwNp9kp~(!d2kHF$MSsA(`RJ9i}l1oFwiPkgfNyVND1K<}= zD&3Ki@~j*@s#K@`rvL}RlAJC(otf{t^CyShYwa8U(e5p??2)mY32I4;{LhX~`NN(KHuYUYG)n~oNxkuc|<-|~|1$xK-4%ivGuK6`W zc5t52AEBfvsVD=^Y0y4#rA#P%{PdP8qMvN(8!=2L&CA3W~);4pV;RwSzeBU3t{_)-yKT;j}E_(N+T4wpdG(T3Lea z8$p`Kp{nx(FB($E*3@7xnzKkE@Key76T+6?+()-WGdxt%VJHi;4si^Aa$`BABl6+= zvvL?Ka&Lm}<&(0}<;XB=VBlLS z%=8`MDD^|?dsSO>D~2OAgAE7CED#(0)PmLvx}{%2rt5_l{DYr{d;-HdwvSLj1yYdP zY2QLPyxdTlT@V`KCQ+VyStf$|x~7$MPx*@W-`d2y+Gn-z;R@L|$z)HTKc;XehoT#a z>KgQH9EddgJG$&Xa^^dUAl-6KQW7p5Z*Pr5Ln%^F?T>4WjW#`1B9y&P-{|X*H(5xQ z$%wX0SS2gQAdM?Gtt5I=-86e1%x723Ey yVbP60QIlo&?SzUjc-sPiQCAaYPh7* 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 literal 0 HcmV?d00001 diff --git a/manuals/user-guide/src/main/resources/images/sfc/sf-selection-arch.png b/manuals/user-guide/src/main/resources/images/sfc/sf-selection-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..168d979363c00724246d9b7a63294e3e0efe1e17 GIT binary patch literal 36004 zcmeFZcT|&Iw=W8a3MfrbR6v^aW}!$8ML>E7sZmjouJj%e=>jU!yGZZ7Cn6wCI-x@l zseuq$AcPR^gTB7|`}TOxK6{@(?ilxs>lhA3o@cFQAI ziw7pIL_}0=r~ipNo%5d(5xtdAy)SRzWr=Dr`S{e>d!^Unc$oU21Z_Vp+!F5_=y=6{ z?b$<=SmFg}Vld@ZE4iSks5}qx>a9xOB(YiZBNE4Ru2HQQbe_d=-DG=HPD*B|%2{wO zj;~6s@IyrMih-fEk+l(3oc{f99}id#4N;Qr{o!GB+*_Aph)8H&5s|VI1%9RRvUqH&rpQJ_{O73{4dfm%@b32m9vb3yaNt`_{r_mO zK+W>2^REVH*}7#$dyB8*$E;QYkJ#t&Jy3w5|eq6=YvO)lwr71Cz(N2A*^$vYRs|*(-xCaPGdQBik=CYtLA&!Pqfx z8@~|FI?N&+6^`!(K6BLKvmrlBX`a&^0)KDNtkMO}G{lRFh2fXlhO60Mk|3pB`Qxk?wQXdd+$Y>5tb+4d$f{Z8PSpIm z*cHj{k+c$mu^eM(10RrzNewJl3NKKfJrnpD(3B3}@98Vxm6EYXHkVxbDTul9iXTS! zSidJa=8rVW?l)n3g;hk#vvQrjxac~1HAyOB6_;mBX_USZQL3V)akXak+#L9baI1C3ix`N_e7$KfX&YVG|6zG7?adse15= z5T{h6yHZT^AAO8MB#=o;fKCKVqa=Z*3&P9o8JExK4-jY{xgc50{&hea2u+yktL_5G z89E8YSA<|{xl9Nt4dgaAfsphjwMyYtH!pwur*xB>awk2X;Q6jbfDnK6;pJ~*!hB~3 z^m?U4Iju^8Xq&-xVIU%~z~+SPmINk7@LvZE1Ch1g1ZD{f3{Pc~JNbH^br3`n21}%a zoMo3oUqR7I0^z__P z`FDkOq++X{JVH)_NHnyLt`d_ z_q>z2y~Apcyy6GPuhdk1`77y3mg-{Dr7qbJ_u$BOn$-w7*$%|dP@6J=5@RG~6u8ld zA48{Klo7CDeqV&4G~R8TuI#(A2Ew;;Ksvzk?mPHcsY}hvm!IQHX0frwT+;=@_s;9Hy!W>fk=Cxe z8YL!}3@+dcykYg)R<;&Z|Dq7=x3o5n>$#sD==p+-AXF0Xa8?9YK#v)FT7}}PbHJ39 zCdcozyEvd9W<5UXa2?;vD%y{;U(cdiTjxrKiR{J~j(0L0yLe~eQL}WY6ldbsItf(D zbQ^T;!yh>`A7gg72qJB~{q)F$>)D>^i3d~jgkya*UgO|YU_w}~)(oSBk^4lYvbf-8zh6D{q=)#p z>0bACxwWe;>o?VoKoC|H-hRqPyvD|oHy&SmdJ^H(vzIs81*$vzGGd)su0`A2ynucm zGy)9^QD>P-`9wN&ky<8psqz5y^-d& zY9=#FrH=RJcv`qy^8wc%V)`+&?7s63h$=O{kTsQj;HKs-A^|$ z$Q!I$FwU@*-Fi*}F9%f_Y|C=idb3wb+Nal~i#F5~8d$*9)F;S_s-u1(yKOd+=x8is zd4nq_!QsoWzRRlJ8rEFDk0&{fd^=B#FLm&xHFC^?Jp#nR+cEgF@$P~!<-)*QAyKqN z{o0u8PBPSrVg23!W#acoPbVL#$>S*}yg$*~v~{R6Buw4hoZuB`t>}*9;lvGBCw&gX zcg#;B;h^e))QBbb}Fv>_*NIrW@AUJIpUVsuX$)G^mNyBB_AGg zmz@VS`>UjNjJZ;}-yd)m?j2=E3-L!$-??8DSQM2Nl#@^HR2(b#x=m}rUy$yYf7^&! zrY+Vu*(_)(17j;p5ZK^GL?2X#V;SF4FRI}u-wtzqF1A%97m-t;g|zxpLtC80WN|`K zwaHFt+k3_xEiKa}3UyL%B4Ey&jSd!F>l9g7&tCHxhn^of|0LliWm znX64wAck&d3|#B*k>A?cL^vAqFa1mlcx}(H(4s(izt3hk(GU^x+k9eo>p8qV|1T}85MPuWyR(`a%ss3 zS<-^73cVfP<)x{J@Ax@}vN)uLXbsfJ&+iuQ`w|>VE2DyvGm1g?p793fwVK{d>Q^_V z9^xugPsvijTr0y?UDJAh$v=OVI%}4f=RN#Y-$cOW^`vF&{cm2$DKdW-gY=0+6;TP^lcO=8(z zu}=8ho*~>X-qg&i@6>$Kp{z(bIkzA(g;aFj=xNmHq-!eCI`VPKliwU8$g|-9Ha+K@ya^dl83SdERbdQ*&NuEmzdqtaRQ(2;(HypC7 ziqUzY4OMPYu6&wbCdUmg=QmKF#x+~rD~ZF7tXsP^HNrfX4n<0dvc@~8C?SbGRXq&Pf-1UY5=~qklRl@DX`(9kQv(VbTn#3f< z4n()v!2oZPvtYN`rxduui#l$xvmE|T^cHw;?r||_{#JM`|KZpUQ%>~4K$^g|GR^s) zxRzhL<<0v~&rs9$(X{3s)uOC*A6fV~71Mg^ZqYYZuo-lcM(RA;=vsPKS0ggft6={u z#zqTo!s(xKw&SxEwIl2++-`DQefnzS4Z925C8g2&*8JNx8KLRzb!ov|6dczZ;gw}t z{&u?TbC#t}zUII_sf+3{@(K3Be0%~$!XYRrr6TCEW0NDvzNL@|;MU*9E~?-gUN-k> ziB9jX7=4@)KEf$KPI)vFn&pfB9*3Dhza4*Rw;cguaL`Yva$JKt(m5_)4Cgk^Cr$Fb zo!D3^PH|NU-@rivrBN8^8$kBWB;{=!Jo+lE9nZH28gC7Du#uiE@b;o24@y`*q2O z5ox0pYEz7vxY_f-lHn-XC=XAby1rCRNHLrCq?pDG1r(`DZ|Aw6S=z9OTabZN$lNqu z7?|ro*cAn$m=Zp_#FVr|!lGl=nDgRww)3cKl)4xE=7g!k5>u86P_Om}xo#tqnUwHr zmh00~PbR)q2&89yuPN(Fd%3@axV^KoGyYB9EKk2EJ5@ajwM{;k2pFx=8Ks(*k9DG* zM(;t#@Ony1yh*!-^K;yXm8QM<|g7_s*tMpE|cjfT8a z{rLV#$*AfNjj*G1Lciw+l;Btc63lqM3e{y(48Ej=SS2yUui_#sN_N0MS zFbe>4+8@J;&0M{HFy`Vc&}NhH=M553+N0^(;P>9kg^LP3vP# zRGN{K_S&|QMbGj+m$G-4xT{19@z7{LAi1DaCAmM?&H=fyJ2-mPdAmAJz#bDo37F1n zPFl*@<%i+rX6eVWDRFUx%P;G@-0q;RVYFmWQo&5q@#zX@%~hy!x0-KXK-}C+W2J#G zd)KPH{(UoHUTJz##OXf@}JnurE^G42~+H&-uGA(3tD-%EM9~VZUSKjAa zT=sMHNeDUS5&u_4a@S;yRKs zhKj@&OmTI>V`fynk3WrANajxuDNT3X@x^@THR}5qE~vILrpSJM$~dApGm5h|bb`5_ zN>jx z_{gkRj>g8ivgl7QhTDK;$nY62Xwy&mg%+fK^F)rxWG3EsrS8;i&**Vk`GNBAb(7yK%l2{+k8iceyOE#1v9NhIEa(VNf*BHge^*}^pa1x?!knhE|ni? zM}}kq`t8RWp`L@0I$B7N*q%nB_FLuK)ny+CXIoHtTXVkP5a9TZ($uEP5?YkXL+IiQ zBx-#aecbn$T28VIMg7V`S#-BQG(O2O~>>(0ULV7kdz^rFGomF?)E>emuD^CRV)#JAM z<?4=04MPKOL(J@=)I6QRv_a+``&r#@BcW+SN+)_)1A6Y*nUK!e@l#bm`n9j9U+BopjjyV#eU4K&e;m!dRFI{aE-%wYGl-EF&f+QwQ-qc(Y7@Kyam`x3L-XLsM1tU1bLE_8U(t|H%V`8Sl1 zR3&m*D;0ne79ModkVFG8gUxT4;r~Yk{*O?BKgz~9KVr8b1CTUg07?4=zaT)d?*Qxs zSceY1f5(9S^m+CyG5g!2&=>gbL1o8IXGWd|=`!_91@j{as+Ou|%Xe zm0$1+IzzP!z)liVE1&TGI|lTpPvxEO{|RORu%6T28zBVrO=Jr^2fi4JYv&i5m?Bk(OzX%3hQS8Koc?L43r$2z4U6r_evlEBPkv(%AMz9RiZb3 zQM^J2>Q&?BWR046OIW&26L|M-4&6wO^JaQ|8y)iKTWNQOR%v>=P+A9#B1d`dW~SCl z3p||hb_dI`{qrl$lfi4x))->g8}Vk=>`uwYZTr=_0rQ@aakYD$iBzH znRCkwM@2{FM>U`1gJu;@t~Y{*dPAIEzoQt0xk#3e%<2uzn(mdQENHXI^=ZRRt=wB` z%T3cPO1}$~3<#`&OXX=2&5KjP4?!YTgd7WfPp1~|t^-#o?tSgJf&MaW0i)cCju&Lb zMN;|t#iir?6fvD)M~>$v*1(D^8mrF~#pNHKT?Gdv{+XBx8eA6v>x)CEm1L!hLi*<0L$2gqH_a%7ix*~ZQw2XE6t^S#x)5MlnFiNf7pDe~5zCi&xk!SfLee9zzswF8KNuT^ zog2wgP|r%BqzyRwv<5B^)!c{}nthV3j{i1DSYm+G-pk>QuzyGDM&*_>R$p(5kT5%r zwBc%5K$kMpX=@q}l#C`6MiuUz&%MSTcq0c9)q#+2yz)$fWUsPX>ddiySdiJU60ij0 zvrZ^5+d|oT!owGe1ElnZrUhdCWuu46b%z=t{QcFyHAHgfAOqT{>i!6YforvDGXjADq>5OpgNc zD!z;NL8`&m^6!_D5B9n^T3$~O0>091l0%2_fBo{zc7m4gp!TpWgIydqFkNYr*xJvj zM6-fR=h$}uQHQkk9-rfTZx6gOPf7Te6A8Ss*k|4Of3=r_@9Me_CZ}bbFY0b@4R;=& zC#reDw|keGn?EmMJu*%?r_|X?ec?!0|3M(1d}ape>a*j|>T@*p!GN^KRPu|?U1Ei! z*H8Ss_J)+&nhEA${w(B_S7fvhzLX@Djy~ zF6(Tp25n}-vmSE;v1!s(r=)V01?Mj74{wifRSBC+63dtU90N|O(5a?|L@&B(a=pl& zh7+|2sE>Ury~Zu)+53i=7SbjXd*8eU`qHBoU*Xuv5dmX?`nb2u4MwfP9-Bs2Rw)9@ z&1|MS@|`ZT=~>5{FyN`0*|AYk)S=qX-hpP1l?OJ*2YCny(FP;40@1N`#{YFcyPB~? zUh)3YQO~z!_|38Y1@yGlUG9W+6LLt8zZD|nGp=6+pw~Dt0Cj7`+hj+2R#OuE{f%`G(RGJz5w4jAhMXs2pHB(;)jsW8K+AnR(YMB5Ms+KI1jDX@!ir}8tGJLkuJv( zRD`M}_qTueYPFy{;l>=agCq4 z9?HOAcb@PRCY?VW>>=&xU~6VFZc|oAZkWitUKWXZT<%H&0y7w#i9JF&aznP0at>lj z0`~78Zg=;DFEvt;t$#VcA`@aO-P2D->|>&QQAu=H?$u`eW&YFI73h`RHnd}UnD5wB zPXJq5_)gEoje{f(birHBi&(Q8E%>q7UKUU_PJ3nS;JcA<2^>?)Acm(Larv0W45({k zA|ly39Z(lP*L~oro=;m9wBlgY<+z*Qka-!4s(^#NJPy;S=Pu#(C(x7w0xh0yOJy-} zZammkJx8ZwoG&57#Jwj(?w@9AJ2Gcla@(XZriOyhP>%Rf6 zPLR|^8*mi9bR%E(Xn=E}^9sQ6@~IYzDwh#Qq5K^YKT7E*S zoC6-=DXGC9Nb#Q3(XeCaE_&7jr^vxA+jw?6bU#>58*r71*JgOC69L~=P~oeOk1N7x z9(&3Vc|~GJR@UK?z@X>sWw{+C_FGH15v~JkbqL6&Aho&9ceL>)=w#EkpNIXygfowF z)?g~&D3`uxig5S+8ca(cFPLDz4qr|po{sa<$FI>9eAPRfmqR+qd#_)uV4oTqsOi6M`s3#c7swrM?%Dkf=3Q~^mil|J~f4!$RvE#deifAe_+ z?9gMOtU`WKm|4<);*J~5<^#q*{QIhSU@kVrtU!bVBHoYpiTA&JsEB9t`NP-0k_#Y9 z#7>*1f6pHzi4`I?pN5}n0IK;kBRs{BXtq~&fb2P0uYnYhY>B5$$jf@ZKKfq zL-1#+{H8De4F6X-!0gW;k~+n|stDel`NuYCL7|tE|CANT#r&pQ|5P66umapH$+f1= z^Jkqx|B{mR{6DslI#10nLj0#-;Rg9HdiZbo8Fs-wU_52qAcojudE?7M&s2Kh)B)=>!7~=M&yNY z*N4Ifpwy!SZQFf}Wsco(`zSJF1~P1R_~=fPl4M)TMn!^6X{o_p7U8pBe}Az*uEJGq zYjE{4m=}7ox0KyvaDM4g_g?Q(@J^kl_Fm8mH;b&}<=XYHaJ}ceMZ@|j$Srs@w&l}6-bfD4e?U_YdFA6=+w z2u&BqZ+r4*W#y#h>mB36!2I@#8P!ZVcO%3!b6Sfv)ZIA=Hze+%QZy}U!IWfWbLX4V zxR>KjX4DKN=dGrreS?F=U5!J-gDcAhc_?y=e3CQCdlE<@U^<;<4~snZG=yc6Fg-OG z9guSlre#0bqI9Aqfh5=X&f(MN{dz?w^}8Q>Rosm#1Ma;rE>(I$_B0BxXlgphSn8`p z@D8bii@SbiZa4ZyV*JiXD0f*gE_XugZq5RW*jZVKi+s}Rw}E5qr%#^pXR|>yw6{5Y zxdk)2JKUEZUB(u5_HRlx_uO0U?LXJd-J&1%o_L_p5P z!R6VbpO5aZSuZ$u4oR?FgWr8ZHDvY%d)G)Pf9#ya{eh2Hs+h@UEz2w|<2&FSdjg-q z^xT^~gpYE%uC7;Q=uLdsA+sO2Wk|(N&51p{0P^_!Kmh=Z8S-5AK(%;fiW{U+PEBkjLE}v4=Vc zp7+ncBSKBhC)->GcHVfSuexG<{2pmH3dNj_ZoYU7( zyYso9(<5?+gY--Jmr?Fj7r0MQF+$Zl`O)dNk70w$o^A%54=u`gXNthkhV@F}#1+H* z*3KK*$T4qPi0<>)b0oxoBhsSd(>fD)l~iFxE7Dn_FUvtntK!4;+K0uQ4bg1z!1N7* zJsTPfBNYx9ke2AjWOP?N6vljQeKQJjycPzYmR?`KX{^)wVBlJmk&;={o^gqjuYQPA z^jg9rP{^jP|Y~km`kNLlh*wyYUm;0Sb?S4PslPsKcmQ1wDjw5rL!kT@c ziN9AQLTGJhKz7L7Uq8S5^Q$^rS_Vf!{-W@+u{Y&Vpdg8dBymS@n`D)s7AfAe54W~$ z+>JW+GNyh$H_bY(EaNTFmL8q)%Vmy_4DHkt0oFTb{*jn>bL23 zkUS`iy1FpX;a=|wIe>9v#jYd&;a~mI^R1Ott2ruGiixWa*LmH8Ms{7;OQtCfsL%c3?FYY zEJbd}RI>%)+AHWF-)4Nfx0|`-@Jr5HpOwy>R&V`UM8NixM*UhEe=a18x4hO%E^(|p zuoYGxv&0``yWsm)5q;UMecrwU0!Y`ii#5}VhG{u#x_DmKX@YYWGg$r`-`>>%Reo*? zO@30wX?P%Yk*W^v~0!Y>F5T&~%rt7g}w!0rYicr6Tt*vFzFGu4hMG8B(OT9&FpZ2aRYH z$^joQK&QMfAilbN>;mUw*Ex4qq+7QnnJ0(tYP$2j9f!Z+(?qBpUX!%B-wrl@q z2ymXbTic$tXFR%=-pQ@bT=SDs?&K94O)yp3F%1XRtq9a-45UDc5H+VoD=d9JOXfHzUsTd^*6jtylsEc3(u5a5p~!-7ypz4($fbY%X_pDDd*-jmYm7gaCdZ0 z=4nZL#u_=Vx?tM6rPQ6`BK~de-APqT-ya#YuFldGo(%j^S8!2@YD3#k%Sv5_G&!rP zrqzBzxk~^R(ATjp^@<~^x~$7h8dda@*GE3v^s!0`Wj2cQ#Z*zYO=AMh8fmGM_{nG} z?gmx2y(qVv>75JbER4f786+{`*!9Pj13!L>hl;{jOzER-IE-HcAM4R1L7UY z54SBh;e4&*YbKS0S1ph9TRfIo_golJ+0EId2w?4L&h>B;sC} zn#MZ@K1ITkmejVCf-KGQ!{(1jf@tqdPpwwfch@_0fO+U*Ka^Nvo}m3NT3Wtk?#S3G zTpb)2;+AFKzn`_9qt9bD!FwoCUFaN?Re4b21+HCD&mM1B^Dr}j=Oji!lN28-Iakit>0>R0 z9EV$5X4*Gv_I*GXHLny`F{8->Hs_qMGu>y=VAQmLIbHRv=H>m_(u-&L=-)$cwE2g2 z{$Omns`>b+{t)V{*uZO+^U-NH0HM5fv1Tvh^}|g;pBy`j$nq;!cP%3h*HR1&N-N`Z z_cFc>9#FFE@)Kg4)zC+S&vK^Y@(3gN9vcqhMm~;KJ~xjp<7-GEmTyK>8}`A^I8Q`k z^g?=!G9GFSc}`j>7Mb!^bR%Z-lCRVW-y;`8B;;MTu&f5Y zVfRu9-=8XE7e%6NfF1Zdf%&V>*mbu{LGe#A5~lf&ZLC1-FF5|h`3=7v?B4~?BtTGg zxoe`q`)L;2pTwsfuo%Dz|K~OpEVT8se{zADf6fJFq$>w${>c1E`-Fn9y(!PGkpr12P)p0w#ze}h<3&=Jw9)i(wsvV1#qs^hskA$4tjSnL zsTVIk{wiVjzPYuqIsuY?xk^P2Wn4fPX*chDB~%=HI|w+w2J|#|^Tqu9j9QLC!T5E? z{oTg(6Iex-wjJi1X-+9U-G!w{WAzp5vHreQu+ZrWdb7T;&UJgzxYsvJ=jo;3kC+fW z9O;ISjO0|kbwB-j7bQ79CruZvPn(U{BCs*!lt~#3U9$6kSt9B0cs%Uq?N=%tP}2^S zvdaOv?0-q7WIv@cRiisKWD)WQ9er_}D*&Z(6LoXT={ZPyQJd|HvQ@UJJ-~ecwdhs7 zaY;FtB+ldBUnB35axw6)FpN?66+>*tN7KxlZ|oe;^oJkoFIDZX(?!PFhDe>x=a7x{ za-EO_w{BgdW!ZCY@%oKvdPoXCEY4K%Lfa`v^4F}(%?ta=;NKDov+u^iyaRfgHjY3Z zTBxMbRB)lCMUi0K&fvokr_&LYGWN*WAuO;e)cW?cxfb7%7$+x-hP}9<5Hsgc;<9lzhfX7cF}W78P{C$ z>FyX|xXjjrarM`T7}yN?^z8DHClc+zHZQCX;)V2<*wW&)SoK2#)|) zaIP&$54eV*0eF{ZUo{LakjRdJu8WDrTQ!Hr15j5xL*g$4`sxWbx%|kKZf}yKdh;y3VXCa@x6Nq7w2NtP}s(zdE5zHZ6ON81HG08a;wQm zXeI`YKuYN4{~jgrK$iXF1s7m>r`I43t9S(gUzNO2W?=u{;UXdc&SC53FSDhAG>Gs= zy_OpyPsEOpY^q)*WBdZq{sSyU*pVqt-BFy^fum|^vay(2u=RX7Q<1ddvp5G(g0nXqA=c8dsGWvv9mOG!EF@v@-s1dkux)5Y> z9+{F34j5Ntc)ftGt4qUo*u>9)YH^cvOP$>O-0|y@ti@+o9I*VQ2ZJtTi^+hsk1yxE zq~W6vPQ#M^V#Y(4VZQGA^#o8DPaFBCISL=e#^0?;gKXhdopGh z)vf1WY`8TLd`wm5|8oYnIf=A?a~!cLTFpXocnYw>qHNhnBQ!Gow_?h{@BM>n6*J3$ zMGh8~p$wH{Bdew+SRha;6J<0|IS#Ppm1A%85|RB{{NIvz%bRMf2hwd-W-@sOGgP4eB zpz`w^$ST{A#N`d7dXMXuwQP5HgS}jK9JMWQ$2R=|KN_qMlfJ733{;y_;#({okiTi^D6sKT_Mg)NF~UW{|AsA~rVa#- zeziecgas@v^f%e^$+3oioKz`WqJ*kbwy(QGYan@(3jPkEqOI z`PQlWe?^A#fQ$ZzpjaCBrvcGFMtsXAr^oB>DD|I^da(h?KdQA))7xmCrMfKF$4eydqivijsgc^Y@e}?h|brvs&#IpZWXIuWankg#O|r zQfz>8`Y$E?vkKP#y#Awt373u4MKvoc#qq@j9I7O61LWEF!J@(A?xf8P5ZGP>!^V>bu|0^xzyIH|uF>x&|INyyLBaOI#Z6YX}u8tx&3`dM-3f&{&h2C)KAo$p3F(p?W*H~r6&jWNo37;@C zp8Fu`6D^Oy<&1P=MZM&U z5&0Gl0~wx^67f<02Q#I&!JLjYZ#R9J zV|b@{j)aF^{}q-0vSPE2jF#aJMyuE_E<>4sw#0YDJ$~TqNi@?|aSQrCp+oxe0t^K^ zYBaH*p>#K{eBNu>5|-ayiNc#yqk(H7c{&#SpTa<>oTkd^O|v$4V%@rpbxNArfw7CU zIMZupcE}VtlKF8{_Se5Gyc~&yHQV|v~VUp@k4 zAb-!olswb|l#9nb+2;0qq>%A^sXFfAOLy0ydpU3OwInwWUD1(Fm^%v2CME0;50B3+ z--c~J9KzSvt4zBwH=4=%jCvkkLta!V&+#a4Q(e*79$!YiZ8SzhqsiVq{nt(W3R{(< zXe+ElEZCU)lj?Rm_yzf$1)c&IO}@zwMZMex3aT02<3h0!_{k@A_w(SB3W+#7x)!p* zny{vr^7 zPyy!?9f*{bh6Zx|tH2Xazrq5qW+~Js6~fHp;lWjdBi-Ts-L=Xn`;vZ-Rqg#?mbtoZ zPIkhKWN~DMZJ?oqlv2*8GzE9ZiW&p7kleAVuC{+Z#@snpuzJ$Y9X`e1U|aXbdY$I5 zUn)gspJKsCiUH*iif*|znbh*I8OU%?(V$ zj{3z>n$@l~jm?+}?G1I*hF6)YIA@FRz#D>oD@e+E{W7GA|FUTN!fV|4m?I~RKbx|1 zEiU%#Geb(x=!Z3THYCY5HXS($8++9U9@m@@lS*hiDN`CiU#INtFMV+lW-6%7@a}D3 z{_T~IpAHzv-w%MiD~<;zk&A))QTwl3<_j!)#jX-vC{Zm!Pdo0;LVeCh)cx3xmq$EX zubMm8SaxF{sc<3NN4RN7i7<1GAwikEnXP5e!OT%{bo!`S)R~ju*5oTyUFPJSih9!d z0D##JfpFv30aMFVRUXgW`y%0N{)~EDi~2iD!5kS!CZuw&*4viWaYvm7$rUi+X`*|k#_xy|jIJwD>*AO?EB&x&`)UierqI9$e@@G`p z4g01BXW)*Vs1Zi$T(27~s^$5f>$B!6s{dF^sx+(4%#623jZ`3z(9*24AHF>3;GXR= zX6)lN#QS=+tyHb>PHPZ+(*w=$CLgsw1p?w|Rv56g-oE@hrpf$WkRTSb^Y^3wYr>qr z!n(ieME<`S=~qd^4#k$dFyq$v^%Qv2emgC85x0EoOnKrsa0EmrRVX9xY(X*$=o1q-wpS$uzAaazg{>=&%IBRBtDW3An7Ev1Qj^J+tb96rh-7L;Z#BV!@i`|vcvWpySU zySZ``SsDq$VFrOZ3<@e+*dg<*(Tg2S!$DdV4-C+^eym z^Yp339Ut$~32T?8C7Vcr%!YZAg5rlsPlMob^6&o!O%7B#>*F0A4D6$TSm>*ryGO&F zs%qJ)&ya@GnEPq^m&GSb_^-IEB#baBxzTmKPZ63iEl~j}^z#Vte^PO$@5L`+jY-Ei z0bz~C*Ds?`7d8*8`XD&{oUxfhZt{A)^u%gq zG<~h-Fb4^*nbPB>j(WBV07$I!WDojPM^&d(=NqhU)Cn9-<>`f}=@dB|tW*9SimKyq!Pk`4JW}#nLyZC>rT5H=h|CiALr9BmVayWmu6^*yCuRKQ{+JiTX5d_ z!?UNkQ9s%94YLx_Z^r8b{YEDXNvdVoCi~9z{Waua9L}XC>wtB}Po)1EN%Co4F@G-b zT^GxXQ*|u9ebtUot6>YSv&zL4m~|kyJvC&#b9_7+pl`6fNpM>rkr{jq2&V_ z5~KnU|NlsWLbB28QEDv}4-3}qrS~+QS`(yCUR1i+HPn_{mW_(tPqH=_TsZfV2hmWgy?R{`Xdvt>eoFC;0gS!wz!dU&eXr&<|?_1%u>% zkUwZQWMs6l>1CPrkp6`AU4R#@V?vznpIn~vCn5@*0pj4Lv1*ZvBxku`HEf zZT$|{#y6SPicbh5L3!NccKkKpeEiQG8^1WoI;82k4ag83r9Q%{^PEJok!?v_-zn9k z0DTpF*y6}7dF})%D(33a5RfzTuoU_Bf&R(%sZsqaR4C^5L~*F;5RXeFFDxNS$5po{`e9{qdS^Zx{Dj6+Z(TzCA1OZ|`!Y=ImY3RL!l!9MxYphEv5 zd@QEU1%AC${tPkc^0TW3$C1FFA!~$-I_7r{Kq4I__i3dMZ@b`)fx_4t|6WgKlcxU~ zYLo*?)Jul%HR&M&a&R3ZOEFC5{v*4+XrEOD9sKcrZLIT51D;R;A4unsku{O1Fdrv= z%#3~127cKR8n4JY4y09ac692Oy? zPXho;`DGv%ah73=l3)YM^<&V0;c6`wLt| z0pMcLDY$rOMZGCg?T=`k6^?G%V*d>;;%O#8lDHjy6?*ut@;-3$2B+9EHvxlG!^K&* zB~H(7flKv{y%jNUnT|?Ixaa)QNp*9O9~f#2!X#Sj_&bL_=wNFJ>@&YmHtV~5#!NfF zYq9>rvkLdoYo`v~oB`aub z2T((rzNf^%^K&Oa`Sko)EV^N3ZyF6ch(9mHvwXmRkOn!Bv7x8Exe*!)_&14Dv`;-} z%13hnjkEj$+?#UIDJ(Z&+erYywIhM)auHu3*ajcS9Ha+~``aMA(UV}<%HCgf$S#to zABVrTwqUUl=hn?#{Cki;5KW)5=Q|qn|6Y8oP8RTdJv^p-I;QXR1aKl3=|D7x!{$#9 z_BG$ZaKNGArH=ubC#jIA8NFNeKzCgCCo?1W9CJWYI2fGb$qDY%1NB}9?U-2aN zA1QIM7}-A!{x1Lu16w0t%uOCKJF(0pmE)*Oot|~;+!G>F`wnCDDb~G~x^|J8**ZN& z$vk3?RQ;;vZ+`^uMFob#G>O^T2Tt17>nj!H_8VpE-ylH_$?`Vea!uC!ht|V2v#Wa4 zdZ@%S6?PlW`z|jPdj-SqvLUVlNV5z5c7h;vQ%AR0A47e)?SA@GCn}~1k)SCVw~MX0 zNsOjaM)k3pvEhfa{mrSZ@~l9we60PIv7t59cQ;7t?wLH;(q5oWvDP?wJhHb}_Sx>W zW-NPBx}W5vi2Qcv)%2>{(x03!D&uDdDZ^lU7lm}~7OuS_A-vJNi|z8V7hy=Tb{KSq z+pOj3Dpxt=*xHQTANMnP-y3h`cD1c(E2=dN#&}r)|EzZ)`OM&h|EIk(52t#2|Ng0@ zC=tn&AwtLyGR8JkGG{JA5oIp(wC#{gA#;eGIpa3Vu=h@e44LO~BQu-KHrw_rs`ESN z{LXVd*YCQXf1c<1`g30&pU+zNy4U@=KlfVi*Yf{*+B!(J_%;iyG#!4iJ0tM@7FZB% zb4%ISK8?CA00f_xI9t*ppw5>T457N%!q9u0_Q8{pClB8DYEl>`KX@igA(gfh%nMFcvJV(WN2{is12hjV04!T zsMe0IhsPWX@MiOE^SwuVf1B>U?11B=kEe9+$x+>$qQ^^7a%R&V{1@oWpk>|41 zVLsn`n*ZUIClIsM;5;6+HKz#*^!#~`FBvD~r3!o~=W(D=-?*6cM`ZKohFx#! zSE{F8yFWVlxZ69K>Aq|L+B>=Jp)3iGI2^sqt})}u?(7$*4P=DakOAQ%>7q3~gQ2CJ z$}=C%HHE3LMrKxo$8i=eR7G0FpD zPxeH!37%KTCDO|5jW4~LOp?^d91dZH1ynDSuv{P&&3f)rwP!2n$e9d3H%b(!2i{&{ zT_aE4y|tsjwT$0~2ymKf(jD6Q?`n(d?1w{%6u(UH+$id>f6o zBd$82D677xa2Ix_Z{4wu*YB>&rxgha;VTv85U!yD_EDH35AT;c#u44qMpnr4TGjL~ z{jW2&cC0{Ozl>p7>qlN`M%q;n10+p*-@t{0nJ^iGepCmM`k`IIA-9aSi6}_@612sz z!%$JW%E%6Ne_NkA9ta-p1ssTektg2_h0+JO2c5dYePd4Uzf`9NSy;MfSf9_$#>y4r;YMXN>CWQuOoX45a%`q}2cJF`I6S?gTp-&6fpaCo%?l!o7^qYk|pnAogM&qVK? zBD+Xs&scz}mR0=k5o!3xz()*KTz0N6u=s2LcY;IswndLjT^W0;Vw<;Lh9eq3NS|QR zjX&RL9Q^m0E|>f~k~9-qwZb9qLb*HNq59VKBn2#xtyT5)(L_HRx_QFEgd_SW0{n8V zp8@Uf&iqcBSfmd`n_t89Gd{`T$<8{>kSZN|Gcd8>EKecNw=~MbAW@fbBt!l=BBmhV z{dM3Ku_F{!CIdjh{%8LIW9v@r9>bBTN0n1X_F}A9B9#c%A*zKIgws=q+hD+Pfq355 zOY!2{w+Lq$Q*VRzgVnhH_&?+>-)UFD@eT-269;KXS<|1;Z?;oB44s8bEk*o4gA^D1 zvWYf%Lc`0LHG=|+X0i*Z?g0>HVOE%i-c*^RCcdBQXk_Z=n&^;zitMSct+Z@@`#*Qa zj*wsfz(9wYNGYa;ClV|o8lOx3l*L#0JyVyM^dEqL*4 zd%=~%xe4?ejCBFm8E9L+7e z{WyIaDAXo{xwo-WwLWj`Dcj-O*leBti+n3y69xy_2;atfUsz_*hMlo8oyrU}UOVRLIXA3kUhYHj&CyZg zgIHe+?F3D0MB(rY%J`z~=3%P5wI=@^$*NiYo=YSdHSgMY%DI$7uQ<&)6|606#7V)J zknS_YbPHdawzNXt25Y6#^Cp;@+dwV0qJ1%Lshx{+m7SMQX~o3yFD|g3T0x#?rVPdZ z5VebAvs}yxo(;W8NSf7h(d-`|mqzxZR zGN0EEuZR0d2&=s=TF6<SU!*hiPbN zSloc@SrD5uFr+I%4+x#ZsVMP+`qTyiHR_X$Jaep^Nd)NaWShjhi(&d)TN2*V{aP!l zSeJ#S+Alp0-z7bb?00bo)hH1wSTFWFKdipoJT3DQujsH~kl+R{&!^8t#1EBIN3>Iv z;%-*w2PVtn5=m67zn7lG~W22QCv6`n0dkX2=L%T5h^N4_k6bpH|-TM0|XC zZPF@sH)`{EsbNkzBb!9>@$|vKn;PuBN`vw9e)`luw)o+)yka&`Pa(JkU7JqVrg6W4 zPP+p?p|qU3xu*2XMNOo#;lfTn2mK|JjSV6j%RNSZW}L3as!O+1?L!T7dl53*g#sr{ zvKNBo&GG1sk&PLlitVn-;v5+U>Epwf^hNtA{6?4Tm+RYi?0I;Rec8pY+z~3*Vv7xi z?xS@|QXWm*lE=x&Z?nf_qLX!NFu8LLZC7Jj_;U<}{v!RWPN zqo3RrkUXnsm)955Kz%Jtv;9^Vh&d;N@fIZVWsdU2uLIW>q5)7h%l%V6PPu&%p~cDc z{Nj-Is}|eyPZoBN3Gv_e_-dLGVOR7zUZu_7QogcwmVGM-;uhHOsd?y)!JX?XFIq@v zN-LFvwVH1YTlFbB(7SKI$J7B+G^aONEp9w*vK2y$EA|tY%6U)}+97AWH?;-B|VdY2pj4Fah?YnQ#z5UI= zuB)QuFVi7e&-NnUSSjZlSh{8t@3wEO)}fkFO_3`Pegw)M5rh59yMFEs|8i?e@C;8@c07i0MJLd_ngm+cupf z^=}i^ktR1Y=eP2SIH~PAL0Gs>o51@p9x&O0&|78QXJ>Oiq?k7ESkx4`JqFpSQzT zUhudg{FomeSfZD#M!Th0_1BTeUj1Z$Ql7hE@w@FEemz1}1S<#D)g`&Yz*{4gMb3s$Wd=3xi_)2hNy6=k4 zLSb+Bn?x~lk#h`fxx9hH+KXjnH8Qbs#mn=ej*6p;K^Y;Qr_w{-ov}99CeJq|GOT1{ z=4GyGgtzB1?qAWybDg&7oYt+;gKvU|Gf7&51cJUEUT(^#hI-eyC+ay`U?4e!UG{Fp zY0jPVGRW*o&0@F8$Hma>O3`?%t2c^*%+{J(J@|NE&alEe=!ttCt54;VT}s;m#YORM zna7?&#N(vPgKpEnPDtLHUx?dDGZFV-gEtu1YC&E8&3vW~AOL z=c{Ef#{18w0$s;bhcioGaqI{KPVkCE#x>e~YbTx%vr&OEMgysu*FliI4ins}+@=(F z{VUH@fk}k8j$J-_rzGA;G7Z@@mY3Mc1{0y!xwz+B?D`|bHURR%fpL8IymdR%dT7dJ zuGQI5OxCVzCLhMuHnSS4rMJ|~M)-ED1fwzGypn*sL?`5LCsm)5Uc%fWIXO(F_fe*B zKhaiP=LKWys`L0~!)0$?*Kv8PC_YN_`BVjhL=c+k>G9Dq&ef;X-9cqT!>{x7`Znb8 zrL(D@!XGx~rus7SeW0yd9!3Ksi%n7vwm^+%aX2+sz1TUbQR7-t2NB$8^(n>DzGtWU z7#(QpvufrS~utrtJFraUWbr3l zt=M6x& zVb(8t_6FBmjLa;K|Iyi-1X;vk$vwsRUvN~TICmQc zZ8BD@UzL5wo3ZcSYsv6h@9Y*Ec1p&z{-s&s?DR=&Ycm@g@O`=2oNek1Jjm#A<}4h6;PJTcq#C z6T+@JKiW<1RlffH#+7D6kb~E-!Y<}G$Z{}5^D*Nx0z}aykGAfv?^`CV(_v4(S{9t` z*m<^ct;75RSX>k@k6~D1XH-JKuucNDlL~l}mQ9qSJcY}v3Mjr1}l4_HP!lgu} z_j^9QjnpmEL%s_cqP;4%S-Fqun_rq&b}n&6%eikc)c`ppz*24+o0;*v1aoVP_>XOA z8cdGS(v>2kTaO;!KFQ|v`HRb=l<%HzKkQIF=gmOx?jUkH#u+G68tFZ>;w#gTke0E+ zajD^9K$#9fZKF#jQk$PCr})|3?q!iI%@j&&ZZ)Eu8XGw;FI-ZN5kcipn=EaLEaLxhGA%GAtkwL898Bfv=yd=Wa9-V|hFdJqXs3p=+*jtSFbR z&vAQGMFC4>gC*w>i(m%0-&`BQUuYfZeCSt1PC zBg*tt5Dhk{m)O1)VjHy|ker}P$0GKZ}errdJq<(yI1@K~s(=>om^Eo7RiOb_3-nF)$1TXkQPc!5TCb~UB= zUA|6j{y3l4cBn~u)cX73Z3{d2W@2?8!^#Lx@MiFGuVKCiu}2PfD$$tk!-KMid(zzo z3V-zWA?sY%!^b1qsZuruiEOw%3=`;!W7QHgs;{>M&Cfyjt2AI!8Qg*7j&x z!e%rnjHhvF4l0@)f}J5z7Vvr{_#s5^?5wZ`&MH__va zD>)#xI|ibo3RKhR$B+eqPiUng4~v}r?%w>B*Vp1B6xm@h^%(=gFru~o6i_&+GoGdX z;@bAzW7xP_WpXt7u(V16%LC=bNvAepjGt<^b)u_NZN}=SbX@+?^~QC^KRl#~=aqk! z62SUG1UbtEVsRDnjBC~sv~9lE*po?sD2rzG>DNF?oJl3E+R<=QYypT zt>e8IoDAfxhjhzm^{Q@*O*ron&K)+u1~g|~++BMu8s@)sy^M;+`EiP|<| zwjPqKEt!7%yJU%GRsEqz_C$qSF~1#4fG}6YeAB7bSSEwCJPr_$!dYQ9 zC^Wz9;)3#rO}_|EXS{8~P3+>rFwEcDM<*yzXP1-OdMNKjVb=LnxbvboGA$GCtjrJ6 zw-ezIPt&`oaLH8{Tr{i%K}_Dvzb7cY9X&Bh8TM{WH0#~dMdKB0i;(}uggR^o72tM` z=Yi6z<07gZ#|kVy?xe!EmQ6Rh$LK0A*>eznglypMEZ1Qc@Fa#2x_Vz-cAk?1wEM;E zl=HAcBr_;R(^Ow)2dfPx-9#j>%*{@CNq-&VO_Xy#PX&a7(3a~VB>QD2_oZaNkVw%^ zDdQPEcQ85S#?ouN75aIVuXh$ZC%RZJ6j+4a*%%E~J;Ql{Sg@vB{nU^;n`KpK(+{%t z$1mUKHaZFKZW7@rVR~v%fXl7z=m|Wv(NaNkFf@GGHyr(ac;y;GWk|5FDnlLGzdW?R z3ClX06HUFRWr6Dgg^y*yo=_>M7aSwa-E54$G&(6Kz8?J_B^iF8@o9v#mX?_ChU}$3=@U`4WBFILW1MFTVtra zgUS-m2M2C*odqIbUL`evm~}sR7eD*Zh@4vK)?R z?ebktyeW}V1Q6NKy}isr}8MBO=<-@iqY+aYaeK|wko{NTHZ z)~-bnlUYTldSrS$=c>P5T9>H(1za~tSnK+wForoxH(3+ggFg5w7q`oJZQXn2=g#fM z0}+Mkm|^S(SidD3(+98ch0Ow04R zL%Z8P1bz>^)Y(yP*FxdeC`V(+POWI=4d~YmFmFQZ;3oEC@=O<-B41mv6FkEqHWVAL zcORw=S&?w@#x~T!)5f0H8yjOD3OOdfRFynOG|KTgLmr$2q_vWI!_@ApEyx)lcq!PM z2}YYy8=qI6Z2Xh$X$g8kT+cE)5~Ur7cRXu^@(LFa>#<2LAX_n*1FyDNrrqiXvh?jyaBLAV?Y+4U%giYvL-VR$nySr^{e=+a<2u|NfL-;EkF zh?C5(xS8Vb$NZC=X}19_$yvoyS!n+riAbLwCATRp=pTZB?mW)W*Pt)y)3Q z`U=|GVblWqmUHgoJG-gwa(t{XiIU678S4co@2;}=%690adLgpcuRBkzWoX_J(_#`8 z-NKu)Qyg3N$>B<}ZxmI=vZvyP6s*><$m?)xJbxj#MSag-5oD(w42)X zkf0)2pPW^|>nyZVceTR%4G#`lW#XlIbr$xv!y4SOe@HxoBz{wysXPsL`Sj3$z8}7n zGlmaGw^Sj+zbLsG@ee!LwMAad%{A6~_M+ ztF@gT2V|4{%}+9f2ZUKa+D4LTfMr745bEnvB4mtu>o>Q|W$~RDwk?cpWZ{yB!=Q`J z#G92ozR(OD9NL?(awd&Bq}xc_qqJx&eS6_M+7_|vzz^&6Z;chOLuoufn8XP8oWVV8 z+lqL~B?q6b=65TD%)e{gRLQoAaT5qx$+_)|aT;BqLjFiM=nqWt3Wy{X39-${*EG?p zy$!)O+vu}rz&U)bzf+W>!V9p$cJ5R{*=Sl&*C~eOlhpunf0JnjUqWpl31ILdst3#@Q@$Go+>po35JSQQ%6Bd2`qbm7?ddl7ckM+ z|B373$Gc7!c26os<|&>`xbs5Un%+;dtm{#?^&pRu4M-D&I0&@0r{)-LQ^Vu{Za}#h zF<^VsP+}~((byQxEgEE~70qFA*yYKa1Hz=~*6B4FgGG8#Ll?F1*I$!&h>~6-q}=0k zjsK>~eX?9HYR0ttYE)4)@y`WtgZryAC)H}Y!8cI=q}|GkbXl`zMhGm}u^0T;I;6B| z3kp|k3eg9PGr#kN-A*U}1Wpk~z5}nQP}MzIr%!I6io-^*#c>o&01$lF&zCa!s@@f5 znX6ZB5M^>QTgNjQT+xX<%qy5D5z*u`{z0kwS|wmH=Uv&wP0xWK#+@I6CV%R-~GLAXB^J4lSVAa5uJ87 z<9AD`tmBW;g&pNE-Y#8`S@||Hr@Z}{t-LKuuHN2#1YWioy#9Z03XAD~n(`m3{Kr?o zT>sAu`u{zy=`!J>W^tAxLOT*>** zKP5~U6UyyEM!dGw?J)LB5a?bL+!K31JN0bL^ua)h!b`4dsh>Mw&||DH`#Q<;OW1jO z@r>bUb@ir4Mt_I%h*Cd75i z>VTDp?Sx2cPf#$!Xi_y=T;hmIKVaVz_)BxJ zFO6Z_ksbrD$kQ%&AC#9_Xi}S;RS%l_u&($;G~RuATp7UXFHRyZulC>1>4`QmN%mZ| zoFDl%R6(~tJnH0};W*PgwA$2L`@JP~HXkeLVAGyeFO|8$uV+betyx7dM#b60US}rq zJkt4V2Hl2{HGS8pb7FPb`cx@D))gDd@ED@_`JnXsTIl!Sc6eo(B-ZqTh$@zXzRHBr zdI*aj=9V&bB{ckKL=|!XY>5k?*(3Z9_v&9bp4-px-#9BhSf>|dj*rV6&D}Q#>Y683 z(@)GMWScB4v4ZwA$_PeA!Bsep4AZ|1c0`p~>0Gy_zfyegZE~#pjHEiR*W;=>%nKUa z9<1EheWC74Qg^VDK>TDlX@Yq^gLCe41(1m!lqt2-j&)wNP=5Q)?w?W!L>-*yacLjG z3xa)@Ph)w6loy4Rcgq)*>s5Gj!`h?U)DVf4Mb7q?n^RGQX(e87ojApYh!Ob1XYPs} za|6Ow=iaF9k75VvhFW6v;8mY?%iC4P3O6%$_Ta<(b`Z4vkFKH4z*4F#ri=m$OaG1m z>P72rTCL}EyuW>>a_ar9Q9!^*nI0Waf(+v`Av%_1yl0h<=SP_uwM-9{mS&SC803Fb zk~R9SBzf%c@l8*};`pC|GKjcnLxxeLDu2GQ(S3-x!PpIrUAQFY3T=hkwdHPg_2o|` z&eqQRU0-&i>$P2Utm7+e2MWJ1+R%HjZjCnnvPqQPzbG$0)H3(Fvu){QiS}7-ZpQb8 zGo)K4@=Oyw;h>iQC1}>r zN6P?}gO8xxWS44dHPDptt!0qGqiWMzcYg0X!{u;v+WR-2hZ~{OUcF@U)XNT82V4-L zUUiFhIOp2m=`w^jC0sQ!Hx4fz*-e7D9tjtCjs>EpE#)VWfQeC+l;o%Y-E84>Rv|pg zb|+qq)f?_U)R4)%Y-CmgaF;3gODdTD1adKs3y3&W)ec1*ePFA)>nX6S76vxX;)mZ| z1e>|TfrNuKmGv_C^#SE>UM_h$#=v%#f?hpjn0j1_QsfY3#CTGTKf{!8s~x(00* z()#{kzA=|*OpXM;vj_H5>T-CREWujoaN9Ro;=sKPTQB70>GEyM&CbAP*nZ~@qm2sz zx`fgqe|QZdswGvZ4L7ulT40C>YlOTf0rvaL|7Yy*+^F>msSPgu%E4_cVMr+Mv~sbw zDPP+=HJm98%f|mmZyxZpNzvBpp;-0j1PZ7Mp!07@e_(NeC`j#d9sJ^RWBrd(u32mI z-_yyN?n5zb<<(R59z;{M+wVOw!8~vYP5O#Ys1-}B;3Q&>>DJ!mx4-sxm&pS3iS?jM z*@&2Z9-(o%IWsKU%k-c*0bc2z5DFzy_j+^bAo?qZmknku(@X#VM3&jp4a4eX8{ae} z%qd&hxqAU*yy58}G-k|sEkrUF1E4Yo@2^4rhf0qJ|Df5UAgh38|5ND^4QTd!zi9UV zJE%-IPY7pbwy_wJkbJ@l{bOnEU~``QC{~`f$1iS3>dg&w6ckkznV*s}PEA^Hn8Z~RVdE<-M?QMDh>cJm^dN2(o6vuCK zbV%<2cuXTocKGtW`(VO+iBEbh|AB&N=+uFAIrC$*+^6FqU_RRdzn(Y)e6Edz$QOp* z8CjELzIjjs;QvXZUgDzCtw0wbcN!esAOX%-0NRsVAM|q&+Lp0;IeW9*2K-S6Ejc-M zm@0fm=8PBaR3y6kDek+!u2Z8+|F_-x=mpJm-K<_KaZ5?nLvbU^ap_~Utb}t+UQR2) zsXrlL@{jsag;@SeuC6N+{8F$Db>}2#|CX{Hes!uHB91G|t<3Npt7lN6ReubK2spOq!!h5{LiTvk@%C-B>Ux^{|=eS(Yd|75k38QQXS)~HpO2))4rJ& z+RH)_^70}q{Xn{!>sV>KdJdBLagMRD<11qDcCn@eM4O6e(n)eUpf0=c?(?YrfsNAV z)^wwDZWjiq?jb3z5*?!g8;40BTN68i=+5h16*g*1bK;P`{#$nY?eU-Tj?ds|sefTT zx^4WwM}qk!Y5Bh>k^cOF1V7%PVru#wzchrE$3ElAYIuHmLvxn~P9MwoRF50^qa z2}_`&c`d=2-at;ANAhgvkJInp>G!_EA}{u54~MmpeR!ry{6XI0DInEVDr7PMGTK({G%6o`FS2ThFPNd*YY3&?(E^LsND^#X3xiY z@po;X0My>ugd?_&_j}5>Q)_{cy>?lp!XChB7vnd4NdGOM`hIp31vz`#x7;>O^W+&O zNmyRaowxw)kL?~blL(&IS6<63fE>nNVl{JYJ>bSx;>&r4CVq$4>Ng#C$LraC0$|D=1kh_p z@My}h6oW)ZJaI>8F&rA^PwlVraYtzMI~5F^nErm!Xox)nGLLCFV+Nf(nJ#77MFcdV zcmR!Q?ll+O&k;)@&)E8Ak($hYRcCR?n3kJR-E_gLs!|iTwqUHY zWW{*1W?8>Ttf~#d=sAt)SIfI+Z-nt*a}h&PFa{@ItOQ2_@J1&%?ak!3NQ-UZV0(lI zP+Kzmm~#L3(3q}%zT}I~V*@EH$l*l-JCv&^#-QYsR_>W^c?M5Pr(5ISg*@TcYi{Bp zsHX7UU1Ehb%id1NX(ZiVPT*GaPf4d}JpU8hB+gF3P2l5=f+l}}jkq;k@!RfNB1AKs z37}uOa?Mdh&R+`JRK2TCZ(_TC$#*+KY`uPfu+~|uihXV+sPoxlx5jdLG-h^6dCo|x z>AdJwg{;>xvUyG49j0~tZ>E^8mg$>p&(#Il$5?N+QI&PvL^>MU601@T@s&TZqnBvh ziX?|SrvpCxUdOcQ@g5h|Yf-$Bp_6t_$eH5ABC3y-{6s4muU$z8uwZPKhGj0{N$)_JT^Ebz%<4M!cG_)%V-|gxhGw10 z=DB?->5an>=>gQ!b<6-X#v=SK?cT^NyjptOs=6Scr?80{Gw^stW|ic)@%#1|mr;@v z9?-xuf`dqor4gJ-;Mx7mTY(5MUI~xlqIhO^Y|MC^t;UoJT=|ik-N9;j&TfYvajJH$ zEzK$3=T!pl(z2-(4Iks0!gEkF@6Is{N?O2q3<@K@*~bra5|$wB2J#Be4bnuQ^L*1; zQ491fX zgM4O66F*U@8%yP!?DIM8ow8}1Yk5`^5lRZSRWuEL4oyDO*UbCrCbr0aS5WCjHEI=r zqE4|zAs=bXT!i*;XH!36ZK@K%T78(kuXbTJN*P0vux@r7V#&)g9%Exwm<&89o4 zsyaey*PA?YEdcVG{`8Z#za!EQ?z6-5h%EixroBmW$%FImT1b(?{7z;(zy|Ppcz=(F#qGcUB z>y7ssjq60wB{VQB@375O`?R@odzt6RnTstQTT_ZZNCKXuzxq%8XHLqf? zvX}nqZv+bkcd|7}myJSk@#)=L3@whYdp^vc&WmtUe*w-sXtL-_rs=3 zy89I>p@ZRV_xAd0-A`a|pQaq9U@jOR_r*E(x-5R$YEs=sEGUTV4S2_7QbFXYiLT{; zhq@JAFTCHgtR-s9Xo6vSd|Ad&Up)Hw57hoZPlTOT{PfEHy{F2XYZnY2^z}n-3b@}^ zVBUbE^lAo0pU#P8Q)hk}4R2|=*j>c4aYo?bEmbE6j7G9V&MjaeC)6nu2b+gg~%2PL2Os?sm;)-(^2mf#Td2FG95zo>D{bd1jP>aQ@g^SQ@>bN7yY z0~HU-JL!R5eBkDeuB~-GJ>ZVi`(V(Pt@uN}k_n`$?my$yVUgpoHt-9|Csp7oc=8aS zahU(S)&JLP5{DEhxDOF_hnIc+{Bsn32%--JMoBuN5w|!p9{5n|3TT1gDP?-NTTNZ$3{0mz# z3rdu1^1IPzfy?|0y^wq<+{fql-S6`LD}zxD%XXUjkg?Y(kI`_pWS0F%`@7L6*eF!-A)%p!vBsYO(Vv%lt5EIi+k6F*lNsIYbR}fp zK*7=aeh3*lz`~*Mprt|pA{LaGbM>LjS|MiCQ8F%HM*qab{Q+b$HP@vx$*rV$p zWHoEP!B6x1!63PvIi0Hr7%zr2ur4=LBOKH*2CnKY23z&cTP?=Uw1Bi@HHZDLw_iH{ zjz_so)i~!az`~4ncqN%(GIoXsKK9Y)ESCE9E-cxbnOi{36%UT^KEL|?B=qy26;&j( zMhbS3qzBGjI@1Q~*3p80ZI3R=Ukab1}Yp%-t#eSZo^LOaB_FKaPXyTP@k|!98>x{6XLG*ysRq>FhtipW