diff --git a/fabric_examples/complex_recipes/iPerf3/iperf3_optimized.ipynb b/fabric_examples/complex_recipes/iPerf3/iperf3_optimized.ipynb new file mode 100644 index 00000000..0016108b --- /dev/null +++ b/fabric_examples/complex_recipes/iPerf3/iperf3_optimized.ipynb @@ -0,0 +1,358 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a Slice, Apply performance tuning and Run iPerf3\n", + "\n", + "This notebook creates a slice on a single site with 3 nodes with each node connected to a NIC_Basic and running on a different host. \n", + "All the nodes are connected via local L2 Network. The notebook then depicts an example on how to apply CPU Pinning and Numa Tuning.\n", + "In this notebook, Virtual CPUs for each of the Nodes are pinned to the Physical CPUs residing on the same Numa node as the NIC_Basic connected to the node. In addition, Memory for the Node is also tuned to the same Numa node as the NIC_Basic connected to the node.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Import the FABlib Library\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from ipaddress import ip_address, IPv4Address, IPv6Address, IPv4Network, IPv6Network\n", + "import ipaddress\n", + "from fabrictestbed_extensions.fablib.fablib import FablibManager as fablib_manager\n", + "\n", + "fablib = fablib_manager()\n", + "\n", + "fablib.show_config();" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## Create the Experiment Slice\n", + "\n", + "The following creates three nodes with basic NICs running on different hosts connected to an isolated local Ethernet. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# find two available sites\n", + "\n", + "# we will use NIC_Basic to generate traffic so need sites that have >= 3 workers for this example.\n", + "hosts_column_name = 'hosts'\n", + "\n", + "# find two sites with >= 3 hosts\n", + "site1 = fablib.get_random_site(filter_function=lambda x: x[hosts_column_name] > 0)\n", + "print(f\"Site: {site1}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "slice_name = 'iPerf3-tuned-basic'\n", + "\n", + "node1_name='Node1'\n", + "node2_name='Node2'\n", + "\n", + "network_name='net1'\n", + "nic_name = 'nic1'\n", + "model_name = 'NIC_Basic'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Define a subnet to use for the L2 Network\n", + "from ipaddress import ip_address, IPv4Address, IPv6Address, IPv4Network, IPv6Network\n", + "\n", + "subnet = IPv4Network(\"192.168.1.0/24\")\n", + "available_ips = list(subnet)[1:]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#Create Slice\n", + "slice = fablib.new_slice(name=slice_name)\n", + "\n", + "net1 = slice.add_l2network(name=network_name, subnet=subnet)\n", + "\n", + "\n", + "hosts = [f\"{site1.lower()}-w1\", f\"{site1.lower()}-w2\", f\"{site1.lower()}-w3\"]\n", + "\n", + "for h in hosts:\n", + "\n", + " # Node1\n", + " node1 = slice.add_node(name=f\"{h}-a\", cores=16, ram=32, site=site1, image='docker_rocky_8', host=f\"{h}.fabric-testbed.net\")\n", + "\n", + " iface1 = node1.add_component(model=model_name, name=nic_name).get_interfaces()[0]\n", + " iface1.set_mode('auto')\n", + " net1.add_interface(iface1)\n", + "\n", + " node1.add_post_boot_upload_directory('node_tools','.')\n", + " node1.add_post_boot_execute('sudo node_tools/host_tune.sh')\n", + " node1.add_post_boot_execute('node_tools/enable_docker.sh {{ _self_.image }} ')\n", + " node1.add_post_boot_execute('docker pull fabrictestbed/slice-vm-rocky8-multitool:0.0.2 ')\n", + "\n", + "#Submit Slice Request\n", + "slice.submit();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run iPerf3 without any performance tuning\n", + "\n", + "Run iperf3 between every pair of the Nodes before applying performance tuning." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "\n", + "\n", + "source_name = f\"{site1.lower()}-w1-a\"\n", + "source_node = slice.get_node(name=source_name)\n", + "\n", + "source_addr = source_node.get_interface(network_name=network_name).get_ip_addr()\n", + "\n", + "node_names = [f\"{site1.lower()}-w1-a\", f\"{site1.lower()}-w2-a\", f\"{site1.lower()}-w3-a\"]\n", + "\n", + "for i in range(len(node_names)):\n", + " source_node = slice.get_node(name=node_names[i])\n", + " source_addr = source_node.get_interface(network_name=network_name).get_ip_addr()\n", + " \n", + " for j in range(len(node_names)):\n", + " if i==j:\n", + " continue\n", + " print(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\")\n", + " stdout1, stderr1 = source_node.execute(\"docker run -d --rm \"\n", + " \"--network host \"\n", + " \"fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \"\n", + " \"iperf3 -s -1\"\n", + " , quiet=True, output_file=f\"{source_node.get_name()}-no-tune.log\");\n", + "\n", + " print(f\"Source: {node_names[i]} to Dest: {node_names[j]}\")\n", + " dest_node = slice.get_node(name=node_names[j])\n", + "\n", + " stdout2, stderr2 = dest_node.execute(\"docker run --rm \"\n", + " \"--network host \"\n", + " \"fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \"\n", + " f\"iperf3 -c {source_addr} -P 10 -t 30 -i 10 -O 10\"\n", + " , quiet=False, output_file=f\"{dest_node.get_name()}-no-tune.log\");\n", + " print(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Perform CPU Pinning and Numa Tuning" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "\n", + "for node in slice.get_nodes():\n", + " # Pin all vCPUs for VM to same Numa node as the component\n", + " node.pin_cpu(component_name=nic_name)\n", + " \n", + " # User can also pass in the range of the vCPUs to be pinned \n", + " #node.pin_cpu(component_name=nic_name, cpu_range_to_pin=\"0-3\")\n", + " \n", + " # Pin memmory for VM to same Numa node as the components\n", + " node.numa_tune()\n", + " \n", + " # Reboot the VM\n", + " node.os_reboot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Re-configure Network Interfaces and Enable Docker post reboot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "\n", + "# Wait for the SSH Connectivity to be back\n", + "slice.wait_ssh()\n", + "\n", + "# Re-configuring the Network\n", + "for node in slice.get_nodes():\n", + " node.config()\n", + " stdout1, stderr1 = node.execute(\"sudo systemctl enable docker\")\n", + " stdout1, stderr1 = node.execute(\"sudo systemctl start docker\") \n", + " stdout1, stderr1 = node.execute(\"sudo docker pull fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \")\n", + " stdout1, stderr1 = node.execute(\"sudo systemctl enable docker\")\n", + " stdout1, stderr1 = node.execute(\"sudo systemctl start docker\") " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Verify IP Addresses are configured" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "slice.list_interfaces();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run iperf3 after performance tuning\n", + "\n", + "Run iperf3 between every pair of the Nodes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "\n", + "\n", + "source_name = f\"{site1.lower()}-w1-a\"\n", + "source_node = slice.get_node(name=source_name)\n", + "\n", + "source_addr = source_node.get_interface(network_name=network_name).get_ip_addr()\n", + "\n", + "node_names = [f\"{site1.lower()}-w1-a\", f\"{site1.lower()}-w2-a\", f\"{site1.lower()}-w3-a\"]\n", + "\n", + "for i in range(len(node_names)):\n", + " source_node = slice.get_node(name=node_names[i])\n", + " source_addr = source_node.get_interface(network_name=network_name).get_ip_addr()\n", + " \n", + " for j in range(len(node_names)):\n", + " if i==j:\n", + " continue\n", + " print(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\")\n", + " stdout1, stderr1 = source_node.execute(\"docker run -d --rm \"\n", + " \"--network host \"\n", + " \"fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \"\n", + " \"iperf3 -s -1\"\n", + " , quiet=True, output_file=f\"{source_node.get_name()}.log\");\n", + "\n", + " print(f\"Source: {node_names[i]} to Dest: {node_names[j]}\")\n", + " dest_node = slice.get_node(name=node_names[j])\n", + "\n", + " stdout2, stderr2 = dest_node.execute(\"docker run --rm \"\n", + " \"--network host \"\n", + " \"fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \"\n", + " f\"iperf3 -c {source_addr} -P 10 -t 30 -i 10 -O 10\"\n", + " , quiet=False, output_file=f\"{dest_node.get_name()}.log\");\n", + " print(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Delete the Slice\n", + "\n", + "Please delete your slice when you are done with your experiment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "slice.delete()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/fabric_examples/complex_recipes/iPerf3/iperf3_optimized_smart_nic.ipynb b/fabric_examples/complex_recipes/iPerf3/iperf3_optimized_smart_nic.ipynb new file mode 100644 index 00000000..b73854e4 --- /dev/null +++ b/fabric_examples/complex_recipes/iPerf3/iperf3_optimized_smart_nic.ipynb @@ -0,0 +1,335 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a Slice and Run iPerf3\n", + "\n", + "This notebook creates a slice 2 nodes with each node connected to a NIC_ConnectX_5 on two different sites. \n", + "All the nodes are connected via L2 Network. The notebook then depicts an example on how to apply CPU Pinning and Numa Tuning.\n", + "In this notebook, Virtual CPUs for each of the Nodes are pinned to the Physical CPUs residing on the same Numa node as the NIC_ConnectX_5 connected to the node. In addition, Memory for the Node is also tuned to the same Numa node as the NIC_ConnectX_5 connected to the node.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Import the FABlib Library\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from ipaddress import ip_address, IPv4Address, IPv6Address, IPv4Network, IPv6Network\n", + "import ipaddress\n", + "from fabrictestbed_extensions.fablib.fablib import FablibManager as fablib_manager\n", + "\n", + "fablib = fablib_manager()\n", + "\n", + "fablib.show_config();" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## Create the Experiment Slice\n", + "\n", + "The following creates two nodes with basic NICs running on different hosts connected to an isolated local Ethernet. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# find two available sites\n", + "\n", + "# we will use CX5 to generate traffic so need sites that have CX5 for this example.\n", + "cx5_column_name = 'nic_connectx_5_available'\n", + "\n", + "# find two sites with available ConnectX-5 \n", + "sites = fablib.get_random_sites(count=2, filter_function=lambda x: x[cx5_column_name] > 0)\n", + "print(f\"Sites: {sites}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "slice_name = 'iPerf3-tuned-smart-nic'\n", + "\n", + "node1_name='Node1'\n", + "node2_name='Node2'\n", + "\n", + "network_name='net1'\n", + "nic_name = 'nic1'\n", + "model_name = 'NIC_ConnectX_5'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from ipaddress import ip_address, IPv4Address, IPv6Address, IPv4Network, IPv6Network\n", + "\n", + "subnet = IPv4Network(\"192.168.1.0/24\")\n", + "available_ips = list(subnet)[1:]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#Create Slice\n", + "slice = fablib.new_slice(name=slice_name)\n", + "\n", + "net1 = slice.add_l2network(name=network_name, subnet=subnet)\n", + "\n", + "\n", + "for s in sites:\n", + " # Node1\n", + " node1 = slice.add_node(name=f\"Node-{s}\", cores=16, ram=32, site=s, image='docker_rocky_8')\n", + "\n", + " iface1 = node1.add_component(model=model_name, name=nic_name).get_interfaces()[0]\n", + " iface1.set_mode('auto')\n", + " net1.add_interface(iface1)\n", + "\n", + " node1.add_post_boot_upload_directory('node_tools','.')\n", + " node1.add_post_boot_execute('sudo node_tools/host_tune.sh')\n", + " node1.add_post_boot_execute('node_tools/enable_docker.sh {{ _self_.image }} ')\n", + " node1.add_post_boot_execute('docker pull fabrictestbed/slice-vm-rocky8-multitool:0.0.2 ')\n", + "\n", + "#Submit Slice Request\n", + "slice.submit();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run iPerf3 without any performance tuning" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "\n", + "\n", + "for i in range(len(sites)):\n", + " node_name = f\"Node-{sites[i]}\"\n", + " source_node = slice.get_node(name=node_name)\n", + " source_addr = source_node.get_interface(network_name=network_name).get_ip_addr()\n", + " \n", + " for j in range(len(sites)):\n", + " if i==j:\n", + " continue\n", + " print(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\")\n", + " stdout1, stderr1 = source_node.execute(\"docker run -d --rm \"\n", + " \"--network host \"\n", + " \"fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \"\n", + " \"iperf3 -s -1\"\n", + " , quiet=True, output_file=f\"{source_node.get_name()}-no-tune.log\");\n", + "\n", + " dest_node_name = f\"Node-{sites[j]}\"\n", + " print(f\"Source: {node_name} to Dest: {dest_node_name}\")\n", + " dest_node = slice.get_node(name=dest_node_name)\n", + "\n", + " stdout2, stderr2 = dest_node.execute(\"docker run --rm \"\n", + " \"--network host \"\n", + " \"fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \"\n", + " f\"iperf3 -c {source_addr} -P 10 -t 30 -i 10 -O 10\"\n", + " , quiet=False, output_file=f\"{dest_node.get_name()}-no-tune.log\");\n", + " print(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Perform CPU Pinning and Numa Tuning" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "\n", + "for node in slice.get_nodes():\n", + " # Pin all vCPUs for VM to same Numa node as the component\n", + " node.pin_cpu(component_name=nic_name)\n", + " \n", + " # User can also pass in the range of the vCPUs to be pinned \n", + " #node.pin_cpu(component_name=nic_name, cpu_range_to_pin=\"0-3\")\n", + " \n", + " # Pin memmory for VM to same Numa node as the components\n", + " node.numa_tune()\n", + " \n", + " # Reboot the VM\n", + " node.os_reboot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Re-configure Network Interfaces and Enable Docker post reboot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "\n", + "# Wait for the SSH Connectivity to be back\n", + "slice.wait_ssh()\n", + "\n", + "# Re-configuring the Network\n", + "for node in slice.get_nodes():\n", + " node.config()\n", + " stdout1, stderr1 = node.execute(\"sudo systemctl enable docker\")\n", + " stdout1, stderr1 = node.execute(\"sudo systemctl start docker\") \n", + " stdout1, stderr1 = node.execute(\"sudo docker pull fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \")\n", + " stdout1, stderr1 = node.execute(\"sudo systemctl enable docker\")\n", + " stdout1, stderr1 = node.execute(\"sudo systemctl start docker\") " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Verify IP Addresses are configured" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "slice.list_interfaces();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run iperf3 after performance tuning\n", + "\n", + "Run iperf3 between every pair of the Nodes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "\n", + "\n", + "for i in range(len(sites)):\n", + " node_name = f\"Node-{sites[i]}\"\n", + " source_node = slice.get_node(name=node_name)\n", + " source_addr = source_node.get_interface(network_name=network_name).get_ip_addr()\n", + " \n", + " for j in range(len(sites)):\n", + " if i==j:\n", + " continue\n", + " print(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\")\n", + " stdout1, stderr1 = source_node.execute(\"docker run -d --rm \"\n", + " \"--network host \"\n", + " \"fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \"\n", + " \"iperf3 -s -1\"\n", + " , quiet=True, output_file=f\"{source_node.get_name()}.log\");\n", + "\n", + " dest_node_name = f\"Node-{sites[j]}\"\n", + " print(f\"Source: {node_name} to Dest: {dest_node_name}\")\n", + " dest_node = slice.get_node(name=dest_node_name)\n", + "\n", + " stdout2, stderr2 = dest_node.execute(\"docker run --rm \"\n", + " \"--network host \"\n", + " \"fabrictestbed/slice-vm-rocky8-multitool:0.0.2 \"\n", + " f\"iperf3 -c {source_addr} -P 10 -t 30 -i 10 -O 10\"\n", + " , quiet=False, output_file=f\"{dest_node.get_name()}.log\");\n", + " print(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Delete the Slice\n", + "\n", + "Please delete your slice when you are done with your experiment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "slice = fablib.get_slice(slice_name)\n", + "slice.delete()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/requirements.txt b/requirements.txt index 335e861b..4ab0f436 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -fabrictestbed-extensions==1.5.0 +fabrictestbed-extensions==1.5.2 python-dotenv ipython==8.12.0 fabrictestbed-mflib>=1.0.0 diff --git a/start_here.ipynb b/start_here.ipynb index 872f7f11..ed461b78 100644 --- a/start_here.ipynb +++ b/start_here.ipynb @@ -109,11 +109,12 @@ "- [Kubernetes Cluster](./fabric_examples/complex_recipes/kubernetes/kubernetes_simple.ipynb): Create a private Kubernetes cluster on FABRIC resources.\n", "- [Benchmarking FABRIC Storage: Local disk and NVMe](./fabric_examples/fablib_api/bbenchmarking_storage/enchmarking_storage.ipynb): Create and benchmark a node with local disk and NVMe device.\n", "- [iPerf3](./fabric_examples/complex_recipes/iPerf3/iperf3.ipynb): Test bandwidth across your FABRIC slice.\n", + " - [CPU Pinning and Numa Tuning Basic NIC](./fabric_examples/complex_recipes/iPerf3/iperf3_optimized.ipynb): Apply CPU Pinning and Numa tuning with NIC_Basic and test bandwidth across your FABRIC slice.\n", + " - [CPU Pinning and Numa Tuning ConnectX_5/ConnectX_6](./fabric_examples/complex_recipes/iPerf3/iperf3_optimized_smart_nic.ipynb): Apply CPU Pinning and Numa tuning with NIC_ConnectX_5 and test bandwidth across your FABRIC slice.\n", "- Chameleon Facility Ports: Create slices spanning Chameleon and FABRIC ([L2 connection](./fabric_examples/complex_recipes/Chameleon_Facility_Port/Chameleon_Facility_Port_L2.ipynb), [L3 FABnetv4](./fabric_examples/complex_recipes/Chameleon_Facility_Port/Chameleon_Facility_Port_fabnetv4.ipynb))\n", "- Grafana and Prometheus:\n", " - [Grafana/Prometheus Server](./fabric_examples/complex_recipes/grafana_prometheus_servers/grafana-prometheus-servers.ipynb): Deploy a Grafana/Prometheus services on a FABIRC node using Docker.\n", " - [Prometheus Node Exporter](./fabric_examples/complex_recipes/grafana_prometheus_servers/node_exporter.ipynb): Create a slice that can be monitored by a Grafana/Prometheus server. \n", - "\n", "### Monitoring MFLib\n", "- [Monitoring with MFLib Examples](./fabric_examples/mflib/mflib_example_index.ipynb): Examples for setting up automated monitoring in your slice. \n", "\n",