fabric-network

Configure L2/L3 networking, FABnet, facility ports, VLANs, and IP addressing on FABRIC slices

fabric-testbed/claude-plugin-marketplace1 installsApache-2.0Synced Aug 26

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI

Agent Skills format with YAML frontmatter. Claude Code reads it as-is.

---
name: "fabric-network"
description: "Configure L2/L3 networking, FABnet, facility ports, VLANs, and IP addressing on FABRIC slices"
license: "Apache-2.0"
---

# Instructions

When invoked, generate networking code for FABRIC slices. Determine the user's networking needs:

1. **L2 Networks** (Bridge, PTP, STS) — Layer 2 Ethernet connectivity
2. **L3 FABnet** — FABRIC's routed IPv4/IPv6 network across sites
3. **FABNetv4Ext** — Public IPv4 addresses
4. **Facility Ports** — External connectivity to campus/provider networks
5. **Sub-interfaces/VLANs** — VLAN tagging on dedicated NICs
6. **Port Mirroring** — Traffic capture

Guide users on NIC type selection based on their needs.

**Important**: Use the modern API pattern for networks:
1. Create the network with `slice.add_l2network()` or `slice.add_l3network()`
2. Set interface mode: `iface.set_mode('auto')`
3. Add interface to network: `net.add_interface(iface)`
4. For L3 routing: `node.add_route(subnet=fablib.FABNETV4_SUBNET, next_hop=net.get_gateway())`

# API Reference

## L2 Network Types

```python
net = slice.add_l2network(
    name: str = None,
    interfaces: list[Interface] = [],  # Can pass here or use net.add_interface() after
    type: str = None,       # "L2Bridge", "L2PTP", "L2STS"
    subnet: ipaddress = None,  # For auto IP assignment
    gateway: ipaddress = None,
    user_data: dict = {},
) -> NetworkService
```

- **L2Bridge**: Local Ethernet on a single site, unlimited interfaces
- **L2PTP**: Point-to-point link between exactly 2 interfaces (can span sites)
- **L2STS**: Site-to-site link between exactly 2 interfaces on different sites

## L3 Network

```python
net = slice.add_l3network(
    name: str = None,
    interfaces: list[Interface] = [],  # Can pass here or use net.add_interface() after
    type: str = "IPv4",     # "IPv4", "IPv6", "IPv4Ext", "IPv6Ext"
    user_data: dict = {},
    technology: str = None,
    subnet: ipaddress.ip_network = None,
    site: str = None,
) -> NetworkService
```

## Network Methods

```python
net.add_interface(iface)           # Add interface to network
net.get_gateway()                   # Get gateway for L3 networks
net.get_interfaces()                # Get all interfaces on network
```

## Interface Configuration

```python
iface.set_mode('auto')             # Auto IP from subnet
iface.set_mode('manual')           # Manual IP configuration
iface.set_mode('config')           # Default config mode
iface.get_ip_addr()                # Get assigned IP
iface.get_os_interface()           # Get OS device name (e.g., "ens7")
```

## FABnet (Simplified L3 on Node)

```python
node.add_fabnet(
    name: str = "FABNET",
    net_type: str = "IPv4",    # "IPv4" or "IPv6"
    nic_type: str = "NIC_Basic",
    routes: list = None,
    subnet: ipaddress.ip_network = None,
)
```

## Routing

```python
# High-level route (preferred)
node.add_route(
    subnet: IPv4Network | IPv6Network,
    next_hop: IPv4Address | IPv6Address | NetworkService,
)

# Low-level IP configuration (for manual setup)
node.ip_addr_add(addr, subnet, interface, persistent=None)
node.ip_link_up(subnet, interface)
node.ip_route_add(subnet, gateway, interface=None, persistent=None)
```

## Sub-interfaces (VLANs)

```python
interface.add_sub_interface(
    name: str,
    vlan: str,
    bw: int = 10,  # Bandwidth in Gbps
)
```

