一键导入
fabric-programmable-networking
Provision P4 Tofino switches, DPDK SmartNICs, BlueField DPUs, and Open vSwitch on FABRIC
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Provision P4 Tofino switches, DPDK SmartNICs, BlueField DPUs, and Open vSwitch on FABRIC
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | fabric-programmable-networking |
| description | Provision P4 Tofino switches, DPDK SmartNICs, BlueField DPUs, and Open vSwitch on FABRIC |
| allowed-tools | ["Read","Grep","Glob","Write","Edit","Bash"] |
When invoked, generate code for programmable networking on FABRIC. Four main capabilities:
Help the user choose the right approach and generate complete setup code.
# Add P4 Tofino switch to slice
switch = slice.add_switch(name="p4-switch", site=site)
# Get switch ports
iface1 = switch.get_interfaces()[0]
iface2 = switch.get_interfaces()[1]
# Interactive command execution (regex prompt matching)
switch.execute(command=[
("command", r"expected_prompt_regex", timeout_seconds),
])
# Get logical port numbers
port = switch.get_interfaces()[0].get_device_name()
# Standard SR-IOV (10 Gbps virtual function, 1 port)
model = 'NIC_Basic'
# Mellanox ConnectX-5 (25 Gbps dedicated, 2 ports)
model = 'NIC_ConnectX_5'
# Mellanox ConnectX-6 (100 Gbps dedicated, 2 ports)
model = 'NIC_ConnectX_6'
# BlueField-3 DPU (100 Gbps, 2 ports)
model = 'NIC_ConnectX_7_100'
# BlueField-3 DPU (400 Gbps, 2 ports)
model = 'NIC_ConnectX_7_400'
pci_addr = iface.get_component().get_pci_addr()[0]
mac_addr = iface.get_mac()
os_iface = iface.get_physical_os_interface_name()
dev_name = iface.get_device_name()
bluefield = node.get_component(name='nic1')
output = bluefield.configure() # Push BFB image via RShim
output = bluefield.configure(commands=['cmd1', 'cmd2']) # With custom commands
node.pin_cpu(component_name='nic1') # Pin vCPUs to NIC's NUMA node
node.numa_tune() # Pin memory to same NUMA node
from fabrictestbed_extensions.fablib.fablib import FablibManager
fablib = FablibManager()
site = fablib.get_random_site()
slice = fablib.new_slice(name="p4-experiment")
# Create L2 networks
net1 = slice.add_l2network(name="net1")
net2 = slice.add_l2network(name="net2")
# Host nodes
node1 = slice.add_node(name="host1", site=site, cores=4, ram=16, disk=50)
iface1 = node1.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface1.set_mode("auto")
net1.add_interface(iface1)
node2 = slice.add_node(name="host2", site=site, cores=4, ram=16, disk=50)
iface4 = node2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface4.set_mode("auto")
net2.add_interface(iface4)
# P4 Tofino switch
switch = slice.add_switch(name="p4-switch", site=site)
sw_iface1 = switch.get_interfaces()[0]
sw_iface2 = switch.get_interfaces()[1]
net1.add_interface(sw_iface1)
net2.add_interface(sw_iface2)
slice.submit()
switch = slice.get_node(name="p4-switch")
# Upload P4 program
switch.upload_directory("P4_labs", ".")
# Compile P4 program
stdout, stderr = switch.execute(command=[
("sde-env-9.13.3", r"\[nix\-shell\(SDE\-9.13.3\):.*\$ ", 10),
("p4_build.sh P4_labs/lab1/p4src/basic.p4", r"\[nix\-shell\(SDE-9.13.3\):.*\$ ", 20),
("exit", r"\[nix\-shell\(SDE-9.13.3\):.*\$ ", 10),
])
# Start switch daemon (in background thread)
thread = switch.execute_thread(command=[
("sde-env-9.13.3", r"\[nix\-shell\(SDE\-9.13.3\):.*\$ ", 10),
("sudo $SDE_INSTALL/bin/./bf_kdrv_mod_load $SDE_INSTALL", r"\[nix\-shell\(SDE-9.13.3\):.*\$ ", 20),
("run_switchd.sh -p basic", r"bfshell>", 30),
("ucli", r"bf-sde>", 10),
("pm port-add 1/- 100G NONE", r"bf-sde>", 10),
("pm port-add 2/- 100G NONE", r"bf-sde>", 10),
("pm port-enb 1/-", r"bf-sde>", 10),
("pm port-enb 2/-", r"bf-sde>", 10),
("pm show", r"bf-sde>", 10),
("sleep infinity", r"bf-sde>", 300),
], output_file="run_switchd.log")
# Get logical port numbers
INGRESS = switch.get_interfaces()[0].get_device_name()
EGRESS = switch.get_interfaces()[1].get_device_name()
# Update setup script with port numbers
switch.execute(
f"sed -i 's/ingress_logical *= *[0-9]\\+/ingress_logical = {INGRESS}/' "
f"P4_labs/lab1/bfrt_python/setup.py"
)
switch.execute(
f"sed -i 's/egress_logical *= *[0-9]\\+/egress_logical = {EGRESS}/' "
f"P4_labs/lab1/bfrt_python/setup.py"
)
# Run bfshell to populate tables
stdout, stderr = switch.execute(command=[
("sde-env-9.13.3", r"\[nix\-shell\(SDE\-9.13.3\):.*\$ ", 10),
("run_bfshell.sh --no-status-srv -b ~/P4_labs/lab1/bfrt_python/setup.py",
r"\[nix\-shell\(SDE\-9.13.3\):.*\$ ", 10),
])
site = fablib.get_random_site(
filter_function=lambda x: x['nic_connectx_6_available'] > 0
)
slice = fablib.new_slice(name="dpdk-experiment")
# L3 network for management
net = slice.add_l3network(name="data-net", type="IPv4")
# L3FWD node with dedicated NIC
l3fwd = slice.add_node(name="l3fwd", site=site, cores=8, ram=32, disk=50)
l3fwd.add_fabnet()
iface1 = l3fwd.add_component(model="NIC_ConnectX_6", name="nic1").get_interfaces()[0]
iface1.set_mode("auto")
net.add_interface(iface1)
# Packet generator node
pktgen = slice.add_node(name="pktgen", site=site, cores=8, ram=32, disk=50)
pktgen.add_fabnet()
iface2 = pktgen.add_component(model="NIC_ConnectX_6", name="nic1").get_interfaces()[0]
iface2.set_mode("auto")
net.add_interface(iface2)
# Post-boot DPDK setup
for n in [l3fwd, pktgen]:
n.add_post_boot_upload_directory('node_tools', '.')
n.add_post_boot_execute('chmod +x node_tools/*')
n.add_post_boot_execute('sudo node_tools/install.sh')
slice.submit()
for n in slice.get_nodes():
n.execute(
f"sudo node_tools/grub.sh {n.get_ram()}",
quiet=True,
output_file=f"logs/{n.get_name()}-grub.log",
)
n.execute(
"sudo node_tools/apply_vfio_settings.sh",
quiet=True,
output_file=f"logs/{n.get_name()}-vfio.log",
)
# Reboot required
for n in slice.get_nodes():
n.execute("sudo reboot")
slice.wait_ssh(timeout=360, interval=10, progress=True)
# Build DPDK (parallel)
execute_threads = {}
for n in slice.get_nodes():
execute_threads[n] = n.execute_thread(
"node_tools/dpdk.sh",
output_file=f"logs/{n.get_name()}-dpdk.log",
)
for n, thread in execute_threads.items():
stdout, stderr = thread.result()
# Run L3FWD
l3fwd_iface = l3fwd.get_interface(network_name="data-net")
pktgen_iface = pktgen.get_interface(network_name="data-net")
print(
f"cd dpdk-23.07 && sudo ./build/examples/dpdk-l3fwd "
f"-a {l3fwd_iface.get_component().get_pci_addr()[0]} -c 0x1 -n 4 "
f"-- -p 0x1 --config=\"(0,0,0)\" "
f"--eth-dest=0,{pktgen_iface.get_mac().lower()}"
)
# Run Pktgen
print(
f"sudo ./Builddir/app/pktgen "
f"-a {pktgen_iface.get_component().get_pci_addr()[0]} -l 0-4 -n 3 -- -P -m [1:3].0"
)
site = fablib.get_random_site(
filter_function=lambda x: x['nic_connectx_7_available'] > 0
)
slice = fablib.new_slice(name="bluefield-experiment")
node = slice.add_node(
name="bf-node", site=site, cores=8, ram=32, disk=100, image="dpu_ubuntu_24"
)
dpu = node.add_component(model="NIC_ConnectX_7_400", name="nic1")
iface1 = dpu.get_interfaces()[0]
iface2 = dpu.get_interfaces()[1]
net = slice.add_l2network(name="data-net")
iface1.set_mode("auto")
net.add_interface(iface1)
slice.submit()
# Configure BlueField DPU (push BFB image via RShim)
node = slice.get_node(name="bf-node")
bluefield = node.get_component(name="nic1")
output = bluefield.configure()
# Set up RShim management interface
node.execute("sudo ip addr add 192.168.100.1/24 dev tmfifo_net0")
node.execute("sudo ip link set tmfifo_net0 up")
# SSH to DPU ARM cores: ssh ubuntu@192.168.100.2
# Set up NAT for DPU internet access
import ipaddress
ip = ipaddress.ip_address(node.get_management_ip())
if ip.version == 4:
node.execute("sudo ./node_tools/bf3_rshim.sh --mode ipv4")
else:
node.execute("sudo ./node_tools/bf3_rshim.sh --mode ipv6")
# Console access to DPU
# screen /dev/rshim0/console
site = fablib.get_random_site()
slice = fablib.new_slice(name="ovs-experiment")
# Bridge node (OVS runs here)
bridge = slice.add_node(
name="bridge",
site=site,
cores=4,
ram=8,
disk=50,
host=f"{site.lower()}-w1.fabric-testbed.net",
)
# Add multiple interfaces for bridging
net1 = slice.add_l2network(name="net1")
net2 = slice.add_l2network(name="net2")
br_iface1 = bridge.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
net1.add_interface(br_iface1)
br_iface2 = bridge.add_component(model="NIC_Basic", name="nic2").get_interfaces()[0]
net2.add_interface(br_iface2)
# Host nodes on different physical host (SR-IOV constraint)
host1 = slice.add_node(
name="host1",
site=site,
cores=4,
ram=8,
disk=50,
host=f"{site.lower()}-w2.fabric-testbed.net",
)
h1_iface = host1.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
net1.add_interface(h1_iface)
host2 = slice.add_node(
name="host2",
site=site,
cores=4,
ram=8,
disk=50,
host=f"{site.lower()}-w2.fabric-testbed.net",
)
h2_iface = host2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
net2.add_interface(h2_iface)
slice.submit()
# Install and configure OVS
bridge = slice.get_node(name="bridge")
bridge.execute("sudo apt-get update && sudo apt-get -y install openvswitch-switch openvswitch-common net-tools")
# Create OVS bridge and add ports
bridge.execute("sudo ovs-vsctl add-br br0")
for iface in bridge.get_interfaces():
os_name = iface.get_physical_os_interface_name()
bridge.execute(f"sudo ovs-vsctl add-port br0 {os_name}")
bridge.execute(f"sudo ifconfig {os_name} 0") # Remove IP from physical interface
bridge.execute("sudo ifconfig br0 up")
# Enable Spanning Tree Protocol
bridge.execute("sudo ovs-vsctl set bridge br0 stp_enable=true")
# Verify
stdout, _ = bridge.execute("sudo ovs-appctl stp/show")
print(stdout)
# Configure host IPs
host1 = slice.get_node(name="host1")
os_iface = host1.get_interfaces()[0].get_physical_os_interface_name()
host1.execute(f"sudo ip link set dev {os_iface} up")
host1.execute(f"sudo ip addr add 10.10.10.1/24 dev {os_iface}")
host2 = slice.get_node(name="host2")
os_iface2 = host2.get_interfaces()[0].get_physical_os_interface_name()
host2.execute(f"sudo ip link set dev {os_iface2} up")
host2.execute(f"sudo ip addr add 10.10.10.2/24 dev {os_iface2}")
# Test connectivity through OVS bridge
stdout, _ = host1.execute("ping -c 5 10.10.10.2")
print(stdout)
execute(command=[...]) with regex prompt matchingdpu_ubuntu_24 image; RShim interface at 192.168.100.1/24node.pin_cpu() and node.numa_tune() for DPDK workloadsnode.execute_thread() for long-running installsRun iPerf3 network performance benchmarks with optional CPU pinning and SmartNIC optimization
Generate FABRIC testbed environment setup, configuration validation, and SSH key management code
Deploy Docker containers and Kubernetes clusters on FABRIC nodes
Connect FABRIC to external testbeds via facility ports and set up port mirroring
Provision and flash Xilinx U280 FPGAs on FABRIC nodes
Provision GPU nodes on FABRIC with driver installation and CUDA setup