| name | fabric-facility-ports |
| description | Connect FABRIC to external testbeds via facility ports and set up port mirroring |
| allowed-tools | ["Read","Grep","Glob","Write","Edit","Bash"] |
Instructions
When invoked, generate code for inter-testbed connectivity and traffic monitoring. Two main capabilities:
- Facility Ports — Connect FABRIC to external testbeds (Chameleon, CloudLab) via L2 or L3
- Port Mirroring — Mirror traffic from one interface to a listener node for analysis
Help the user set up the right connectivity and generate complete code.
API Reference
Adding a Facility Port
facility_port = slice.add_facility_port(
name: str,
site: str,
vlan: str,
) -> Component
Available Facility Ports
| Name | Site | External Testbed |
|---|
Chameleon-TACC | TACC | Chameleon at TACC |
Chameleon-StarLight | STAR | Chameleon at Chicago |
Utah-Cloudlab-Powder | UTAH | CloudLab/Powder at Utah |
Listing Facility Ports
fablib.list_facility_ports()
Port Mirroring
pmnet = slice.add_port_mirror_service(
name: str,
mirror_interface_name: str,
receive_interface: Interface,
mirror_interface_vlan: str = None,
mirror_direction: str = 'both',
)
Getting Peer Port Info
mirror_port_name = node.get_interfaces()[0].get_peer_port_name()
mirror_port_vlan = node.get_interfaces()[0].get_peer_port_vlan()
Patterns
L2 Connection to Chameleon
from fabrictestbed_extensions.fablib.fablib import FablibManager
from ipaddress import IPv4Address, IPv4Network
fablib = FablibManager()
fabric_site = "TACC"
facility_port = "Chameleon-TACC"
network_vlan = "3100"
subnet = IPv4Network("192.168.100.0/24")
available_ips = list(subnet.hosts())
slice = fablib.new_slice(name="chameleon-l2")
net = slice.add_l2network(name="inter-testbed-net", subnet=subnet)
node = slice.add_node(name="fabric-node", site=fabric_site, cores=4, ram=16, disk=50)
node_iface = node.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
node_iface.set_mode("config")
net.add_interface(node_iface)
fp = slice.add_facility_port(name=facility_port, site=fabric_site, vlan=network_vlan)
fp_iface = fp.get_interfaces()[0]
fp_iface.set_mode("manual")
net.add_interface(fp_iface)
slice.submit()
node = slice.get_node(name="fabric-node")
node_iface = node.get_interface(network_name="inter-testbed-net")
node_iface.ip_addr_add(addr=available_ips[10], subnet=subnet)
chameleon_ip = "192.168.100.5"
stdout, _ = node.execute(f"ping -c 5 {chameleon_ip}")
print(stdout)
L3 FABNetv4 Connection to Chameleon
fabric_site = "TACC"
facility_port_name = "Chameleon-TACC"
network_vlan = "3100"
slice = fablib.new_slice(name="chameleon-fabnet")
node = slice.add_node(name="fabric-node", site=fabric_site, cores=4, ram=16, disk=50)
node.add_fabnet()
fp = slice.add_facility_port(
name=facility_port_name, site=fabric_site, vlan=network_vlan
)
fp_iface = fp.get_interfaces()[0]
fabric_net = slice.add_l3network(
name="facility_port_fabnetv4", interfaces=[fp_iface]
)
slice.submit()
fabric_network = slice.get_network("facility_port_fabnetv4")
subnet = fabric_network.get_subnet()
gateway_ip = fabric_network.get_gateway()
print(f"Subnet: {subnet}")
print(f"Gateway: {gateway_ip}")
L2 Connection to CloudLab
fabric_site = "UTAH"
facility_port_name = "Utah-Cloudlab-Powder"
network_vlan = "3101"
subnet = IPv4Network("10.10.1.0/24")
slice = fablib.new_slice(name="cloudlab-l2")
net = slice.add_l2network(name="cloudlab-net", subnet=subnet)
node = slice.add_node(name="fabric-node", site=fabric_site, cores=4, ram=16, disk=50)
node_iface = node.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
node_iface.set_mode("config")
net.add_interface(node_iface)
fp = slice.add_facility_port(name=facility_port_name, site=fabric_site, vlan=network_vlan)
fp_iface = fp.get_interfaces()[0]
fp_iface.set_mode("manual")
net.add_interface(fp_iface)
slice.submit()
node = slice.get_node(name="fabric-node")
node_iface = node.get_interface(network_name="cloudlab-net")
node_iface.ip_addr_add(addr=IPv4Address("10.10.1.10"), subnet=subnet)
stdout, _ = node.execute("ping -c 5 10.10.1.1")
print(stdout)
Port Mirroring (Within a Slice)
site = fablib.get_random_site()
slice = fablib.new_slice(name="port-mirror")
subnet = IPv4Network("192.168.1.0/24")
net = slice.add_l2network(name="data-net", subnet=subnet)
node1 = slice.add_node(name="sender", site=site)
iface1 = node1.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface1.set_mode("auto")
net.add_interface(iface1)
node2 = slice.add_node(name="receiver", site=site)
iface2 = node2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface2.set_mode("auto")
net.add_interface(iface2)
listener = slice.add_node(name="listener", site=site)
listener_iface = listener.add_component(
model="NIC_ConnectX_5", name="pmnic"
).get_interfaces()[0]
mirror_port_name = iface1.get_peer_port_name()
pmnet = slice.add_port_mirror_service(
name="mirror-service",
mirror_interface_name=mirror_port_name,
receive_interface=listener_iface,
mirror_direction="both",
)
slice.submit()
listener = slice.get_node(name="listener")
listener.execute(
"sudo tcpdump -i $(ip -o link show | grep -v lo | head -1 | awk '{print $2}' | tr -d ':') "
"-w /tmp/capture.pcap -c 1000 &"
)
sender = slice.get_node(name="sender")
receiver_addr = slice.get_node(name="receiver").get_interface(
network_name="data-net"
).get_ip_addr()
sender.execute(f"ping -c 100 {receiver_addr}")
Port Mirroring (Across Slices)
traffic_slice = fablib.get_slice(name="traffic-experiment")
traffic_node = traffic_slice.get_node(name="node1")
mirror_port_name = traffic_node.get_interfaces()[0].get_peer_port_name()
listener_slice = fablib.new_slice(name="mirror-listener")
listener = listener_slice.add_node(name="listener", site=site)
listener_iface = listener.add_component(
model="NIC_ConnectX_6", name="pmnic"
).get_interfaces()[0]
pmnet = listener_slice.add_port_mirror_service(
name="cross-slice-mirror",
mirror_interface_name=mirror_port_name,
receive_interface=listener_iface,
mirror_direction="both",
)
listener_slice.submit()
Important Notes
- Facility port VLAN: Obtained from the external testbed (Chameleon network segmentation ID, CloudLab pre-assigned)
- Interface modes: Use
'manual' for facility port interfaces, 'config' for FABRIC node interfaces on L2
- Port mirroring permission: Requires
Net.PortMirror project permission tag
- Listener NIC: Use
NIC_ConnectX_5 or NIC_ConnectX_6 (dedicated NICs) for mirrored traffic
- Mirror direction:
'rx' (ingress only), 'tx' (egress only), or 'both'
- Cross-slice mirroring: Use
get_peer_port_name() from the source slice to reference the port in the listener slice