## FABnet Subnet Constants

```python
fablib.FABNETV4_SUBNET   # IPv4Network("10.128.0.0/10")
fablib.FABNETV6_SUBNET   # IPv6Network("2602:FCFB:00::/40")
fablib.FABNETV4EXT_SUBNET  # IPv4Network("23.134.232.0/22")
```

## NIC Selection Guide

| Use Case | NIC Model | Notes |
|----------|-----------|-------|
| Basic connectivity, FABnet | `NIC_Basic` | Shared, 1 port, most common |
| High-throughput experiments | `NIC_ConnectX_6` | Dedicated, dual 100G ports |
| Legacy 25G experiments | `NIC_ConnectX_5` | Dedicated, dual 25G ports |
| 400G experiments | `NIC_ConnectX_7_400` | Dedicated, 400G |
| SmartNIC programming | `NIC_BlueField_2_ConnectX_6` | Dedicated, programmable |
| VLANs/sub-interfaces | `NIC_ConnectX_6` or `NIC_ConnectX_5` | Dedicated NICs only |

# Patterns

## L2 Bridge with Auto IP (Same Site)

```python
from ipaddress import IPv4Network

slice = fablib.new_slice(name="l2-bridge")
site = fablib.get_random_site()

subnet = IPv4Network("192.168.1.0/24")

# Create network with subnet for auto IP
net = slice.add_l2network(name="lan", subnet=subnet)

node1 = slice.add_node(name="node1", 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="node2", site=site)
iface2 = node2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface2.set_mode('auto')
net.add_interface(iface2)

slice.submit()

# Verify — IPs are auto-assigned
node2_addr = node2.get_interface(network_name="lan").get_ip_addr()
stdout, stderr = node1.execute(f"ping -c 5 {node2_addr}")
```

## L2 Point-to-Point (Cross-Site)

```python
from ipaddress import IPv4Network

slice = fablib.new_slice(name="l2-ptp")
[site1, site2] = fablib.get_random_sites(count=2)

subnet = IPv4Network("10.0.0.0/30")

net = slice.add_l2network(name="ptp-link", subnet=subnet, type="L2PTP")

node1 = slice.add_node(name="node1", site=site1)
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="node2", site=site2)
iface2 = node2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface2.set_mode('auto')
net.add_interface(iface2)

slice.submit()

# Verify
node2_addr = node2.get_interface(network_name="ptp-link").get_ip_addr()
stdout, stderr = node1.execute(f"ping -c 5 {node2_addr}")
```

## FABnet IPv4 (Cross-Site L3 — Recommended)

```python
from ipaddress import IPv4Network

slice = fablib.new_slice(name="fabnet-v4")
[site1, site2, site3] = fablib.get_random_sites(count=3)

# Create per-site L3 networks
net1 = slice.add_l3network(name="net1", type="IPv4")
net2 = slice.add_l3network(name="net2", type="IPv4")
net3 = slice.add_l3network(name="net3", type="IPv4")

# Node 1
node1 = slice.add_node(name="node1", site=site1)
iface1 = node1.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface1.set_mode('auto')
net1.add_interface(iface1)
node1.add_route(subnet=fablib.FABNETV4_SUBNET, next_hop=net1.get_gateway())

# Node 2
node2 = slice.add_node(name="node2", site=site2)
iface2 = node2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface2.set_mode('auto')
net2.add_interface(iface2)
node2.add_route(subnet=fablib.FABNETV4_SUBNET, next_hop=net2.get_gateway())

# Node 3
node3 = slice.add_node(name="node3", site=site3)
iface3 = node3.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface3.set_mode('auto')
net3.add_interface(iface3)
node3.add_route(subnet=fablib.FABNETV4_SUBNET, next_hop=net3.get_gateway())

slice.submit()

# All nodes can reach each other via FABnet
for node in slice.get_nodes():
    for net_name in ["net1", "net2", "net3"]:
        try:
            iface = node.get_interface(network_name=net_name)
            print(f"{node.get_name()} on {net_name}: {iface.get_ip_addr()}")
        except:
            pass
```

