Skip to content

Juniper cSRX support#3344

Merged
ipspace merged 8 commits intoipspace:devfrom
leec-666:csrx2
May 1, 2026
Merged

Juniper cSRX support#3344
ipspace merged 8 commits intoipspace:devfrom
leec-666:csrx2

Conversation

@leec-666
Copy link
Copy Markdown
Contributor

Juniper cSRX was added to ContainerLab 0.75.0 https://github.com/srl-labs/containerlab/releases/tag/v0.75.0. This PR adds support for it in Netlab.

There are limited features in cSRX e.g. it does not support routing protocols or VLANs. See https://www.juniper.net/documentation/us/en/software/csrx/csrx-consolidated-deployment-guide/topics/concept/security-csrx-docker-feature-support.html and https://www.juniper.net/documentation/us/en/software/csrx/csrx-consolidated-deployment-guide/csrx-consolidated-deployment-guide.pdf.

It might not be useful to many but I had to lab a weird NAT issue today and netlab would have sped it up so why not spend 20 times longer adding support than it took to do manually?!

Comment thread netsim/devices/csrx.yml Outdated
# cSRX default is 3 (management + 2 data interfaces)
# If more interfaces are required, this must be increased.
# Setting to a higher value than required will break interfaces (no arp etc)
CSRX_PORT_NUM: 3
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be dynamically generated by the quirk python module?
it can count the interfaces for the node and define the var for each node?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah I meant to ask about that. So the quirks file would be responsible? I'll see if I can figure it out.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 83e54f3 should do it.

I forced an error which resulted in this output:

┌──────────────────────────────────────────────────────────────────────────────────┐
│ CREATING configuration files                                                     │
└──────────────────────────────────────────────────────────────────────────────────┘
[ERRORS]  Errors found in topology.yml
[ERROR]   csrx: cSRX supports a maximum of 16 interfaces. Node fw1 has 17 interfaces.
[HINT]    Set defaults.devices.csrx.warnings.csrx_port_num to False to disable this check
[FATAL]   Cannot proceed beyond this point due to errors, exiting

