From 16f2d5dc2f4e921d4faccac611ebe8ccc8f4be7b Mon Sep 17 00:00:00 2001 From: Lip <127746398+Lip-sun@users.noreply.github.com> Date: Sun, 9 Aug 2026 16:00:46 +0000 Subject: [PATCH] Allow IPv6 addresses for ERSPAN sessions Signed-off-by: Lip <127746398+Lip-sun@users.noreply.github.com> --- config/main.py | 14 ++++++++++++-- tests/config_mirror_session_test.py | 14 +++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/config/main.py b/config/main.py index bd268ff631f..5eee0905381 100644 --- a/config/main.py +++ b/config/main.py @@ -1559,6 +1559,16 @@ def remove_router_interface_ip_address(config_db, interface_name, ipaddress_to_r if ipaddress.ip_interface(ipaddress_string) == ipaddress_to_remove: config_db.set_entry(table_name, (interface_name, ipaddress_string), None) + +def validate_ip_address(ctx, param, ip_addr): + """Helper function to validate IP address + """ + try: + ipaddress.ip_network(ip_addr, False) + return ip_addr + except ValueError as e: + raise click.UsageError(str(e)) + def validate_ipv4_address(ctx, param, ip_addr): """Helper function to validate ipv4 address """ @@ -3319,8 +3329,8 @@ def erspan(ctx): @erspan.command('add') @click.argument('session_name', metavar='', required=True) -@click.argument('src_ip', metavar='', callback=validate_ipv4_address, required=True) -@click.argument('dst_ip', metavar='', callback=validate_ipv4_address,required=True) +@click.argument('src_ip', metavar='', callback=validate_ip_address, required=True) +@click.argument('dst_ip', metavar='', callback=validate_ip_address, required=True) @click.argument('dscp', metavar='', type=DSCP_RANGE, required=True) @click.argument('ttl', metavar='', type=TTL_RANGE, required=True) @click.argument('gre_type', metavar='[gre_type]', callback=validate_gre_type, required=False) diff --git a/tests/config_mirror_session_test.py b/tests/config_mirror_session_test.py index 7bf1f506e5f..f0bfe03b671 100644 --- a/tests/config_mirror_session_test.py +++ b/tests/config_mirror_session_test.py @@ -115,13 +115,6 @@ def test_mirror_session_erspan_add(): assert result.exit_code != 0 assert ERR_MSG_IP_FAILURE in result.stdout - # Verify invalid ip version - result = runner.invoke( - config.config.commands["mirror_session"].commands["erspan"].commands["add"], - ["test_session", "1::1", "2::2", "8", "63", "10", "100"]) - assert result.exit_code != 0 - assert ERR_MSG_IP_VERSION_FAILURE in result.stdout - # Verify invalid dscp result = runner.invoke( config.config.commands["mirror_session"].commands["erspan"].commands["add"], @@ -176,6 +169,13 @@ def test_mirror_session_erspan_add(): mocked.assert_called_with("test_session", "100.1.1.1", "2.2.2.2", 8, 63, 0, 0, None, None, None, 0, 0) + # Verify IPv6 ERSPAN session + result = runner.invoke( + config.config.commands["mirror_session"].commands["erspan"].commands["add"], + ["test_session", "2001:db8::1", "2001:db8::2", "8", "63", "10", "100"]) + + assert result.exit_code == 0 + mocked.assert_called_with("test_session", "2001:db8::1", "2001:db8::2", 8, 63, 10, 100, None, None, None, 0, 0) @patch("validated_config_db_connector.device_info.is_yang_config_validation_enabled", mock.Mock(return_value=True)) @patch("config.validated_config_db_connector.ValidatedConfigDBConnector.validated_set_entry", mock.Mock(side_effect=ValueError))