## Simplified FABnet (Using node.add_fabnet)

```python
slice = fablib.new_slice(name="simple-fabnet")

node1 = slice.add_node(name="node1", site="TACC")
node1.add_fabnet(net_type="IPv4")

node2 = slice.add_node(name="node2", site="UCSD")
node2.add_fabnet(net_type="IPv4")

slice.submit()
```

## FABNetv4Ext (Public IPs)

```python
slice = fablib.new_slice(name="public-ip")

node1 = slice.add_node(name="web-server", site="TACC", cores=4, ram=8, disk=50)
nic1 = node1.add_component(model="NIC_Basic", name="nic1")
iface1 = nic1.get_interfaces()[0]
iface1.set_mode('auto')

ext_net = slice.add_l3network(name="ext-net", type="IPv4Ext")
ext_net.add_interface(iface1)

slice.submit()

# The node gets a public IP
iface = node1.get_interface(network_name="ext-net")
print(f"Public IP: {iface.get_ip_addr()}")
```

## VLAN Sub-interfaces

```python
slice = fablib.new_slice(name="vlan-experiment")

node = slice.add_node(name="node1", site="TACC")
# Must use a dedicated NIC for VLANs
nic = node.add_component(model="NIC_ConnectX_6", name="nic1")

iface = nic.get_interfaces()[0]
sub1 = iface.add_sub_interface(name="vlan100", vlan="100", bw=10)
sub2 = iface.add_sub_interface(name="vlan200", vlan="200", bw=10)

# Connect sub-interfaces to different networks
net1 = slice.add_l2network(name="net-vlan100", interfaces=[sub1])
net2 = slice.add_l2network(name="net-vlan200", interfaces=[sub2])

slice.submit()
```

## Multi-Subnet with Static Routing

```python
from ipaddress import IPv4Network

slice = fablib.new_slice(name="multi-subnet")
site = fablib.get_random_site()

net1_subnet = IPv4Network("192.168.1.0/24")
net2_subnet = IPv4Network("192.168.2.0/24")

# Create L2 networks
net1 = slice.add_l2network(name="net1", subnet=net1_subnet)
net2 = slice.add_l2network(name="net2", subnet=net2_subnet)

# Node1 on subnet 1
node1 = slice.add_node(name="node1", site=site)
iface1 = node1.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface1.set_mode('auto')
net1.add_interface(iface1)

# Router bridging both subnets
router = slice.add_node(name="router", site=site)
r_iface1 = router.add_component(model="NIC_Basic", name="r-nic1").get_interfaces()[0]
r_iface1.set_mode('auto')
net1.add_interface(r_iface1)

r_iface2 = router.add_component(model="NIC_Basic", name="r-nic2").get_interfaces()[0]
r_iface2.set_mode('auto')
net2.add_interface(r_iface2)

# Node2 on subnet 2
node2 = slice.add_node(name="node2", site=site)
iface2 = node2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface2.set_mode('auto')
net2.add_interface(iface2)

slice.submit()

# Enable routing on router node
router.execute("sudo sysctl -w net.ipv4.ip_forward=1")

# Get auto-assigned IPs for routing
router_net1_ip = router.get_interface(network_name="net1").get_ip_addr()
router_net2_ip = router.get_interface(network_name="net2").get_ip_addr()

# Add static routes on endpoints
node1.execute(f"sudo ip route add {net2_subnet} via {router_net1_ip}")
node2.execute(f"sudo ip route add {net1_subnet} via {router_net2_ip}")

# Test end-to-end
node2_addr = node2.get_interface(network_name="net2").get_ip_addr()
stdout, stderr = node1.execute(f"ping -c 5 {node2_addr}")
```

More General & Other skills

← All General & Other skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY