From 2d70a91b25b8e3112c523f390ae004a37e324da6 Mon Sep 17 00:00:00 2001 From: malletvapid23 Date: Sat, 13 Aug 2022 03:00:36 +0300 Subject: [PATCH] add lacp_rate to portchannel (#2036) #### What I did Make lacp_rate configurable for portchannel. ``` Option specifying the rate in which we'll ask our link partner to transmit LACPDU packets in 802.3ad mode. Possible values are: slow Request partner to transmit LACPDUs every 30 seconds fast Request partner to transmit LACPDUs every 1 second The default is slow. ``` #### Why I did it In case of slow lacp_rate configuration link down will be detected in 60-90 seconds, it may be to long (for example for MCLAG high availability), in case of using ` --fast-rate=true` link down will be detected in 2-3 seconds. #### How I did it * add optional argument to `config portchannel` command, default=slow for backward compatibility. (this PR) * parse argument in `teammgr` and forward it to `teamd` (other PR: https://github.com/Azure/sonic-swss/pull/2121) * update docs https://github.com/Azure/SONiC/pull/937 #### How to verify it Confgiure bond on other side, then configure portchannel and sniff the traffic from it. ``` config portchannel add PortChannel0001 --fast-rate=true config portchannel member add PortChannel0001 Ethernet0 config interface ip add PortChannel0001 192.168.1.2/24 tcpdump -ne ``` --- config/main.py | 14 ++++++++++---- doc/Command-Reference.md | 5 +++-- tests/portchannel_test.py | 28 +++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/config/main.py b/config/main.py index 5c74ec9..49713d1 100644 --- a/config/main.py +++ b/config/main.py @@ -1967,8 +1967,11 @@ def portchannel(db, ctx, namespace): @click.argument('portchannel_name', metavar='', required=True) @click.option('--min-links', default=1, type=click.IntRange(1,1024)) @click.option('--fallback', default='false') +@click.option('--fast-rate', default='false', + type=click.Choice(['true', 'false'], + case_sensitive=False)) @click.pass_context -def add_portchannel(ctx, portchannel_name, min_links, fallback): +def add_portchannel(ctx, portchannel_name, min_links, fallback, fast_rate): """Add port channel""" if is_portchannel_name_valid(portchannel_name) != True: ctx.fail("{} is invalid!, name should have prefix '{}' and suffix '{}'" @@ -1979,9 +1982,12 @@ def add_portchannel(ctx, portchannel_name, min_links, fallback): if is_portchannel_present_in_db(db, portchannel_name): ctx.fail("{} already exists!".format(portchannel_name)) - fvs = {'admin_status': 'up', - 'mtu': '9100', - 'lacp_key': 'auto'} + fvs = { + 'admin_status': 'up', + 'mtu': '9100', + 'lacp_key': 'auto', + 'fast_rate': fast_rate.lower(), + } if min_links != 0: fvs['min_links'] = str(min_links) if fallback != 'false': diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index f19c987..4d30c3b 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -6925,12 +6925,13 @@ When any port is already member of any other portchannel and if user tries to ad Command takes two optional arguements given below. 1) min-links - minimum number of links required to bring up the portchannel 2) fallback - true/false. LACP fallback feature can be enabled / disabled. When it is set to true, only one member port will be selected as active per portchannel during fallback mode. Refer https://github.com/Azure/SONiC/blob/master/doc/lag/LACP%20Fallback%20Feature%20for%20SONiC_v0.5.md for more details about fallback feature. +3) fast-rate - true/false, default is false (slow). Option specifying the rate in which we'll ask our link partner to transmit LACPDU packets in 802.3ad mode. slow - request partner to transmit LACPDUs every 30 seconds, fast - request partner to transmit LACPDUs every 1 second. In slow mode 60-90 seconds needed to detect linkdown, in fast mode only 2-3 seconds. A port channel can be deleted only if it does not have any members or the members are already deleted. When a user tries to delete a port channel and the port channel still has one or more members that exist, the deletion of port channel is blocked. - Usage: ``` - config portchannel (add | del) [--min-links ] [--fallback (true | false)] + config portchannel (add | del) [--min-links ] [--fallback (true | false) [--fast-rate (true | false)] ``` - Example (Create the portchannel with name "PortChannel0011"): @@ -11020,4 +11021,4 @@ ZTP will be restarted. You may lose switch data and connectivity, continue? [y/N Running command: ztp run -y ``` -Go Back To [Beginning of the document](#SONiC-COMMAND-LINE-INTERFACE-GUIDE) or [Beginning of this section](#ztp-configuration-and-show-commands) \ No newline at end of file +Go Back To [Beginning of the document](#SONiC-COMMAND-LINE-INTERFACE-GUIDE) or [Beginning of this section](#ztp-configuration-and-show-commands) diff --git a/tests/portchannel_test.py b/tests/portchannel_test.py index 7c9a7b6..9b187f1 100644 --- a/tests/portchannel_test.py +++ b/tests/portchannel_test.py @@ -1,4 +1,5 @@ import os +import pytest import traceback from click.testing import CliRunner @@ -60,7 +61,32 @@ def test_delete_non_existing_portchannel(self): print(result.output) assert result.exit_code != 0 assert "Error: PortChannel0005 is not present." in result.output - + + @pytest.mark.parametrize("fast_rate", ["False", "True", "false", "true"]) + def test_add_portchannel_with_fast_rate(self, fast_rate): + runner = CliRunner() + db = Db() + obj = {'db':db.cfgdb} + + # add a portchannel with fats rate + result = runner.invoke(config.config.commands["portchannel"].commands["add"], ["PortChannel0005", "--fast-rate", fast_rate], obj=obj) + print(result.exit_code) + print(result.output) + assert result.exit_code == 0 + + @pytest.mark.parametrize("fast_rate", ["Fls", "tru"]) + def test_add_portchannel_with_invalid_fast_rate(self, fast_rate): + runner = CliRunner() + db = Db() + obj = {'db':db.cfgdb} + + # add a portchannel with invalid fats rate + result = runner.invoke(config.config.commands["portchannel"].commands["add"], ["PortChannel0005", "--fast-rate", fast_rate], obj=obj) + print(result.exit_code) + print(result.output) + assert result.exit_code != 0 + assert 'Invalid value for "--fast-rate"' in result.output + def test_add_portchannel_member_with_invalid_name(self): runner = CliRunner() db = Db()