Can the hint be disabled? This check should not ever be disabled.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to have a hard (= cannot be disabled) error, use log.error and set module to csrx (device type). See "requires_plugin" in "devices/_common.py" (that one uses module=node.device because it's a generic thing that works for any device)

@ipspace
Copy link
Copy Markdown
Owner

ipspace commented Apr 29, 2026

Starting with a naive question: is this beast different enough that we need a different device (and not just vSRX with provider=clab)?

@leec-666
Copy link
Copy Markdown
Contributor Author

leec-666 commented Apr 30, 2026

Aside from feature support, there are some other annoying differences:

  • Username and password are different which means vsrx.clab would need to change
  • The initial config deployment fails because the junos template does not use interface units and includes LLDP. Both cases would need to be handled.

I found it simpler to make it a new device with a couple of new templates, and not inherit from vSRX or Junos and list the features it does support rather than adding overrides for those it doesn't. This means if a user attempts to use the ospf module for example (what documentation?), lab startup will fail immediately informing them as such instead of waiting for the module to run and fail with config syntax errors.

Copy link
Copy Markdown
Owner

@ipspace ipspace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tons of minor details, but overall a great job! Thank you!

Comment thread docs/caveats.md Outdated
Comment thread docs/caveats.md Outdated
Comment thread docs/platforms.md Outdated
Comment thread docs/platforms.md Outdated
Comment thread docs/platforms.md Outdated
Comment thread netsim/ansible/templates/routing/csrx.j2
Comment thread netsim/devices/csrx.py Outdated
Comment thread netsim/devices/csrx.py Outdated
Comment thread netsim/devices/csrx.yml Outdated
mgmt_if: fxp0
ifindex_offset: 0
interface_name: ge-0/0/{ifindex}
loopback_interface_name: "" # Unsupported on cSRX
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you're not inheriting from Junos -- if the loopback is not supported, then don't define this attribute (see asav.yml)

Comment thread netsim/devices/csrx.yml
netlab_show_command: [ cli, -c, 'show $@' ]
netlab_check_command: who
netlab_ready: [ ssh ]
netlab_default_shebang: '#!/config/netlab/netlab-config.sh'
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to use this or should we just use NETCONF to configure it? Or is NETCONF not working?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I based it on cRPD. I thought the connection/deployment methods other than shell scripts relied on Ansible which I know you're not the biggest fan of.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the connection/deployment methods other than shell scripts relied on Ansible

  • Configuration deployment: YES
  • Connecting to the device: NO

which I know you're not the biggest fan of.

You're right ;) However, we need Ansible anyway to deploy configurations on other Junos devices, but admittedly the script-based configuration is faster. I'm OK with either one, just don't make it too complicated just to have a bash script.

@ipspace
Copy link
Copy Markdown
Owner

ipspace commented Apr 30, 2026

Username and password are different which means vsrx.clab would need to change

My bad. I should have checked whether we already have vSRX on clab (and we do). This is clearly not the same (or would require tons of tweaks), so a new device is absolutely warranted.

I found it simpler to make it a new device with a couple of new templates, and not inherit from vSRX or Junos and list the features it does support rather than adding overrides for those it doesn't.

Yeah, listing everything that DOES NOT work would be totally annoying.

@ipspace
Copy link
Copy Markdown
Owner

ipspace commented May 1, 2026

NIce job. This looks ready-to-merge to me (any thoughts @ssasso?). Just a minor detail that I can't check myself: as you map /etc/hosts into the container, do you need to include 'junos/hosts.j2' into the initial config?

@leec-666
Copy link
Copy Markdown
Contributor Author

leec-666 commented May 1, 2026

and I'm not sure if it's worth noting but if you ping an ipv4 address from a cSRX device, the replies are duplicated somewhere inside the host

root@fw1> ping r1    
PING r1 (10.0.0.3) 56(84) bytes of data.
64 bytes from r1 (10.0.0.3): icmp_seq=1 ttl=64 time=1.32 ms
64 bytes from r1 (10.0.0.3): icmp_seq=1 ttl=64 time=1.49 ms (DUP!)
64 bytes from r1 (10.0.0.3): icmp_seq=2 ttl=64 time=1.13 ms
64 bytes from r1 (10.0.0.3): icmp_seq=2 ttl=64 time=1.25 ms (DUP!)
^C[abort]


No duplicate response seen in capture:

lee@nsyt-x-test-containerlab-1:~/netlab/csrx$ netlab capture fw1 eth2 icmp
Starting packet capture on fw1/eth2: sudo ip netns exec clab-csrx-fw1 tcpdump -i eth2 --immediate-mode -l -vv icmp
tcpdump: listening on eth2, link-type EN10MB (Ethernet), snapshot length 262144 bytes
06:25:37.849146 IP (tos 0x0, ttl 64, id 54769, offset 0, flags [DF], proto ICMP (1), length 84)
    10.1.0.9 > 10.0.0.3: ICMP echo request, id 53, seq 1, length 64
06:25:37.849192 IP (tos 0x0, ttl 64, id 9087, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.0.3 > 10.1.0.9: ICMP echo reply, id 53, seq 1, length 64
06:25:38.849995 IP (tos 0x0, ttl 64, id 55654, offset 0, flags [DF], proto ICMP (1), length 84)
    10.1.0.9 > 10.0.0.3: ICMP echo request, id 53, seq 2, length 64
06:25:38.850037 IP (tos 0x0, ttl 64, id 9386, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.0.3 > 10.1.0.9: ICMP echo reply, id 53, seq 2, length 64

@ipspace
Copy link
Copy Markdown
Owner

ipspace commented May 1, 2026

and I'm not sure if it's worth noting but if you ping an ipv4 address from a cSRX device, the replies are duplicated somewhere inside the host. No duplicate response seen in capture:

If I got it right: a single ICMP reply comes to the Ethernet interface of cSRX, and then cSRX magically produces two copies of it? If that's the case, leave it to Juniper to sort it out ;))

@leec-666
Copy link
Copy Markdown
Contributor Author

leec-666 commented May 1, 2026

yeah, maybe it's too echoey inside the container because of all the missing furniture features

Copy link
Copy Markdown
Owner

@ipspace ipspace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to merge to me ;)

@ipspace ipspace merged commit 5858755 into ipspace:dev May 1, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants