Skip to content

Conversation

@benoit-nexthop
Copy link
Contributor

@benoit-nexthop benoit-nexthop commented Feb 3, 2026

Pre-submission checklist

  • I've ran the linters locally and fixed lint errors related to the files I modified in this PR. You can install the linters by running pip install -r requirements-dev.txt && pre-commit install
  • pre-commit run

Summary

Implements two new fboss2-dev CLI commands for switch configuration.

1. config vlan port taggingMode

Configures the VLAN tagging mode for a port within a VLAN. This controls whether packets are tagged or untagged when egressing the port. Where <mode> can be:

  • tagged - Packets egress with VLAN tag
  • untagged - Packets egress without VLAN tag

This is a hitless configuration change (no agent restart required).

2. config l2 learning-mode

Configures the L2 learning mode (l2LearningMode in SwitchSettings). This controls how the switch learns MAC addresses. Where <mode> can be:

  • hardware - MAC learning is performed by the hardware ASIC
  • software - MAC learning is performed by the software agent
  • disabled - MAC learning is disabled

Note: Changing L2 learning mode requires an agent restart (not hitless) because the FBOSS agent does not permit changing this setting after initial config application.

Note: this change is part of a series, the previous one is #893, the next one is #900.
This change was originally developed by @manoharan-nexthop

Test Plan

Unit tests

  • config vlan port taggingMode (15 test cases): Argument validation, mode conversion, error handling
  • config l2 learning-mode (14 test cases): Argument validation, mode conversion, error handling

End-to-end tests

config vlan port taggingMode:

============================================================
CLI E2E Test: config vlan <id> port <port> taggingMode
============================================================

[Step 1] Finding an interface to test...
  Using CLI from FBOSS_CLI_PATH: /home/admin/manoharan/fboss2-dev
[CLI] Running: show interface
[CLI] Completed in 0.08s: show interface
  Using interface: eth1/1/1 (VLAN: 2001)

[Step 2] Getting current tagging mode...
[CLI] Running: show running-config
[CLI] Completed in 0.07s: show running-config
  Current mode: untagged

[Step 3] Setting tagging mode to 'tagged'...
[CLI] Running: config vlan 2001 port eth1/1/1 taggingMode tagged
[CLI] Completed in 0.08s: config vlan 2001 port eth1/1/1 taggingMode tagged
[CLI] Running: config session commit
[CLI] Completed in 0.16s: config session commit
  Tagging mode set to 'tagged'

[Step 4] Verifying tagging mode is 'tagged'...
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Verified: Tagging mode is 'tagged'

[Step 5] Setting tagging mode to 'untagged'...
[CLI] Running: config vlan 2001 port eth1/1/1 taggingMode untagged
[CLI] Completed in 0.08s: config vlan 2001 port eth1/1/1 taggingMode untagged
[CLI] Running: config session commit
[CLI] Completed in 0.15s: config session commit
  Tagging mode set to 'untagged'

[Step 6] Verifying tagging mode is 'untagged'...
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Verified: Tagging mode is 'untagged'

============================================================
TEST PASSED
============================================================

config l2 learning-mode:

============================================================
CLI E2E Test: config l2 learning-mode <mode>
============================================================

[Step 1] Getting current L2 learning mode...
  Using CLI from FBOSS_CLI_PATH: /home/admin/manoharan/fboss2-dev
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Current mode: hardware

[Step 2] Setting L2 learning mode to 'software'...
[CLI] Running: config l2 learning-mode software
[CLI] Completed in 0.07s: config l2 learning-mode software
[CLI] Running: config session commit
[CLI] Completed in 2.88s: config session commit
  Waiting for agent to be ready after restart...
  Sleeping 30s for agent restart...
  L2 learning mode set to 'software'

[Step 3] Verifying L2 learning mode is 'software'...
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Verified: L2 learning mode is 'software'

[Step 4] Setting L2 learning mode to 'hardware'...
[CLI] Running: config l2 learning-mode hardware
[CLI] Completed in 0.08s: config l2 learning-mode hardware
[CLI] Running: config session commit
[CLI] Completed in 3.51s: config session commit
  Waiting for agent to be ready after restart...
  Sleeping 30s for agent restart...
  L2 learning mode set to 'hardware'

[Step 5] Verifying L2 learning mode is 'hardware'...
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Verified: L2 learning mode is 'hardware'

============================================================
TEST PASSED
============================================================

Sample usage

CLI: Add DSCP, EXP, and DOT1P map configuration commands

Summary

Add CLI commands to configure the dscpMaps, expMaps, and pcpMaps
attributes of the QosMap object within a QosPolicy. These commands
allow configuring bidirectional mappings between codepoint values
and internal traffic classes.

New CLI commands:

  • DSCP maps (RFC 2474, values 0-63):
    • config qos policy <name> map dscp <value> traffic-class <tc>
    • config qos policy <name> map traffic-class <tc> dscp <value>
  • MPLS EXP maps (RFC 3032/5462, values 0-7):
    • config qos policy <name> map mpls-exp <value> traffic-class <tc>
    • config qos policy <name> map traffic-class <tc> mpls-exp <value>
  • DOT1P/PCP maps (802.1Q, values 0-7):
    • config qos policy <name> map dot1p <value> traffic-class <tc>
    • config qos policy <name> map traffic-class <tc> dot1p <value>

The first command in each pair is additive (ingress classification -
multiple codepoints can map to the same traffic class), while the
second is not additive (egress rewrite - one traffic class maps to
one codepoint value).

Test Plan

New end to end tests:

Note: Google Test filter = *ConfigQosPolicyMapTest*
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from ConfigQosPolicyMapTest
[ RUN      ] ConfigQosPolicyMapTest.CreateSamplePolicy
I0204 18:36:53.719844 63663 CliTest.cpp:35] CliTest::SetUp - starting CLI test
I0204 18:36:53.719979 63663 ConfigQosPolicyMapTest.cpp:63] Using test policy name: cli_e2e_test_qos_policy_1770259013719
I0204 18:36:53.719994 63663 ConfigQosPolicyMapTest.cpp:229] ========================================
I0204 18:36:53.719999 63663 ConfigQosPolicyMapTest.cpp:230] ConfigQosPolicyMapTest::CreateSamplePolicy
I0204 18:36:53.720004 63663 ConfigQosPolicyMapTest.cpp:231] ========================================
I0204 18:36:53.720008 63663 ConfigQosPolicyMapTest.cpp:242] [Step 1] Configuring DOT1P/PCP maps...
I0204 18:36:53.720016 63663 CliTest.cpp:118] Running CLI command: config qos policy cli_e2e_test_qos_policy_1770259013719 map dot1p 0 traffic-class 0
I0204 18:36:53.761480 63663 ConfigQosPolicyMapTest.cpp:102] Command: dot1p 0 traffic-class 0
I0204 18:36:53.761503 63663 ConfigQosPolicyMapTest.cpp:104] stdout: {"localhost":"Successfully set QoS policy 'cli_e2e_test_qos_policy_1770259013719' pcpMaps.fromPcpToTrafficClass [tc=0] = 0"}
[... additional map configuration commands ...]
I0204 18:36:53.985447 63663 ConfigQosPolicyMapTest.cpp:276]   DOT1P maps configured
I0204 18:36:53.985452 63663 ConfigQosPolicyMapTest.cpp:279] [Step 2] Configuring traffic-class-to-queue mappings...
I0204 18:36:53.985462 63663 CliTest.cpp:118] Running CLI command: config qos policy cli_e2e_test_qos_policy_1770259013719 map tc-to-queue 0 0
I0204 18:36:54.002140 63663 ConfigQosPolicyMapTest.cpp:128] Command: tc-to-queue 0 0
I0204 18:36:54.002164 63663 ConfigQosPolicyMapTest.cpp:129] stdout: {"localhost":"Successfully set QoS policy 'cli_e2e_test_qos_policy_1770259013719' trafficClassToQueueId [0] = 0"}
[... additional tc-to-queue commands ...]
I0204 18:36:54.091056 63663 ConfigQosPolicyMapTest.cpp:286]   TC-to-queue mappings configured
I0204 18:36:54.091071 63663 ConfigQosPolicyMapTest.cpp:289] [Step 3] Committing config...
I0204 18:36:54.091084 63663 CliTest.cpp:118] Running CLI command: config session commit
I0204 18:36:54.316841 63663 ConfigQosPolicyMapTest.cpp:291]   Config committed
I0204 18:36:54.316868 63663 ConfigQosPolicyMapTest.cpp:294] [Step 4] Verifying config was applied...
I0204 18:36:54.326264 63663 ConfigQosPolicyMapTest.cpp:297]   Got running config from agent
I0204 18:36:54.326306 63663 ConfigQosPolicyMapTest.cpp:303]   Found test policy in running config
I0204 18:36:54.326319 63663 ConfigQosPolicyMapTest.cpp:314]   Verified pcpMaps has 6 entries
I0204 18:36:54.326344 63663 ConfigQosPolicyMapTest.cpp:329]   All pcpMap entries verified
I0204 18:36:54.326363 63663 ConfigQosPolicyMapTest.cpp:347]   trafficClassToQueueId verified
I0204 18:36:54.326374 63663 ConfigQosPolicyMapTest.cpp:349] TEST PASSED
[       OK ] ConfigQosPolicyMapTest.CreateSamplePolicy (607 ms)
[----------] 1 test from ConfigQosPolicyMapTest (607 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (607 ms total)
[  PASSED  ] 1 test.

Sample usage

[admin@fboss101 ~]$ fboss2-dev config vlan 2001 port eth1/1/1 taggingMode untagged
Successfully set tagging mode for port 'eth1/1/1' in VLAN 2001 to 'untagged'

[admin@fboss101 ~]$ fboss2-dev config l2 learning-mode software
Successfully set L2 learning mode to 'software'

[admin@fboss101 ~]$ fboss2-dev config session commit
wedge_agent restarted, config committed

manoharan-nexthop and others added 14 commits January 28, 2026 18:12
1. Some of the configuration commands like QoS buffer pool modification
requires an agent restart and some are hitless. Inorder to take
appropriate action during the commit, track the highest impact action by
storing the same in `$HOME/.fboss2/action_level` at the end of each
configuration change. The proposed change only prints a warning if the
action needs to be taken. Later this can be modified to perform the
action automatically

2. Add QoS buffer pool configuration commands
```
- fboss2 config qos buffer-pool <name> shared-bytes <value>
- fboss2 config qos buffer-pool <name> headroom-bytes <value>
- fboss2 config qos buffer-pool <name> reserved-bytes <value>
```

1. Updated existing UT for action information
2. Added new tests for QoS buffer bool configurations.

```
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos buffer-pool testpool headroom-bytes 1024
Successfully set headroom-bytes for buffer-pool 'testpool' to 1024
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config session diff
--- current live config
+++ session config
@@ -121,6 +121,12 @@
     "arpAgerInterval": 5,
     "arpRefreshSeconds": 20,
     "arpTimeoutSeconds": 60,
+    "bufferPoolConfigs": {
+      "testpool": {
+        "headroomBytes": 1024,
+        "sharedBytes": 0
+      }
+    },
     "clientIdToAdminDistance": {
       "0": 20,
       "1": 1,
[admin@fboss101 ~]$ ll ~/.fboss2
total 216
-rw-r--r-- 1 admin admin 213283 Jan 13 05:15 agent.conf
-rw-r--r-- 1 admin admin     42 Jan 13 05:15 conf_metadata.json
[admin@fboss101 ~]$ cat ~/.fboss2/conf_metadata.json
{
  "action": {
    "WEDGE_AGENT": "AGENT_RESTART"
  }
}
```
…mand.

This doesn't yet automatically create the VLAN if it doesn't exist.
A recent merge introduced a duplicate command by mistake (bad merge on
my part) and this escaped because of lack of test coverage.

Also make sure we keep `cmake/CliFboss2Test.cmake` sorted.
Now every config command is saved in the CLI session metadata so we can
easily tell what commands were used in a given session. The metadata is
now also saved along the config when we commit the session. A future
commit will make rollback also rely on this metadata to decide whether
or not to restart the agent.
Replace the basic file-based configuration versioning mechanism with
Git-based versioning for the CLI config session.

Key changes:

- Add new Git class (Git.h/cpp) providing a simple interface for Git
  operations: init, commit, log, show, resolveRef, getHead, hasCommits
- Use folly::Subprocess with full path /usr/bin/git for all Git commands
- Replace revision files (agent-rN.conf + symlink) with atomic writes
  to agent.conf tracked in a local Git repository
- Use Git commit SHAs as revision identifiers instead of rN format
- Update RevisionList validation to accept Git SHAs (7+ hex chars)

Repository initialization:
- Automatically initialize Git repo if it doesn't exist
- Automatically create initial commit if repo has no commits but
  config file exists
- Use --shared=group flag and umask 0002 to ensure .git directory
  is group-writable when /etc/coop is group-writable

Commands updated:
- config history: Shows Git commit log with SHA, author, timestamp, message
- config session diff: Uses git show to compare commits
- config session commit: Creates Git commits with username as author
- config rollback: Reads config from Git history and creates new commit

Test updates:
- Update all CLI config tests to use Git-based setup
- Initialize Git repo and create initial commit in test fixtures
…esolution

When multiple users have concurrent config sessions, the first user to
commit succeeds, but subsequent users get an error because their session
is based on a stale commit. Previously, whoever committed last would
overwrite changes of other users that committed before them.

This commit adds a `config session rebase` command that:
1. Takes the diff between the config as of the base commit and the
session
2. Re-applies this diff on top of the current HEAD (similar to git
rebase)
3. Uses a recursive 3-way merge algorithm for JSON objects
4. Detects and reports conflicts at specific JSON paths
5. Updates the session's base to the current HEAD on success

The 3-way merge algorithm handles:
- Objects: recursively merges each key
- Arrays: element-by-element merge if sizes match
- Scalars: conflict if both head and session changed differently from
base

Add unit tests covering:
- Successful rebase with non-conflicting changes
- Rebase failure when changes conflict
- Rebase not needed when session is already up-to-date

NOS-3962 #done
Add new fboss2-dev CLI commands for managing static MAC address entries
on VLANs:
 - `config vlan <vlan-id> static-mac add <mac-address> <port-id>`
 - `config vlan <vlan-id> static-mac delete <mac-address>`

These commands allow operators to configure static MAC address entries
in the FBOSS switch configuration, which is useful for scenarios where
MAC addresses need to be pinned to specific ports.

Features:
* VLAN ID validation (1-4094 range)
* MAC address format validation
* Port existence validation with automatic logical ID resolution
* Duplicate entry detection for add operations
* Integration with ConfigSession for proper config management

Unit Tests:
```
   ./fboss/oss/scripts/nhfboss-test.sh --timeout 30 --retry 0 --filter 'CmdConfigVlanStaticMac'

   Output:
   [==========] Running 33 tests from 1 test suite.
   ...
   [  PASSED  ] 33 tests.
```

Manual CLI Testing:
```
$ fboss2-dev config vlan 2001 static-mac add 02:00:00:E2:E2:01 eth1/1/1
Successfully added static MAC entry: MAC 02:00:00:E2:E2:01 -> VLAN 2001, Port eth1/1/1 (ID 9)
$ fboss2-dev config session commit
Config session committed successfully as r77 and config reloaded.
$ fboss2-dev config vlan 2001 static-mac delete 02:00:00:E2:E2:01
Successfully deleted static MAC entry: MAC 02:00:00:E2:E2:01 from VLAN 2001
```
Add a new fboss2 show command that retrieves the running configuration
from the agent via the `getRunningConfig()` Thrift API and displays it
as nicely formatted JSON.

This is useful when the config file on disk is missing or out of sync
with the running agent configuration.

# Test Plan

Added unit test CmdShowRunningConfigTest that mocks the getRunningConfig
thrift API.

## Sample usage

```
[admin@fboss101 ~]$ fboss2 show running-config
{
  "sw": {
    "version": 0,
    "ports": [
      {
        "logicalID": 1,
        "speed": "HUNDREDG",
        "name": "eth1/1/1",
        ...
      }
    ],
    ...
  }
}
```

NOS-4057 #done
Implements new fboss2-dev CLI commands for configuring PFC priority
group policies (`portPgConfigs` in `SwitchConfig`). This allows
configuring per-port priority group settings for traffic prioritization
and buffer management.

New command: `config qos priority-group-policy <policy-name> group-id <id> <attr> <value> [<attr> <value> ...]`

Where <attr> can be:
- `min-limit-bytes`
- `headroom-limit-bytes`
- `resume-offset-bytes`
- `static-limit-bytes`
- `scaling-factor` (accepts `MMUScalingFactor` enum values like `ONE_HALF`, `TWO`, etc)
- `buffer-pool-name`

Multiple attributes can be set in a single command, or one at a time.
The implementation doesn't declare the sub-subcommands in a conventional
way in order to avoid an explosion of `.h` / `.cpp` pairs.

Also updates `ConfigSession::restartAgent()` to use `sudo` for `systemctl restart`
since the CLI may be run by non-root users.

New end to end tests:
```
======================================================================
CLI E2E Test: PFC Configuration
======================================================================

[Step 0] Cleaning up any existing test config...
  Copying system config to session config...
  Removing PFC-related configs...
  Updating metadata for AGENT_RESTART...
  Committing cleanup...
  Using CLI from FBOSS_CLI_PATH: /home/admin/benoit/fboss2-dev
[CLI] Running: config session commit
[CLI] Completed in 4.90s: config session commit
  Cleanup complete

[Step 1] Configuring buffer pool 'cli_e2e_test_buffer_pool'...
[CLI] Running: config qos buffer-pool cli_e2e_test_buffer_pool shared-bytes 78773528
[CLI] Completed in 0.08s: config qos buffer-pool cli_e2e_test_buffer_pool shared-bytes 78773528
[CLI] Running: config qos buffer-pool cli_e2e_test_buffer_pool headroom-bytes 4405376
[CLI] Completed in 0.07s: config qos buffer-pool cli_e2e_test_buffer_pool headroom-bytes 4405376
  Buffer pool configured

[Step 2] Configuring priority group policy 'cli_e2e_test_pg_policy'...
  Using single-attribute commands for group-ids 2 and 6...
  Configuring group-id 2 (one attribute at a time)...
[CLI] Running: config qos priority-group-policy cli_e2e_test_pg_policy group-id 2 min-limit-bytes 14478
[CLI] Completed in 0.08s: config qos priority-group-policy cli_e2e_test_pg_policy group-id 2 min-limit-bytes 14478
...
  Using multi-attribute commands for group-ids 0 and 7...
  Configuring group-id 0 (all attributes at once)...
[CLI] Running: config qos priority-group-policy cli_e2e_test_pg_policy group-id 0 min-limit-bytes 4826 headroom-limit-bytes 0 resume-offset-bytes 9652 scaling-factor TWO buffer-pool-name cli_e2e_test_buffer_pool
[CLI] Completed in 0.08s: config qos priority-group-policy cli_e2e_test_pg_policy group-id 0 min-limit-bytes 4826 headroom-limit-bytes 0 resume-offset-bytes 9652 scaling-factor TWO buffer-pool-name cli_e2e_test_buffer_pool
  Configuring group-id 7 (all attributes at once)...
[CLI] Running: config qos priority-group-policy cli_e2e_test_pg_policy group-id 7 min-limit-bytes 4826 headroom-limit-bytes 0 resume-offset-bytes 9652 scaling-factor TWO buffer-pool-name cli_e2e_test_buffer_pool
[CLI] Completed in 0.07s: config qos priority-group-policy cli_e2e_test_pg_policy group-id 7 min-limit-bytes 4826 headroom-limit-bytes 0 resume-offset-bytes 9652 scaling-factor TWO buffer-pool-name cli_e2e_test_buffer_pool
  All priority groups configured

[Step 3] Committing configuration...
[CLI] Running: config session commit
[CLI] Completed in 15.55s: config session commit
  Configuration committed successfully

[Step 4] Verifying configuration...
  Buffer pool 'cli_e2e_test_buffer_pool' verified
  Priority group policy 'cli_e2e_test_pg_policy' verified

======================================================================
TEST PASSED
======================================================================

[Step 5] Cleaning up test config...
  Copying system config to session config...
  Removing PFC-related configs...
  Updating metadata for AGENT_RESTART...
  Committing cleanup...
[CLI] Running: config session commit
[CLI] Completed in 6.67s: config session commit
  Cleanup complete
```

```
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos buffer-pool sample_buffer_pool shared-bytes 78773528
Successfully set shared-bytes for buffer-pool 'sample_buffer_pool' to 78773528
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos buffer-pool sample_buffer_pool headroom-bytes 4405376
Successfully set headroom-bytes for buffer-pool 'sample_buffer_pool' to 4405376
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos priority-group-policy sample_pg_policy group-id 2 min-limit-bytes 14478 headroom-limit-bytes 726440 resume-offset-bytes 9652 scaling-factor ONE_HALF buffer-pool-name sample_buffer_pool
Successfully configured priority-group-policy 'sample_pg_policy' group-id 2
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config session diff
--- current live config
+++ session config
@@ -121,6 +121,12 @@
     "arpAgerInterval": 5,
     "arpRefreshSeconds": 20,
     "arpTimeoutSeconds": 60,
+    "bufferPoolConfigs": {
+      "sample_buffer_pool": {
+        "headroomBytes": 4405376,
+        "sharedBytes": 78773528
+      }
+    },
     "clientIdToAdminDistance": {
       "0": 20,
       "1": 1,
@@ -2196,6 +2202,19 @@
     "maxNeighborProbes": 300,
     "mirrorOnDropReports": [],
     "mirrors": [],
+    "portPgConfigs": {
+      "sample_pg_policy": [
+        {
+          "bufferPoolName": "sample_buffer_pool",
+          "headroomLimitBytes": 726440,
+          "id": 2,
+          "minLimitBytes": 14478,
+          "name": "pg2",
+          "resumeOffsetBytes": 9652,
+          "sramScalingFactor": 8
+        }
+      ]
+    },
     "portQueueConfigs": {},
     "ports": [
       {
```
# Summary

Implements new fboss2-dev CLI commands for configuring PFC (Priority
Flow Control) settings on individual interfaces. This allows
enabling/disabling PFC, setting watchdog parameters, and associating
priority group policies with ports.

The command uses a key-value pair syntax that allows setting multiple
attributes in a single command:

```
config interface <port> pfc-config <attr> <value> [<attr> <value> ...]
```

Valid attributes:
- `tx enabled|disabled` - Enable/disable PFC transmission
- `rx enabled|disabled` - Enable/disable PFC reception
- `tx-duration enabled|disabled` - Enable/disable TX duration
- `rx-duration enabled|disabled` - Enable/disable RX duration
- `priority-group-policy <name>` - Set priority group policy
- `watchdog-detection-time <ms>` - Set watchdog detection time
- `watchdog-recovery-time <ms>` - Set watchdog recovery time
- `watchdog-recovery-action drop|no-drop` - Set watchdog recovery action

# Test Plan

End-to-end tests on fboss101:
```
======================================================================
CLI E2E Test: PFC Configuration
======================================================================

[Step 0] Cleaning up any existing test config...
[...]
  Cleanup complete

[Step 1] Configuring buffer pool 'cli_e2e_test_buffer_pool'...
[...]
  Buffer pool configured

[Step 2] Configuring priority group policy 'cli_e2e_test_pg_policy'...
[...]
  All priority groups configured

[Step 3] Configuring PFC on port 'eth1/1/1'...
  Using single-attribute commands for tx, rx, priority-group-policy...
[CLI] Running: config interface eth1/1/1 pfc-config tx enabled
[CLI] Completed in 0.07s: config interface eth1/1/1 pfc-config tx enabled
[CLI] Running: config interface eth1/1/1 pfc-config rx enabled
[CLI] Completed in 0.06s: config interface eth1/1/1 pfc-config rx enabled
[CLI] Running: config interface eth1/1/1 pfc-config priority-group-policy cli_e2e_test_pg_policy
[CLI] Completed in 0.06s: config interface eth1/1/1 pfc-config priority-group-policy cli_e2e_test_pg_policy
  Using multi-attribute command for all watchdog settings...
[CLI] Running: config interface eth1/1/1 pfc-config watchdog-detection-time 150 watchdog-recovery-time 1000 watchdog-recovery-action no-drop
[CLI] Completed in 0.06s: config interface eth1/1/1 pfc-config watchdog-detection-time 150 watchdog-recovery-time 1000 watchdog-recovery-action no-drop
  Port PFC configured

[Step 4] Committing configuration...
[CLI] Running: config session commit
[CLI] Completed in 11.84s: config session commit
  Configuration committed successfully

[Step 5] Verifying configuration...
  Buffer pool 'cli_e2e_test_buffer_pool' verified
  Priority group policy 'cli_e2e_test_pg_policy' verified
  Port 'eth1/1/1' PFC config verified

======================================================================
TEST PASSED
======================================================================

[Step 6] Cleaning up test config...
[...]
  Cleanup complete
```

## Sample usage

Setting multiple attributes at once:
```
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config interface eth1/1/1 pfc-config tx enabled rx enabled priority-group-policy sample_pg_policy
Successfully configured PFC for interface(s) eth1/1/1

[admin@fboss101 ~]$ ~/benoit/fboss2-dev config interface eth1/1/1 pfc-config watchdog-detection-time 150 watchdog-recovery-time 1000 watchdog-recovery-action no-drop
Successfully configured PFC for interface(s) eth1/1/1

[admin@fboss101 ~]$ ~/benoit/fboss2-dev config session diff
--- current live config
+++ session config
@@ -2218,6 +2218,16 @@
           "rx": false,
           "tx": false
         },
+        "pfc": {
+          "portPgConfigName": "sample_pg_policy",
+          "rx": true,
+          "tx": true,
+          "watchdog": {
+            "detectionTimeMsecs": 150,
+            "recoveryAction": 0,
+            "recoveryTimeMsecs": 1000
+          }
+        },
         "portType": 0,
         "profileID": 39,
         "queues_DEPRECATED": [],
```
# Summary

Implements new fboss2-dev CLI commands for configuring port queue
configs (PortQueue) under queuing policies. This allows setting queue
scheduling, weights, buffer sizes, and other queue-related parameters.

New commands:
- `config qos queuing-policy <name> queue-id <id> scheduling <WRR|SP|DRR>`
- `config qos queuing-policy <name> queue-id <id> weight <weight>`
- `config qos queuing-policy <name> queue-id <id> shared-bytes <bytes>`
- `config qos queuing-policy <name> queue-id <id> reserved-bytes <bytes>`
- `config qos queuing-policy <name> queue-id <id> scaling-factor <factor>`
- `config qos queuing-policy <name> queue-id <id> buffer-pool-name <name>`

# Test Plan

New end to end tests:
```
======================================================================
CLI E2E Test: Port Queue Configuration
======================================================================

[Step 0] Cleaning up any existing test config...
  Copying system config to session config...
  Removing port queue configs...
  Updating metadata for AGENT_RESTART...
  Committing cleanup...
  Using CLI from FBOSS_CLI_PATH: /home/admin/benoit/fboss2-dev
[CLI] Running: config session commit
[CLI] Completed in 4.77s: config session commit
  Cleanup complete

[Step 1] Configuring buffer pool 'cli_e2e_test_buffer_pool'...
[CLI] Running: config qos buffer-pool cli_e2e_test_buffer_pool shared-bytes 78773528
[CLI] Completed in 0.07s: config qos buffer-pool cli_e2e_test_buffer_pool shared-bytes 78773528
[CLI] Running: config qos buffer-pool cli_e2e_test_buffer_pool headroom-bytes 4405376
[CLI] Completed in 0.06s: config qos buffer-pool cli_e2e_test_buffer_pool headroom-bytes 4405376
  Buffer pool configured

[Step 2] Configuring queuing policy 'cli_e2e_test_queue_policy'...
  Configuring queue-id 2...
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 2 scheduling SP
[CLI] Completed in 0.07s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 2 scheduling SP
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 2 weight 10
[CLI] Completed in 0.07s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 2 weight 10
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 2 shared-bytes 83618832
[CLI] Completed in 0.07s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 2 shared-bytes 83618832
  Configuring queue-id 6...
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 6 scheduling SP
[CLI] Completed in 0.07s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 6 scheduling SP
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 6 shared-bytes 83618832
[CLI] Completed in 0.07s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 6 shared-bytes 83618832
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 6 scaling-factor TWO
[CLI] Completed in 0.08s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 6 scaling-factor TWO
  Configuring queue-id 7...
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 7 scheduling WRR
[CLI] Completed in 0.08s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 7 scheduling WRR
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 7 weight 20
[CLI] Completed in 0.07s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 7 weight 20
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 7 reserved-bytes 5000
[CLI] Completed in 0.06s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 7 reserved-bytes 5000
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 7 buffer-pool-name cli_e2e_test_buffer_pool
[CLI] Completed in 0.07s: config qos queuing-policy cli_e2e_test_queue_policy queue-id 7 buffer-pool-name cli_e2e_test_buffer_pool
  All queues configured

[Step 3] Committing configuration...
[CLI] Running: config session commit
[CLI] Completed in 15.79s: config session commit
  Configuration committed successfully

[Step 4] Verifying configuration...
  Buffer pool 'cli_e2e_test_buffer_pool' verified
  Queuing policy 'cli_e2e_test_queue_policy' verified

======================================================================
TEST PASSED
======================================================================

[Step 5] Cleaning up test config...
  Copying system config to session config...
  Removing port queue configs...
  Updating metadata for AGENT_RESTART...
  Committing cleanup...
[CLI] Running: config session commit
[CLI] Completed in 6.37s: config session commit
  Cleanup complete
```

## Sample usage

```
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos queuing-policy test-queue queue-id 0 scheduling SP
Successfully set scheduling for queuing-policy 'test-queue' queue-id 0 to SP
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos queuing-policy test-queue queue-id 0 weight 10
Successfully set weight for queuing-policy 'test-queue' queue-id 0 to 10
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos queuing-policy test-queue queue-id 0 shared-bytes 83618832
Successfully set shared-bytes for queuing-policy 'test-queue' queue-id 0 to 83618832
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos queuing-policy test-queue queue-id 0 reserved-bytes 5000
Successfully set reserved-bytes for queuing-policy 'test-queue' queue-id 0 to 5000
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos queuing-policy test-queue queue-id 0 scaling-factor TWO
Successfully set scaling-factor for queuing-policy 'test-queue' queue-id 0 to TWO
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config qos queuing-policy test-queue queue-id 0 buffer-pool-name ingress_pool
Successfully set buffer-pool-name for queuing-policy 'test-queue' queue-id 0 to ingress_pool
[admin@fboss101 ~]$ ~/benoit/fboss2-dev config session diff
--- current live config
+++ session config
@@ -2197,7 +2197,20 @@
     "maxNeighborProbes": 300,
     "mirrorOnDropReports": [],
     "mirrors": [],
-    "portQueueConfigs": {},
+    "portQueueConfigs": {
+      "test-queue": [
+        {
+          "bufferPoolName": "ingress_pool",
+          "id": 0,
+          "reservedBytes": 5000,
+          "scalingFactor": 9,
+          "scheduling": 1,
+          "sharedBytes": 83618832,
+          "streamType": 0,
+          "weight": 10
+        }
+      ]
+    },
     "ports": [
       {
         "conditionalEntropyRehash": false,
```
# Summary

This adds support for configuring Active Queue Management (AQM) attributes
on port queues via the CLI. The AQM configuration includes:
- congestion-behavior: `ECN` or `EARLY_DROP`
- detection linear: with minimum-length, maximum-length, and probability

The active-queue-management keyword must come last in the command as it
consumes all remaining arguments for its nested sub-attributes.

# Test Plan

End-to-end test output (new test case with queue-id 4 with AQM):

```
[...]
  Configuring queue-id 4...
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 4 scheduling SP shared-bytes 83618832 active-queue-management congestion-behavior ECN detection linear minimum-length 120000 maximum-length 120000 probability 100

======================================================================
TEST PASSED
======================================================================
```

## Sample usage

```
$ fboss2 config qos queuing-policy test_policy queue-id 5 scheduling sp \
    active-queue-management congestion-behavior ecn \
    detection linear minimum-length 120000 maximum-length 120000 probability 100
Successfully configured queuing-policy 'test_policy' queue-id 5

$ fboss2 config session diff
+    "portQueueConfigs": {
+      "test_policy": [
+        {
+          "aqms": [
+            {
+              "behavior": 1,
+              "detection": {
+                "linear": {
+                  "maximumLength": 120000,
+                  "minimumLength": 120000,
+                  "probability": 100
+                }
+              }
+            }
+          ],
+          "id": 5,
+          "scheduling": 1,
+          "streamType": 0
+        }
+      ]
+    },
```
# Summary

This adds a new CLI command to assign a queuing policy (port queue
configuration) to a physical interface:

```
  fboss2 config interface <name> queuing-policy <policy-name>
```

The command validates that the specified policy exists in `portQueueConfigs`
before setting the `portQueueConfigName` attribute on the port.

# Test Plan

End-to-end test output (expanded to include interface assignment):

```
[Step 2] Configuring queuing policy 'cli_e2e_test_queue_policy'...
  Configuring queue-id 2...
[CLI] Running: config qos queuing-policy cli_e2e_test_queue_policy queue-id 2 scheduling SP weight 10 shared-bytes 83618832
  [...]
  All queues configured
  Assigning queuing policy to interface 'eth1/1/1'...
[CLI] Running: config interface eth1/1/1 queuing-policy cli_e2e_test_queue_policy
[CLI] Completed in 0.07s: config interface eth1/1/1 queuing-policy cli_e2e_test_queue_policy
  Queuing policy assigned

[Step 3] Committing configuration...
[CLI] Running: config session commit
[CLI] Completed in 16.09s: config session commit
  Configuration committed successfully

[Step 4] Verifying configuration...
  Buffer pool 'cli_e2e_test_buffer_pool' verified
  Queuing policy 'cli_e2e_test_queue_policy' verified
  Interface 'eth1/1/1' queuing policy verified

======================================================================
TEST PASSED
======================================================================
```

## Sample usage

```
$ fboss2 config qos queuing-policy sample_policy queue-id 0 scheduling sp
Successfully configured queuing-policy 'sample_policy' queue-id 0

$ fboss2 config interface eth1/1/1 queuing-policy sample_policy
Successfully set queuing-policy 'sample_policy' for interface(s) eth1/1/1

$ fboss2 config session diff
--- current live config
+++ session config
@@ -2197,7 +2197,15 @@
     "maxNeighborProbes": 300,
     "mirrorOnDropReports": [],
     "mirrors": [],
-    "portQueueConfigs": {},
+    "portQueueConfigs": {
+      "sample_policy": [
+        {
+          "id": 0,
+          "scheduling": 1,
+          "streamType": 0
+        }
+      ]
+    },
     "ports": [
       {
         "conditionalEntropyRehash": false,
@@ -2219,6 +2227,7 @@
           "rx": false,
           "tx": false
         },
+        "portQueueConfigName": "sample_policy",
         "portType": 0,
         "profileID": 39,
         "queues_DEPRECATED": [],
```
# Summary

Command syntax:
```
  fboss2-dev config qos policy <name> map <map-type> <key> <value>
```

Where:
- `<name>` is the QoS policy name
- `<map-type>` is one of: `tc-to-queue`, `pfc-pri-to-queue`, `tc-to-pg`, `pfc-pri-to-pg`
- `<key>` and `<value>` are integers from 0-7

# Test Plan

New end to end test:

```
======================================================================
CLI E2E Test: QoS Policy Configuration
======================================================================

[Step 0] Cleaning up any existing test config...
  Copying system config to session config...
  Removing QoS policy test configs...
  Updating metadata for AGENT_RESTART...
  Committing cleanup...
  Using CLI from FBOSS_CLI_PATH: ./fboss2-dev
[CLI] Running: config session commit
[CLI] Completed in 2.77s: config session commit
  Cleanup complete

[Step 1] Configuring QoS policy 'cli_e2e_test_qos_policy'...
  Configuring trafficClassToQueueId (tc-to-queue)...
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-queue 0 0
[CLI] Completed in 0.08s: config qos policy cli_e2e_test_qos_policy map tc-to-queue 0 0
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-queue 1 1
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map tc-to-queue 1 1
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-queue 2 2
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-queue 2 2
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-queue 3 3
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-queue 3 3
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-queue 4 4
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-queue 4 4
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-queue 5 5
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-queue 5 5
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-queue 6 6
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-queue 6 6
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-queue 7 7
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map tc-to-queue 7 7
  Configuring pfcPriorityToQueueId (pfc-pri-to-queue)...
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 0 0
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 0 0
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 1 1
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 1 1
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 2 2
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 2 2
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 3 3
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 3 3
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 4 4
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 4 4
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 5 5
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 5 5
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 6 6
[CLI] Completed in 0.05s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 6 6
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 7 7
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-queue 7 7
  Configuring trafficClassToPgId (tc-to-pg)...
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-pg 0 0
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map tc-to-pg 0 0
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-pg 1 1
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map tc-to-pg 1 1
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-pg 2 2
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-pg 2 2
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-pg 3 3
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map tc-to-pg 3 3
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-pg 4 4
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-pg 4 4
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-pg 5 5
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-pg 5 5
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-pg 6 6
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map tc-to-pg 6 6
[CLI] Running: config qos policy cli_e2e_test_qos_policy map tc-to-pg 7 7
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map tc-to-pg 7 7
  Configuring pfcPriorityToPgId (pfc-pri-to-pg)...
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 0 0
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 0 0
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 1 1
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 1 1
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 2 2
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 2 2
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 3 3
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 3 3
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 4 4
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 4 4
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 5 5
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 5 5
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 6 6
[CLI] Completed in 0.06s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 6 6
[CLI] Running: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 7 7
[CLI] Completed in 0.07s: config qos policy cli_e2e_test_qos_policy map pfc-pri-to-pg 7 7
  QoS policy configured

[Step 2] Committing configuration...
[CLI] Running: config session commit
[CLI] Completed in 10.59s: config session commit
  Configuration committed successfully

[Step 3] Verifying configuration...
  QoS policy 'cli_e2e_test_qos_policy' found
  trafficClassToQueueId verified
  pfcPriorityToQueueId verified
  trafficClassToPgId verified
  pfcPriorityToPgId verified

======================================================================
TEST PASSED
======================================================================

[Step 4] Cleaning up test config...
  Copying system config to session config...
  Removing QoS policy test configs...
  Updating metadata for AGENT_RESTART...
  Committing cleanup...
[CLI] Running: config session commit
[CLI] Completed in 6.50s: config session commit
  Cleanup complete
```

## Sample usage

```
admin@fboss101:~/benoit$ ./fboss2-dev config qos policy test-policy map tc-to-queue 0 0
Successfully set QoS policy 'test-policy' trafficClassToQueueId [0] = 0

admin@fboss101:~/benoit$ ./fboss2-dev config qos policy test-policy map pfc-pri-to-queue 3 5
Successfully set QoS policy 'test-policy' pfcPriorityToQueueId [3] = 5

admin@fboss101:~/benoit$ ./fboss2-dev config qos policy test-policy map tc-to-pg 2 2
Successfully set QoS policy 'test-policy' trafficClassToPgId [2] = 2

admin@fboss101:~/benoit$ ./fboss2-dev config qos policy test-policy map pfc-pri-to-pg 7 7
Successfully set QoS policy 'test-policy' pfcPriorityToPgId [7] = 7

admin@fboss101:~/benoit$ ./fboss2-dev config session diff
--- current live config
+++ session config
@@ -5871,7 +5871,28 @@
       }
     ],
     "proactiveArp": false,
-    "qosPolicies": [],
+    "qosPolicies": [
+      {
+        "name": "test-policy",
+        "qosMap": {
+          "dscpMaps": [],
+          "expMaps": [],
+          "pfcPriorityToPgId": {
+            "7": 7
+          },
+          "pfcPriorityToQueueId": {
+            "3": 5
+          },
+          "trafficClassToPgId": {
+            "2": 2
+          },
+          "trafficClassToQueueId": {
+            "0": 0
+          }
+        },
+        "rules": []
+      }
+    ],
     "sFlowCollectors": [],
     "sdkVersion": {
       "asicSdk": "sdk",
```
benoit-nexthop and others added 2 commits February 5, 2026 03:52
# Summary

This change enables running multiple CLI commands within a single process,
which is required for C++ end-to-end tests. The first two end-to-end tests
that were originally written in Python, along with helper functions, have
been rewritten in C++, and can now run as a self-contained gtest binary,
without depending on the fboss2-dev binary.

Some fixes were necessary to make this work, so the CLI could be re-used
as a library instead of being invoked as a subprocess:

1. Remove the `hasRun` static variable from `CmdHandler`
   - Previously, a static `hasRun` flag prevented commands from executing
     more than once per process
   - Now we wrap callbacks in `CmdSubcommands` to check `get_subcommands().empty()`
     to detect leaf commands, eliminating the need for static state

2. Throw exceptions instead of calling `exit(1)` in `CmdHandler`
   - `CmdHandler::run()` now rethrows exceptions instead of calling `exit(1)`
   - This allows tests to catch errors and verify exit codes
   - `Main.cpp` catches exceptions and returns exit code 1

3. Factor out `CLI::App` initialization into `CliAppInit.h`
   - Header-only `initApp()` function shared between `Main.cpp` and tests
   - Eliminates code duplication for CLI setup
   - This couldn't be packaged into a library of its own without going
     into circular dependency hell, hence why it's a header-only helper

4. Reset state in `ConfigSession::initializeSession()`
   - Clear `ConfigSession` attributes when creating a new session (when
     session file doesn't exist)
   - Allows re-using the same `ConfigSession` singleton after `commit()`

5. Update state in `ConfigSession::commit()`
   - Set `base_` to the new commit SHA after successful commit
   - Set `configLoaded_ = false` to force config reload on next access
   - Allows re-using the same `ConfigSession` singleton after `commit()`

6. Automatically initialize session in `ConfigSession::loadConfig()`
   - If session file doesn't exist (e.g., after commit deleted it),
     call `initializeSession()` to create a fresh session

These changes allow the ConfigSession singleton to be properly reused
across multiple CLI command invocations within the same process.

# Test Plan

Added new end-to-end tests in C++ that replace `test_config_interface_mtu.py`
and `test_config_interface_description.py` (the Python scripts will be
removed in a future PR soon).

Sample output (simplified, without timestamps and other noise):

```
[==========] Running 2 tests from 2 test suites.
[----------] 1 test from ConfigInterfaceDescriptionTest
[ RUN      ] ConfigInterfaceDescriptionTest.SetAndVerifyDescription
[Step 1] Finding an interface to test...
  Using interface: eth1/1/1 (VLAN: 2001)
[Step 2] Getting current description...
  Current description: 'CLI_E2E_TEST_DESCRIPTION_ALT'
[Step 3] Setting description to 'CLI_E2E_TEST_DESCRIPTION'...
  Description set to 'CLI_E2E_TEST_DESCRIPTION'
[Step 4] Verifying description via 'show interface'...
  Verified: Description is 'CLI_E2E_TEST_DESCRIPTION'
[Step 5] Restoring original description ('CLI_E2E_TEST_DESCRIPTION_ALT')...
  Restored description to 'CLI_E2E_TEST_DESCRIPTION_ALT'
TEST PASSED
[       OK ] ConfigInterfaceDescriptionTest.SetAndVerifyDescription (412 ms)

[----------] 1 test from ConfigInterfaceMtuTest
[ RUN      ] ConfigInterfaceMtuTest.SetAndVerifyMtu
[Step 1] Finding an interface to test...
  Using interface: eth1/1/1 (VLAN: 2001)
[Step 2] Getting current MTU...
  Current MTU: 9000
[Step 3] Setting MTU to 1500...
  MTU set to 1500
[Step 4] Verifying MTU via 'show interface'...
  Verified: MTU is 1500
[Step 5] Verifying kernel interface MTU...
  Verified: Kernel interface fboss2001 has MTU 1500
[Step 6] Restoring original MTU (9000)...
  Restored MTU to 9000
TEST PASSED
[       OK ] ConfigInterfaceMtuTest.SetAndVerifyMtu (384 ms)

[==========] 2 tests from 2 test suites ran. (797 ms total)
[  PASSED  ] 2 tests.
```
…-mode

# Summary
Implements two new fboss2-dev CLI commands for switch configuration.

## 1. config vlan <vlanId> port <portId> taggingMode <mode>
Configures the VLAN tagging mode for a port within a VLAN. This controls
whether packets are tagged or untagged when egressing the port.
Where `<mode>` can be:
- `tagged` - Packets egress with VLAN tag
- `untagged` - Packets egress without VLAN tag
This is a hitless configuration change (no agent restart required).

## 2. config l2 learning-mode <mode>
Configures the L2 learning mode (`l2LearningMode` in `SwitchSettings`).
This controls how the switch learns MAC addresses.
Where `<mode>` can be:
- `hardware` - MAC learning is performed by the hardware ASIC
- `software` - MAC learning is performed by the software agent
- `disabled` - MAC learning is disabled
Note: Changing L2 learning mode requires an agent restart (not hitless)
because the FBOSS agent does not permit changing this setting after initial
config application.

# Test Plan
## Unit tests
**config vlan port taggingMode** (15 test cases):
- Argument validation, mode conversion, error handling
**config l2 learning-mode** (14 test cases):
- Argument validation, mode conversion, error handling

## End-to-end tests
**config vlan port taggingMode:**
```
============================================================
CLI E2E Test: config vlan <id> port <port> taggingMode
============================================================

[Step 1] Finding an interface to test...
  Using CLI from FBOSS_CLI_PATH: /home/admin/manoharan/fboss2-dev
[CLI] Running: show interface
[CLI] Completed in 0.08s: show interface
  Using interface: eth1/1/1 (VLAN: 2001)

[Step 2] Getting current tagging mode...
[CLI] Running: show running-config
[CLI] Completed in 0.07s: show running-config
  Current mode: untagged

[Step 3] Setting tagging mode to 'tagged'...
[CLI] Running: config vlan 2001 port eth1/1/1 taggingMode tagged
[CLI] Completed in 0.08s: config vlan 2001 port eth1/1/1 taggingMode tagged
[CLI] Running: config session commit
[CLI] Completed in 0.16s: config session commit
  Tagging mode set to 'tagged'

[Step 4] Verifying tagging mode is 'tagged'...
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Verified: Tagging mode is 'tagged'

[Step 5] Setting tagging mode to 'untagged'...
[CLI] Running: config vlan 2001 port eth1/1/1 taggingMode untagged
[CLI] Completed in 0.08s: config vlan 2001 port eth1/1/1 taggingMode untagged
[CLI] Running: config session commit
[CLI] Completed in 0.15s: config session commit
  Tagging mode set to 'untagged'

[Step 6] Verifying tagging mode is 'untagged'...
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Verified: Tagging mode is 'untagged'

============================================================
TEST PASSED
============================================================
```
**config l2 learning-mode:**
```
============================================================
CLI E2E Test: config l2 learning-mode <mode>
============================================================

[Step 1] Getting current L2 learning mode...
  Using CLI from FBOSS_CLI_PATH: /home/admin/manoharan/fboss2-dev
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Current mode: hardware

[Step 2] Setting L2 learning mode to 'software'...
[CLI] Running: config l2 learning-mode software
[CLI] Completed in 0.07s: config l2 learning-mode software
[CLI] Running: config session commit
[CLI] Completed in 2.88s: config session commit
  Waiting for agent to be ready after restart...
  Sleeping 30s for agent restart...
  L2 learning mode set to 'software'

[Step 3] Verifying L2 learning mode is 'software'...
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Verified: L2 learning mode is 'software'

[Step 4] Setting L2 learning mode to 'hardware'...
[CLI] Running: config l2 learning-mode hardware
[CLI] Completed in 0.08s: config l2 learning-mode hardware
[CLI] Running: config session commit
[CLI] Completed in 3.51s: config session commit
  Waiting for agent to be ready after restart...
  Sleeping 30s for agent restart...
  L2 learning mode set to 'hardware'

[Step 5] Verifying L2 learning mode is 'hardware'...
[CLI] Running: show running-config
[CLI] Completed in 0.06s: show running-config
  Verified: L2 learning mode is 'hardware'

============================================================
TEST PASSED
============================================================
```
## Sample usage
```
[admin@fboss101 ~]$ fboss2-dev config vlan 2001 port eth1/1/1 taggingMode untagged
Successfully set tagging mode for port 'eth1/1/1' in VLAN 2001 to 'untagged'

[admin@fboss101 ~]$ fboss2-dev config l2 learning-mode software
Successfully set L2 learning mode to 'software'

[admin@fboss101 ~]$ fboss2-dev config session commit
wedge_agent restarted, config committed
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants