Skip to content

[Nexthop][fboss2-dev] Rewrite fboss2-dev CLI end-to-end tests in C++ with gtest#893

Closed
benoit-nexthop wants to merge 1 commit into
facebook:mainfrom
nexthop-ai:fboss2-cli-prototype_part25
Closed

[Nexthop][fboss2-dev] Rewrite fboss2-dev CLI end-to-end tests in C++ with gtest#893
benoit-nexthop wants to merge 1 commit into
facebook:mainfrom
nexthop-ai:fboss2-cli-prototype_part25

Conversation

@benoit-nexthop

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

Copy link
Copy Markdown
Contributor

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

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.

Note: this change is part of a series, the previous one is #881, the next one is #896.

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.
@meta-cla meta-cla Bot added the CLA Signed label Feb 3, 2026
@benoit-nexthop benoit-nexthop force-pushed the fboss2-cli-prototype_part25 branch from 0e2ede9 to de18a53 Compare February 5, 2026 02:53
benoit-nexthop pushed a commit to nexthop-ai/fboss that referenced this pull request Feb 10, 2026
…p class

# Summary

This PR consolidates the separate CmdConfigInterfaceDescription and
CmdConfigInterfaceMtu commands into a unified CmdConfigInterface command
that can set multiple interface attributes in a single invocation.
```
# Set description
config interface eth1/1/1 description "My port description"

# Set MTU
config interface eth1/1/1 mtu 9000

# Set both in one command
config interface eth1/1/1 description "My port" mtu 9000

# Apply to multiple interfaces
config interface eth1/1/1,eth1/2/1 description "Uplink" mtu 1500
```

Original change by @hillol-nexthop

## Implementation Details

1. **New `InterfaceConfig` class**
- Parses CLI tokens to separate port names from attribute key-value
pairs
  - Supports description and mtu attributes (case-insensitive)
  - Validates attribute names and detects missing values
  - Wraps `InterfaceList` for port/interface resolution
2. **Updated CmdConfigInterface**
  - Changed from pass-through command to functional command
  - Implements `queryClient` to process description and mtu attributes
  - Sets `port->description()` for description attribute
  - Sets `interface->mtu()` for mtu attribute with validation
3. **Updated subcommands to use `InterfaceConfig` instead of
`InterfaceList`**
4. **Deleted obsolete pairs of `.cpp` / `.h`**
5. **New comprehensive test suite**
- 23 tests covering `InterfaceConfig` validation and
`CmdConfigInterface::queryClient` functionality
  - Backward Compatibility
- Subcommands like switchport, pfc-config, and queuing-policy continue
to work as before

# Test Plan

**Note:** The e2e test is already implemented in facebook#893
Above mentioned list of new test file, deleted and updated test files.
Existing unit and end to end tests pass.

# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# Author:    hillol-nexthop <hillol@nexthop.ai>
# Date:      Tue Feb 10 18:53:21 2026 +0530
#
# On branch fboss2-cli-prototype_part28
# Your branch is up to date with 'fork/fboss2-cli-prototype_part28'.
#
# Changes to be committed:
#	modified:   cmake/CliFboss2.cmake
#	modified:   cmake/CliFboss2Test.cmake
#	modified:   fboss/cli/fboss2/BUCK
#	modified:   fboss/cli/fboss2/CmdHandlerImplConfig.cpp
#	modified:   fboss/cli/fboss2/CmdListConfig.cpp
#	modified:   fboss/cli/fboss2/CmdSubcommands.cpp
#	new file:   fboss/cli/fboss2/commands/config/interface/CmdConfigInterface.cpp
#	modified:   fboss/cli/fboss2/commands/config/interface/CmdConfigInterface.h
#	deleted:    fboss/cli/fboss2/commands/config/interface/CmdConfigInterfaceDescription.cpp
#	deleted:    fboss/cli/fboss2/commands/config/interface/CmdConfigInterfaceDescription.h
#	deleted:    fboss/cli/fboss2/commands/config/interface/CmdConfigInterfaceMtu.cpp
#	deleted:    fboss/cli/fboss2/commands/config/interface/CmdConfigInterfaceMtu.h
#	modified:   fboss/cli/fboss2/commands/config/interface/CmdConfigInterfaceQueuingPolicy.cpp
#	modified:   fboss/cli/fboss2/commands/config/interface/CmdConfigInterfaceQueuingPolicy.h
#	modified:   fboss/cli/fboss2/commands/config/interface/pfc_config/CmdConfigInterfacePfcConfig.cpp
#	modified:   fboss/cli/fboss2/commands/config/interface/pfc_config/CmdConfigInterfacePfcConfig.h
#	modified:   fboss/cli/fboss2/commands/config/interface/switchport/CmdConfigInterfaceSwitchport.h
#	modified:   fboss/cli/fboss2/commands/config/interface/switchport/access/CmdConfigInterfaceSwitchportAccess.h
#	modified:   fboss/cli/fboss2/commands/config/interface/switchport/access/vlan/CmdConfigInterfaceSwitchportAccessVlan.cpp
#	modified:   fboss/cli/fboss2/commands/config/interface/switchport/access/vlan/CmdConfigInterfaceSwitchportAccessVlan.h
#	modified:   fboss/cli/fboss2/test/BUCK
#	deleted:    fboss/cli/fboss2/test/CmdConfigInterfaceDescriptionTest.cpp
#	deleted:    fboss/cli/fboss2/test/CmdConfigInterfaceMtuTest.cpp
#	modified:   fboss/cli/fboss2/test/CmdConfigInterfaceSwitchportAccessVlanTest.cpp
#	new file:   fboss/cli/fboss2/test/CmdConfigInterfaceTest.cpp
#	modified:   fboss/cli/fboss2/utils/CmdUtilsCommon.h
#	new file:   fboss/cli/fboss2/utils/InterfacesConfig.cpp
#	new file:   fboss/cli/fboss2/utils/InterfacesConfig.h
#
benoit-nexthop pushed a commit to nexthop-ai/fboss that referenced this pull request Feb 10, 2026
…p class

# Summary

This PR consolidates the separate CmdConfigInterfaceDescription and
CmdConfigInterfaceMtu commands into a unified CmdConfigInterface command
that can set multiple interface attributes in a single invocation.
```
# Set description
config interface eth1/1/1 description "My port description"

# Set MTU
config interface eth1/1/1 mtu 9000

# Set both in one command
config interface eth1/1/1 description "My port" mtu 9000

# Apply to multiple interfaces
config interface eth1/1/1,eth1/2/1 description "Uplink" mtu 1500
```

Original change by @hillol-nexthop

## Implementation Details

1. **New `InterfaceConfig` class**
- Parses CLI tokens to separate port names from attribute key-value
pairs
  - Supports description and mtu attributes (case-insensitive)
  - Validates attribute names and detects missing values
  - Wraps `InterfaceList` for port/interface resolution
2. **Updated CmdConfigInterface**
  - Changed from pass-through command to functional command
  - Implements `queryClient` to process description and mtu attributes
  - Sets `port->description()` for description attribute
  - Sets `interface->mtu()` for mtu attribute with validation
3. **Updated subcommands to use `InterfaceConfig` instead of
`InterfaceList`**
4. **Deleted obsolete pairs of `.cpp` / `.h`**
5. **New comprehensive test suite**
- 23 tests covering `InterfaceConfig` validation and
`CmdConfigInterface::queryClient` functionality
  - Backward Compatibility
- Subcommands like switchport, pfc-config, and queuing-policy continue
to work as before

# Test Plan

**Note:** The e2e test is already implemented in facebook#893
Above mentioned list of new test file, deleted and updated test files.
Existing unit and end to end tests pass.

@joseph5wu joseph5wu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall it matches what I would expect an end-to-end CLI test binary should look like.
Although this is the first diff, I can see there're some future improvements on how to write these tests in a more concise way. As most of the tests should follow the below steps:

  • pick the subject for your tests. could be an interface, a vlan or a qos
  • prepare the exact cli you wants to run and then execute
  • call a validation function
  • maybe we should also properly check the config version updated or config session infra logic in the test too
  • restore the config

Hopefully with more and more tests you're about to add, you can consider what's a best way to make CliTest.cpp more structured and all the commands can reuse more of the code.

What's more, we should also introduce "batch cli" in your end-to-end tests; or cli with different action levels.

Comment on lines +838 to +839
// Force config reload from system config on next access
configLoaded_ = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we also need to clear commands_ and requiredActions_ like you did for line 639-642 above?
If so, can you make a private resetSession() function to make sure all the necessary variables get reset

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.

This change wasn't part of this PR. It was part of the PR adding rebase: #832

Comment on lines +22 to +43
#include <fmt/format.h>
#include <folly/Conv.h>
#include <folly/Demangle.h>
#include <folly/ScopeGuard.h>
#include <folly/Traits.h>
#include <folly/logging/xlog.h>
#include <folly/stop_watch.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <exception>
#include <future>
#include <iostream>
#include <map>
#include <memory>
#include <optional>
#include <queue>
#include <stdexcept>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why suddenly includes so many libraries? Your change in the implementation below doesn't seem to rely on all these libraries

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.

This is adding already required headers. I generate the includes with clang-include-cleaner.

hillol-nexthop added a commit to nexthop-ai/fboss that referenced this pull request Feb 16, 2026
…p class

This PR consolidates the separate CmdConfigInterfaceDescription and
CmdConfigInterfaceMtu commands into a unified CmdConfigInterface command
that can set multiple interface attributes in a single invocation.
```
config interface eth1/1/1 description "My port description"

config interface eth1/1/1 mtu 9000

config interface eth1/1/1 description "My port" mtu 9000

config interface eth1/1/1,eth1/2/1 description "Uplink" mtu 1500
```

Original change by @hillol-nexthop

1. **New `InterfaceConfig` class**
- Parses CLI tokens to separate port names from attribute key-value
pairs
  - Supports description and mtu attributes (case-insensitive)
  - Validates attribute names and detects missing values
  - Wraps `InterfaceList` for port/interface resolution
2. **Updated CmdConfigInterface**
  - Changed from pass-through command to functional command
  - Implements `queryClient` to process description and mtu attributes
  - Sets `port->description()` for description attribute
  - Sets `interface->mtu()` for mtu attribute with validation
3. **Updated subcommands to use `InterfaceConfig` instead of
`InterfaceList`**
4. **Deleted obsolete pairs of `.cpp` / `.h`**
5. **New comprehensive test suite**
- 23 tests covering `InterfaceConfig` validation and
`CmdConfigInterface::queryClient` functionality
  - Backward Compatibility
- Subcommands like switchport, pfc-config, and queuing-policy continue
to work as before

**Note:** The e2e test is already implemented in facebook#893
Above mentioned list of new test file, deleted and updated test files.
Existing unit and end to end tests pass.
Comment thread fboss/cli/test/CliTest.h Outdated
/**
* Represents a network interface from the output of 'show interface'.
*/
struct Interface {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's put this inside CliTest class so it won't mess up with the real facebook::fboss::Interface
(https://github.com/facebook/fboss/blob/main/fboss/agent/state/Interface.h#L56)

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.

Done. Also move the CliResult class that was right before it, so that it became CliTest::Result.

Comment on lines +54 to +56
fs::path sessionDir = fs::path(home) / ".fboss2";
fs::path sessionConfig = sessionDir / "agent.conf";
fs::path sessionMetadata = sessionDir / "cli_metadata.json";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since we're touching files/folders for the fboss2 config cli, I think we should consider to introduce
something similar to
https://github.com/facebook/fboss/blob/main/fboss/agent/AgentDirectoryUtil.h
for our config related directory to store these static settings

Feel free to use future PR to address this improvement

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.

Will do.

* @return MTU value, or -1 if interface not found
*/
int getKernelInterfaceMtu(int vlanId) const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this function is only needed for the ConfigInterfaceMtuTest.cpp.
we don't have to define this method in the general CliTest.cpp.
We should set the standard that this CliTest.cpp only handles the common utility functions,
any other functions related to specific tests should be handled in their own test classes.

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 put it here because I felt like it was likely to be needed for other tests in the future.

Comment thread fboss/cli/test/CliTest.cpp Outdated
Comment on lines +254 to +274
int cliTestMain(int argc, char** argv) {
// Initialize gtest first so it consumes --gtest_* flags before folly::init
::testing::InitGoogleTest(&argc, argv);

// Initialize folly singletons before using CLI components
folly::init(&argc, &argv, /* removeFlags = */ false);

return RUN_ALL_TESTS();
}

} // namespace facebook::fboss

#ifdef IS_OSS
FOLLY_INIT_LOGGING_CONFIG("DBG2; default:async=true");
#else
FOLLY_INIT_LOGGING_CONFIG("fboss=DBG2; default:async=true");
#endif

int main(int argc, char* argv[]) {
return facebook::fboss::cliTestMain(argc, argv);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's move the cliTestMain() implementation to the main() directly.
I don't see there's other place needed to call cliTestMain()

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.

Done.

Comment on lines +122 to +135
folly::dynamic CliTest::runCliJson(const std::vector<std::string>& args) const {
auto result = runCli(args);
if (result.exitCode != 0) {
throw std::runtime_error(
fmt::format(
"CLI command failed with exit code {}: {}",
result.exitCode,
result.stderr));
}
if (result.stdout.empty()) {
return folly::dynamic::object();
}
return folly::parseJson(result.stdout);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am not a big fan of this function, because all the other run cli or command functions are return CliResult while this returns folly::dynamic and throw exception if there's an error.

I'd recommend to remove such function, and always let users call runCli(). And then you just need to provide a function like folly::dynamic toFollyDynamic(const std::string& stdout). This will force your test to do EXPECT_EQ(result.exitCode, 0) first before calling this function to convert the string

@benoit-nexthop benoit-nexthop Mar 20, 2026

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 don't want to have to repeat an EXPECT_EQ() followed by a call to toFollyDynamic() everywhere we run a CLI command. If your concern is with the exception throwing here, can we instead do this:

  EXPECT_EQ(result.exitCode, 0) << "CLI command failed: " << result.stderr;

  if (result.exitCode != 0 || result.stdout.empty()) {
    return folly::dynamic::object();
  }
Comment on lines +240 to +243
if (result.exitCode != 0) {
XLOG(WARN) << "Kernel interface " << kernelIntf << " not found";
return -1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All FBOSS Interface should be shown in kernel interface.
Let's treat it as an error if such interface doesn't exist

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.

Done.

Comment on lines +1354 to +1359
CLI tests are simpler than hardware tests - they don't need config file
manipulation, warmboot/coldboot setup, or SAI-specific logging. They just
run against the already-running agent via Thrift.
"""
tests_to_run = self._get_tests_to_run()
tests_to_run = self._filter_tests(tests_to_run)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm okay with this diff doesn't properly orchestra all the necessary services to run cli_test.
But ideally, I would like to see run_test.py to properly setup agent, qsfp, fsdb and etc services just like link tests.

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.

OK, I can do this in a follow up change. Should CliTestRunner mimic what LinkTestRunner does in _setup_coldboot_test() and _setup_warmboot_test() then? If yes maybe it would be better to refactor the code so as to avoid duplication between LinkTestRunner and CliTestRunner. I can send a PR for this if you agree.

Comment on lines +1369 to +1402
print(f"Running {len(tests_to_run)} CLI end-to-end tests...")
start_time = datetime.now()

# Run all tests in a single gtest invocation
test_filter = ":".join(tests_to_run)
# Use /tmp for test results since CLI tests may not have write access
# to the default TESTRESULT_FILE location
result_file = "/tmp/cli_test_results.xml"
cmd = [
self._get_test_binary_name(),
f"--gtest_filter={test_filter}",
f"--gtest_output=xml:{result_file}",
]

print(f"Running command: {' '.join(cmd)}")

try:
result = subprocess.run(
cmd,
timeout=args.test_run_timeout,
)

end_time = datetime.now()
delta_time = end_time - start_time
print(f"Running all tests took {delta_time}")

if result.returncode != 0:
sys.exit(result.returncode)

except subprocess.TimeoutExpired:
print(f"[ TIMEOUT ] CLI tests timed out after {args.test_run_timeout}s")
sys.exit(1)
except Exception as e:
print(f"[ ERROR ] Failed to run CLI tests: {e}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Now as cli_test as a cpp test binary just like all the other test binaries, can we keep the run logic identical

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.

Done. I had to override the fruid_path and coldboot args for CliTestRunner in order to disable passing --fruid_path and --setup-for-warmboot as those flags are not supported by the cli_test binary.

@benoit-nexthop benoit-nexthop force-pushed the fboss2-cli-prototype_part25 branch from de18a53 to 959d4e8 Compare March 19, 2026 09:55
@benoit-nexthop benoit-nexthop requested review from a team as code owners March 19, 2026 09:55
meta-codesync Bot pushed a commit that referenced this pull request Mar 19, 2026
Summary:
**Pre-submission checklist**
- [x] 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`
- [x] `pre-commit run`

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

Note: this change is part of a series, the previous one is #867, the next one is #893.

Pull Request resolved: #881

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",
```

Reviewed By: KevinYakar

Differential Revision: D97308312

Pulled By: joseph5wu

fbshipit-source-id: 3fc4d0be7e504cd044bb71a89acde5867d1308bd
@benoit-nexthop benoit-nexthop force-pushed the fboss2-cli-prototype_part25 branch 3 times, most recently from 2d4c073 to daa1b1a Compare March 20, 2026 09:39
@meta-codesync

meta-codesync Bot commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

@joseph5wu has imported this pull request. If you are a Meta employee, you can view this in D97513684.

@benoit-nexthop benoit-nexthop force-pushed the fboss2-cli-prototype_part25 branch from daa1b1a to 8c1d28c Compare March 20, 2026 19:23
@facebook-github-tools

Copy link
Copy Markdown

@benoit-nexthop has updated the pull request. You must reimport the pull request before landing.

@benoit-nexthop benoit-nexthop force-pushed the fboss2-cli-prototype_part25 branch from 8c1d28c to 6fa5e9e Compare March 20, 2026 23:15
@facebook-github-tools

Copy link
Copy Markdown

@benoit-nexthop has updated the pull request. You must reimport the pull request before landing.

@benoit-nexthop benoit-nexthop force-pushed the fboss2-cli-prototype_part25 branch from 6fa5e9e to 35be84f Compare March 20, 2026 23:18
@facebook-github-tools

Copy link
Copy Markdown

@benoit-nexthop has updated the pull request. You must reimport the pull request before landing.

@benoit-nexthop benoit-nexthop force-pushed the fboss2-cli-prototype_part25 branch from 35be84f to 93b2f56 Compare March 20, 2026 23:20
@facebook-github-tools

Copy link
Copy Markdown

@benoit-nexthop has updated the pull request. You must reimport the pull request before landing.

# 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.
```
@benoit-nexthop benoit-nexthop force-pushed the fboss2-cli-prototype_part25 branch from 93b2f56 to 50984b8 Compare March 21, 2026 00:15
@facebook-github-tools

Copy link
Copy Markdown

@benoit-nexthop has updated the pull request. You must reimport the pull request before landing.

@meta-codesync

meta-codesync Bot commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

@joseph5wu merged this pull request in 06ff27b.

meta-codesync Bot pushed a commit that referenced this pull request Mar 25, 2026
…-mode (#896)

Summary:
**Pre-submission checklist**
- [x] 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`
- [x] `pre-commit run`

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.

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

Pull Request resolved: #896

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:
## 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

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
```

Reviewed By: KevinYakar

Differential Revision: D98023658

Pulled By: joseph5wu

fbshipit-source-id: 57b01b9f2a9acbfd3c39622fdf86ae0001b3a7a6
benoit-nexthop pushed a commit to nexthop-ai/fboss that referenced this pull request Mar 26, 2026
…p class

# Summary

This PR consolidates the separate CmdConfigInterfaceDescription and
CmdConfigInterfaceMtu commands into a unified CmdConfigInterface command
that can set multiple interface attributes in a single invocation.
```
# Set description
config interface eth1/1/1 description "My port description"

# Set MTU
config interface eth1/1/1 mtu 9000

# Set both in one command
config interface eth1/1/1 description "My port" mtu 9000

# Apply to multiple interfaces
config interface eth1/1/1,eth1/2/1 description "Uplink" mtu 1500
```

Original change by @hillol-nexthop

## Implementation Details

1. **New `InterfaceConfig` class**
- Parses CLI tokens to separate port names from attribute key-value
pairs
  - Supports description and mtu attributes (case-insensitive)
  - Validates attribute names and detects missing values
  - Wraps `InterfaceList` for port/interface resolution
2. **Updated CmdConfigInterface**
  - Changed from pass-through command to functional command
  - Implements `queryClient` to process description and mtu attributes
  - Sets `port->description()` for description attribute
  - Sets `interface->mtu()` for mtu attribute with validation
3. **Updated subcommands to use `InterfaceConfig` instead of
`InterfaceList`**
4. **Deleted obsolete pairs of `.cpp` / `.h`**
5. **New comprehensive test suite**
- 23 tests covering `InterfaceConfig` validation and
`CmdConfigInterface::queryClient` functionality
  - Backward Compatibility
- Subcommands like switchport, pfc-config, and queuing-policy continue
to work as before

# Test Plan

**Note:** The e2e test is already implemented in facebook#893
Above mentioned list of new test file, deleted and updated test files.
Existing unit and end to end tests pass.
benoit-nexthop pushed a commit to nexthop-ai/fboss that referenced this pull request Mar 26, 2026
…p class

# Summary

This PR consolidates the separate CmdConfigInterfaceDescription and
CmdConfigInterfaceMtu commands into a unified CmdConfigInterface command
that can set multiple interface attributes in a single invocation.
```
# Set description
config interface eth1/1/1 description "My port description"

# Set MTU
config interface eth1/1/1 mtu 9000

# Set both in one command
config interface eth1/1/1 description "My port" mtu 9000

# Apply to multiple interfaces
config interface eth1/1/1,eth1/2/1 description "Uplink" mtu 1500
```

Original change by @hillol-nexthop

## Implementation Details

1. **New `InterfaceConfig` class**
- Parses CLI tokens to separate port names from attribute key-value
pairs
  - Supports description and mtu attributes (case-insensitive)
  - Validates attribute names and detects missing values
  - Wraps `InterfaceList` for port/interface resolution
2. **Updated CmdConfigInterface**
  - Changed from pass-through command to functional command
  - Implements `queryClient` to process description and mtu attributes
  - Sets `port->description()` for description attribute
  - Sets `interface->mtu()` for mtu attribute with validation
3. **Updated subcommands to use `InterfaceConfig` instead of
`InterfaceList`**
4. **Deleted obsolete pairs of `.cpp` / `.h`**
5. **New comprehensive test suite**
- 23 tests covering `InterfaceConfig` validation and
`CmdConfigInterface::queryClient` functionality
  - Backward Compatibility
- Subcommands like switchport, pfc-config, and queuing-policy continue
to work as before

# Test Plan

**Note:** The e2e test is already implemented in facebook#893
Above mentioned list of new test file, deleted and updated test files.
Existing unit and end to end tests pass.
benoit-nexthop pushed a commit to nexthop-ai/fboss that referenced this pull request Mar 26, 2026
…p class

# Summary

This PR consolidates the separate CmdConfigInterfaceDescription and
CmdConfigInterfaceMtu commands into a unified CmdConfigInterface command
that can set multiple interface attributes in a single invocation.
```
# Set description
config interface eth1/1/1 description "My port description"

# Set MTU
config interface eth1/1/1 mtu 9000

# Set both in one command
config interface eth1/1/1 description "My port" mtu 9000

# Apply to multiple interfaces
config interface eth1/1/1,eth1/2/1 description "Uplink" mtu 1500
```

Original change by @hillol-nexthop

## Implementation Details

1. **New `InterfaceConfig` class**
- Parses CLI tokens to separate port names from attribute key-value
pairs
  - Supports description and mtu attributes (case-insensitive)
  - Validates attribute names and detects missing values
  - Wraps `InterfaceList` for port/interface resolution
2. **Updated CmdConfigInterface**
  - Changed from pass-through command to functional command
  - Implements `queryClient` to process description and mtu attributes
  - Sets `port->description()` for description attribute
  - Sets `interface->mtu()` for mtu attribute with validation
3. **Updated subcommands to use `InterfaceConfig` instead of
`InterfaceList`**
4. **Deleted obsolete pairs of `.cpp` / `.h`**
5. **New comprehensive test suite**
- 23 tests covering `InterfaceConfig` validation and
`CmdConfigInterface::queryClient` functionality
  - Backward Compatibility
- Subcommands like switchport, pfc-config, and queuing-policy continue
to work as before

# Test Plan

**Note:** The e2e test is already implemented in facebook#893
Above mentioned list of new test file, deleted and updated test files.
Existing unit and end to end tests pass.
meta-codesync Bot pushed a commit that referenced this pull request Mar 26, 2026
…p class (#919)

Summary:
**Pre-submission checklist**
- [x] 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`
- [x] `pre-commit run`

This PR consolidates the separate `CmdConfigInterfaceDescription` and `CmdConfigInterfaceMtu` commands into a unified `CmdConfigInterface` command that can set multiple interface attributes in a single invocation.
```
# Set description
config interface eth1/1/1 description "My port description"

# Set MTU
config interface eth1/1/1 mtu 9000

# Set both in one command
config interface eth1/1/1 description "My port" mtu 9000

# Apply to multiple interfaces
config interface eth1/1/1,eth1/2/1 description "Uplink" mtu 1500
```

Original change by hillol-nexthop

Note: this change is part of a series, the previous one is #900, the next one is #931.

## Implementation Details

1. **New `InterfaceConfig` class**
- Parses CLI tokens to separate port names from attribute key-value
pairs
  - Supports description and mtu attributes (case-insensitive)
  - Validates attribute names and detects missing values
  - Wraps `InterfaceList` for port/interface resolution
2. **Updated CmdConfigInterface**
  - Changed from pass-through command to functional command
  - Implements `queryClient` to process description and mtu attributes
  - Sets `port->description()` for description attribute
  - Sets `interface->mtu()` for mtu attribute with validation
3. **Updated subcommands to use `InterfaceConfig` instead of `InterfaceList`**
4. **Deleted obsolete pairs of `.cpp` / `.h`**
5. **New comprehensive test suite**
  - 23 tests covering `InterfaceConfig` validation and `CmdConfigInterface::queryClient` functionality
  - Backward Compatibility
  - Subcommands like switchport, pfc-config, and queuing-policy continue to work as before

Pull Request resolved: #919

Test Plan:
**Note:** The e2e test is already implemented in #893
Above mentioned list of new test file, deleted and updated test files.
Existing unit and end to end tests pass.

Reviewed By: KevinYakar

Differential Revision: D98340162

Pulled By: joseph5wu

fbshipit-source-id: 82d10267ae00fb6e81710f61781f0746d591f836
Comment on lines +67 to +75
if (kernelMtu > 0) {
EXPECT_EQ(kernelMtu, newMtu)
<< "Kernel MTU is " << kernelMtu << ", expected " << newMtu;
XLOG(INFO) << " Verified: Kernel interface fboss" << *interface.vlan
<< " has MTU " << kernelMtu;
} else {
XLOG(INFO) << " Skipped: Kernel interface fboss" << *interface.vlan
<< " not found";
}

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.

This part of the change was not merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment