Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kernel 4.9: race condition seen with port channel creation. #1981

Closed
jipanyang opened this issue Aug 23, 2018 · 13 comments
Closed

Kernel 4.9: race condition seen with port channel creation. #1981

jipanyang opened this issue Aug 23, 2018 · 13 comments
Assignees
Labels

Comments

@jipanyang
Copy link
Collaborator

Description
Portchannel creation failed partially with config reload or system reboot.

root@sonic:/home/admin# config reload
Clear current config and reload config from the file /etc/sonic/config_db.json? [y/N]: y
Running command: systemctl stop dhcp_relay
Running command: systemctl stop swss
Running command: systemctl stop snmp
Warning: Stopping snmp.service, but it can still be activated by:
  snmp.timer
Running command: systemctl stop lldp
Running command: systemctl stop pmon
Running command: systemctl stop bgp
Running command: systemctl stop teamd
Running command: sonic-cfggen -j /etc/sonic/config_db.json --write-to-db
Running command: systemctl restart hostname-config
Running command: systemctl restart interfaces-config
Running command: systemctl restart ntp-config
Running command: systemctl restart rsyslog-config
Running command: systemctl restart swss
Running command: systemctl restart bgp
Running command: systemctl restart teamd
Running command: systemctl restart pmon
Running command: systemctl restart lldp
Running command: systemctl restart snmp
Running command: systemctl restart dhcp_relay
root@sonic:/home/admin# 
root@sonic:/home/admin# team show
bash: team: command not found
root@sonic:/home/admin# teamshow 
Flags: A - active, I - inactive, Up - up, Dw - Down, N/A - not available, S - selected, D - deselected
  No.  Team Dev       Protocol     Ports
-----  -------------  -----------  -------------
    1  PortChannel1   N/A
    2  PortChannel2   N/A
    3  PortChannel3   N/A
    4  PortChannel4   N/A
    5  PortChannel5   N/A
    6  PortChannel6   N/A
    7  PortChannel7   N/A
    8  PortChannel8   N/A
    9  PortChannel9   N/A
   10  PortChannel10  LACP(A)(Up)  Ethernet10(S)
   11  PortChannel11  LACP(A)(Up)  Ethernet11(S)
   12  PortChannel12  LACP(A)(Up)  Ethernet12(S)
   13  PortChannel13  LACP(A)(Up)  Ethernet13(S)
   14  PortChannel14  N/A
   15  PortChannel15  N/A
   16  PortChannel16  N/A
   17  PortChannel17  N/A
   18  PortChannel18  LACP(A)(Up)  Ethernet18(S)
   19  PortChannel19  N/A
   20  PortChannel20  LACP(A)(Up)  Ethernet20(S)

Restart teamd service, portchannel got created succefully.

root@sonic:/home/admin# systemctl restart teamd
root@sonic:/home/admin# teamshow 
Flags: A - active, I - inactive, Up - up, Dw - Down, N/A - not available, S - selected, D - deselected
  No.  Team Dev       Protocol      Ports
-----  -------------  ------------  -------------
    1  PortChannel1   LACP(A)(N/A)  Ethernet1(D)
    2  PortChannel2   LACP(A)(N/A)  Ethernet2(S)
    3  PortChannel3   LACP(A)(N/A)  Ethernet3(D)
    4  PortChannel4   LACP(A)(N/A)  Ethernet4(D)
    5  PortChannel5   LACP(A)(N/A)  Ethernet5(D)
    6  PortChannel6   LACP(A)(N/A)  Ethernet6(D)
    7  PortChannel7   LACP(A)(N/A)  Ethernet7(D)
    8  PortChannel8   LACP(A)(N/A)  Ethernet8(D)
    9  PortChannel9   LACP(A)(N/A)  Ethernet9(D)
   10  PortChannel10  LACP(A)(N/A)  Ethernet10(D)
   11  PortChannel11  LACP(A)(Up)   Ethernet11(D)
   12  PortChannel12  LACP(A)(Up)   Ethernet12(D)
   13  PortChannel13  LACP(A)(Up)   Ethernet13(D)
   14  PortChannel14  LACP(A)(N/A)  Ethernet14(D)
   15  PortChannel15  LACP(A)(N/A)  Ethernet15(D)
   16  PortChannel16  LACP(A)(N/A)  Ethernet16(D)
   17  PortChannel17  LACP(A)(N/A)  Ethernet17(D)
   18  PortChannel18  LACP(A)(Up)   Ethernet18(D)
   19  PortChannel19  LACP(A)(N/A)  Ethernet19(D)
   20  PortChannel20  LACP(A)(Up)   Ethernet20(D)
root@sonic:/home/admin# 

It looks the portchannel config in /etc/network/interface will bring up the member Ethernet interface.
While if the admin status of member Ethernet interface is up, portchannel create will fail.

root@sonic:/home/admin# teamshow 
Flags: A - active, I - inactive, Up - up, Dw - Down, N/A - not available, S - selected, D - deselected
  No.  Team Dev       Protocol     Ports
-----  -------------  -----------  -------------
    1  PortChannel1   N/A
    2  PortChannel2   N/A
    3  PortChannel3   N/A
    4  PortChannel4   N/A
    5  PortChannel5   N/A
    6  PortChannel6   N/A
    7  PortChannel7   N/A
    8  PortChannel8   N/A
    9  PortChannel9   N/A
   10  PortChannel10  LACP(A)(Up)  Ethernet10(S)
   11  PortChannel11  LACP(A)(Up)  Ethernet11(S)
   12  PortChannel12  LACP(A)(Up)  Ethernet12(S)
   13  PortChannel13  LACP(A)(Up)  Ethernet13(S)
   14  PortChannel14  N/A
   15  PortChannel15  N/A
   16  PortChannel16  N/A
   17  PortChannel17  N/A
   18  PortChannel18  LACP(A)(Up)  Ethernet18(S)
   19  PortChannel19  N/A
   20  PortChannel20  LACP(A)(Up)  Ethernet20(S)
root@sonic:/home/admin# ip link show Ethernet1 Ethernet2
Error: either "dev" is duplicate, or "Ethernet2" is a garbage.
root@sonic:/home/admin# ip link show Ethernet1          
947: Ethernet1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:05:64:30:73:c0 brd ff:ff:ff:ff:ff:ff
root@sonic:/home/admin# ip link show Ethernet2 
948: Ethernet2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:05:64:30:73:c0 brd ff:ff:ff:ff:ff:ff
root@sonic:/home/admin# ip link show Ethernet3
949: Ethernet3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:05:64:30:73:c0 brd ff:ff:ff:ff:ff:ff
root@sonic:/home/admin# ip link show Ethernet4
950: Ethernet4: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:05:64:30:73:c0 brd ff:ff:ff:ff:ff:ff
root@sonic:/home/admin# 
root@sonic:/home/admin# cat /etc/network/interfaces
#
# =============== Managed by SONiC Config Engine DO NOT EDIT! ===============
# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen
# file: /etc/network/interfaces
#
# The loopback network interface
auto lo
iface lo inet loopback
# Use command 'ip addr list dev lo' to check all addresses
iface lo inet static
    address 11.161.62.196
    netmask 255.255.255.255
#

# The management network interface
auto eth0
iface eth0 inet static
    address 30.57.185.38
    netmask 255.255.255.0
    ########## management network policy routing rules
    # management port up rules
    up ip -4 route add default via 30.57.185.254 dev eth0 table default
    up ip -4 route add 30.57.185.0/24 dev eth0 table default
    up ip -4 rule add from 30.57.185.38/32 table default
    # management port down rules
    down ip -4 route delete default via 30.57.185.254 dev eth0 table default
    down ip -4 route delete 30.57.185.0/24 dev eth0 table default
    down ip -4 rule delete from 30.57.185.38/32 table default
#
# "|| true" is added to suppress the error when interface is already a member of LAG
# "ip link show | grep -q master" is added to ensure interface is enslaved
allow-hotplug Ethernet1
iface Ethernet1 inet manual
    pre-up teamdctl PortChannel1 port add Ethernet1 || true
    post-up ip link show Ethernet1 | grep -q master && ifconfig Ethernet1 up
    post-down ifconfig Ethernet1 down
#
allow-hotplug Ethernet10
iface Ethernet10 inet manual
    pre-up teamdctl PortChannel10 port add Ethernet10 || true
    post-up ip link show Ethernet10 | grep -q master && ifconfig Ethernet10 up
    post-down ifconfig Ethernet10 down
#
allow-hotplug Ethernet11
iface Ethernet11 inet manual
    pre-up teamdctl PortChannel11 port add Ethernet11 || true
    post-up ip link show Ethernet11 | grep -q master && ifconfig Ethernet11 up
    post-down ifconfig Ethernet11 down
#
allow-hotplug Ethernet12
iface Ethernet12 inet manual
    pre-up teamdctl PortChannel12 port add Ethernet12 || true
    post-up ip link show Ethernet12 | grep -q master && ifconfig Ethernet12 up
    post-down ifconfig Ethernet12 down
#
allow-hotplug Ethernet13
iface Ethernet13 inet manual
    pre-up teamdctl PortChannel13 port add Ethernet13 || true
    post-up ip link show Ethernet13 | grep -q master && ifconfig Ethernet13 up
    post-down ifconfig Ethernet13 down
#
allow-hotplug Ethernet14
iface Ethernet14 inet manual
    pre-up teamdctl PortChannel14 port add Ethernet14 || true
    post-up ip link show Ethernet14 | grep -q master && ifconfig Ethernet14 up
    post-down ifconfig Ethernet14 down
#
allow-hotplug Ethernet15
iface Ethernet15 inet manual
    pre-up teamdctl PortChannel15 port add Ethernet15 || true
    post-up ip link show Ethernet15 | grep -q master && ifconfig Ethernet15 up
    post-down ifconfig Ethernet15 down
#
allow-hotplug Ethernet16
iface Ethernet16 inet manual
    pre-up teamdctl PortChannel16 port add Ethernet16 || true
    post-up ip link show Ethernet16 | grep -q master && ifconfig Ethernet16 up
    post-down ifconfig Ethernet16 down
#
allow-hotplug Ethernet17
iface Ethernet17 inet manual
    pre-up teamdctl PortChannel17 port add Ethernet17 || true
    post-up ip link show Ethernet17 | grep -q master && ifconfig Ethernet17 up
    post-down ifconfig Ethernet17 down
#
allow-hotplug Ethernet18
iface Ethernet18 inet manual
    pre-up teamdctl PortChannel18 port add Ethernet18 || true
    post-up ip link show Ethernet18 | grep -q master && ifconfig Ethernet18 up
    post-down ifconfig Ethernet18 down
#
allow-hotplug Ethernet19
iface Ethernet19 inet manual
    pre-up teamdctl PortChannel19 port add Ethernet19 || true
    post-up ip link show Ethernet19 | grep -q master && ifconfig Ethernet19 up
    post-down ifconfig Ethernet19 down
#
allow-hotplug Ethernet2
iface Ethernet2 inet manual
    pre-up teamdctl PortChannel2 port add Ethernet2 || true
    post-up ip link show Ethernet2 | grep -q master && ifconfig Ethernet2 up
    post-down ifconfig Ethernet2 down
#
allow-hotplug Ethernet20
iface Ethernet20 inet manual
    pre-up teamdctl PortChannel20 port add Ethernet20 || true
    post-up ip link show Ethernet20 | grep -q master && ifconfig Ethernet20 up
    post-down ifconfig Ethernet20 down
#
allow-hotplug Ethernet3
iface Ethernet3 inet manual
    pre-up teamdctl PortChannel3 port add Ethernet3 || true
    post-up ip link show Ethernet3 | grep -q master && ifconfig Ethernet3 up
    post-down ifconfig Ethernet3 down
#
allow-hotplug Ethernet4
iface Ethernet4 inet manual
    pre-up teamdctl PortChannel4 port add Ethernet4 || true
    post-up ip link show Ethernet4 | grep -q master && ifconfig Ethernet4 up
    post-down ifconfig Ethernet4 down
#
allow-hotplug Ethernet5
iface Ethernet5 inet manual
    pre-up teamdctl PortChannel5 port add Ethernet5 || true
    post-up ip link show Ethernet5 | grep -q master && ifconfig Ethernet5 up
    post-down ifconfig Ethernet5 down
#
allow-hotplug Ethernet6
iface Ethernet6 inet manual
    pre-up teamdctl PortChannel6 port add Ethernet6 || true
    post-up ip link show Ethernet6 | grep -q master && ifconfig Ethernet6 up
    post-down ifconfig Ethernet6 down
#
allow-hotplug Ethernet7
iface Ethernet7 inet manual
    pre-up teamdctl PortChannel7 port add Ethernet7 || true
    post-up ip link show Ethernet7 | grep -q master && ifconfig Ethernet7 up
    post-down ifconfig Ethernet7 down
#
allow-hotplug Ethernet8
iface Ethernet8 inet manual
    pre-up teamdctl PortChannel8 port add Ethernet8 || true
    post-up ip link show Ethernet8 | grep -q master && ifconfig Ethernet8 up
    post-down ifconfig Ethernet8 down
#
allow-hotplug Ethernet9
iface Ethernet9 inet manual
    pre-up teamdctl PortChannel9 port add Ethernet9 || true
    post-up ip link show Ethernet9 | grep -q master && ifconfig Ethernet9 up
    post-down ifconfig Ethernet9 down
#

admin@sonic:~$ docker exec -it teamd /bin/bash
root@sonic:/# ps -x
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss+    0:00 /usr/bin/python /usr/bin/supervisord
  273 ?        Sl     0:00 /usr/sbin/rsyslogd -n
  278 ?        S      0:00 bash /usr/bin/teamd.sh
  286 ?        S      0:00 teamd -f /etc/teamd/PortChannel10.conf -d
  289 ?        S      0:00 teamd -f /etc/teamd/PortChannel11.conf -d
  292 ?        S      0:00 teamd -f /etc/teamd/PortChannel12.conf -d
  295 ?        S      0:00 teamd -f /etc/teamd/PortChannel13.conf -d
  310 ?        S      0:00 teamd -f /etc/teamd/PortChannel18.conf -d
  319 ?        S      0:00 teamd -f /etc/teamd/PortChannel20.conf -d
  341 ?        Sl     0:00 teamsyncd
  457 ?        Ss     0:00 /bin/bash
  463 ?        R+     0:00 ps -x
root@sonic:/# teamd -f /etc/teamd/PortChannel10.conf -d^C
root@sonic:/# ip link show Ethernet6
952: Ethernet6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:05:64:30:73:c0 brd ff:ff:ff:ff:ff:ff
root@sonic:/# teamd -f /etc/teamd/PortChannel6.conf -d
This program is not intended to be run as root.
Daemon process failed.
Failed: Device or resource busy
root@sonic:/# 
root@sonic:/# 
root@sonic:/# ip link set down  Ethernet6
root@sonic:/# teamd -f /etc/teamd/PortChannel6.conf -d
This program is not intended to be run as root.
root@sonic:/# 
@lguohan
Copy link
Collaborator

lguohan commented Aug 24, 2018

I also see such issue, not sure if it is caused by kernel or not. maybe it is related the /etc/network/interface refactor. @stcheng , can you take a look?

@jipanyang
Copy link
Collaborator Author

@hzheng5 has some change in teamd.sh to bring the member ports down before creating portchannel, then bring member up again. The change seemed to work and fixed the problem in my test setup.

@hzheng5
Copy link
Contributor

hzheng5 commented Aug 24, 2018

here is the new start_app function we are using

function start_app {
    rm -f /var/run/teamd/*
    if [ "$(ls -A $TEAMD_CONF_PATH)" ]; then
        for f in $TEAMD_CONF_PATH/*; do
            members=""
            pc_conf="${f:11}"
            for member in $(sonic-cfggen -d -v "PORTCHANNEL['"${pc_conf%.*}"']['members'] | join(' ')" ); do
                members="$members"" $member"
                logger -p notice "teamd set link $member down"
                ip link set $member down
            done
            logger -p notice "teamd create ""$f"
            teamd -f $f -d
            for member in $members; do
                if [ "down" == "$(sonic-cfggen -d -v "PORT['"$member"']['admin_status']")" ]; then
                    logger -p notice "teamd shutdown ""$member"
                    ip link set $member down
                fi
            done
        done
        for pc in `sonic-cfggen -d -v "PORTCHANNEL.keys() | join(' ') if PORTCHANNEL"`; do
            ip link set $pc up
        done

    fi
    teamsyncd &
}

Please let us now if you want to merge the change into master branch.

Thanks,

@stcheng
Copy link
Contributor

stcheng commented Aug 24, 2018

thanks i'll test this

@stcheng
Copy link
Contributor

stcheng commented Aug 28, 2018

Hello @jipanyang and @hzheng5, in my previous pull request #1908, I have added the admin_status: up to only front panel ports by default in minigraph.py file. Could you please check the configurations in your database to see if the port channel member ports are set to admin up? If yes, could you remove these configurations and test it again?

@hzheng5
Copy link
Contributor

hzheng5 commented Aug 28, 2018

Hi @stcheng ,

We can double check the config internally. But we still need to solve this issue when the member ports are set to be "admin up" ?

Thanks,
Haiyang

@stcheng
Copy link
Contributor

stcheng commented Aug 28, 2018

Hi @hzheng5, when ports are set as admin up, they cannot be enslaved due to the restriction of teamd. Do we want to have this behavior or not? If we want to have the behavior of enslaving member ports into a port channel regardless of the admin status, we could force to bring down the ports. If we want to have teamd's restrictions, then we could clean up the unnecessary configurations in the database.

@Alibaba-Sonic
Copy link

Alibaba-Sonic commented Aug 28, 2018 via email

@prsunny
Copy link
Contributor

prsunny commented Aug 29, 2018

Just a thought that, if the interface is already up and if you bring-down the interface, the peer may see link down. However, if we have to fix this, I would go for # 2.

@stcheng
Copy link
Contributor

stcheng commented Aug 30, 2018

Yes. I think the second approach is preferred. But one more question here, if we configure the member port as admin down before enslaving the port, will we need to manually bring down the port after the port is enslaved?

@prsunny
Copy link
Contributor

prsunny commented Aug 30, 2018

No I think. Say if we bring down, then at what point we want to bring it up? But if we want to support lag member up/down, then after enslaving the port, we want to check what is the user configured admin state and if it is down, we have to bring the port down, else if user has it as admin up, then, no-op.

@hzheng5
Copy link
Contributor

hzheng5 commented Aug 30, 2018

For #2, here are the suggested steps inside /usr/bin/teamd.sh to start teamd

  1. force the member ports to be admin down
  2. create the portchannel and add the member ports into the lag
  3. bring up/down the member ports based on their "admin status" in configure db.
  4. bring up/down the portchannels based on their "admin status" in configure db.

Thanks,
Haiyang

@stcheng
Copy link
Contributor

stcheng commented Nov 19, 2018

this issue has already been resolved.

@stcheng stcheng closed this as completed Nov 19, 2018
vivekrnv pushed a commit to vivekrnv/sonic-buildimage that referenced this issue Jan 6, 2022
Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com>

30f5dd6 Update the example for pfcwd start command (sonic-net#1984)
9e30871 [Auto Techsupport] Event driven Techsupport Bug Fixes (sonic-net#1986)
fbd565d Fix wrong help message for cable length setting (sonic-net#1978)
b3a5052 [GCU] Using simulated config instead of target config when validating replace operation in NoDependencyMoveValidator (sonic-net#1987)
35cb524 [GCU] Copying config_db before callding sonic_yang.loadData (sonic-net#1983)
a98858d [GCU] Different apply-patch runs should produce same sorted steps (sonic-net#1988)
8c81ae3 [breakout] Fix the check  when port is not present in BREAKOUT_CFG table (sonic-net#1765)
bc8fe7c [doc][DPB] Update DPB related interface breakout command Info (sonic-net#1438)
1a2a9a3 [config] Fix 'config reload -l' command to get filename by default (sonic-net#1611)
ed2fa69 [debug dump util] FDB debug dump util changes (sonic-net#1968)
3b642c9 [GCU] Loading yang-models only once (sonic-net#1981)
bb56fc2 Update swss_ready check to check per namespace swss service (sonic-net#1974)
4f39f9f [GCU] Moving PatchSorter unit-test to json file to make it easier to read/maintain (sonic-net#1977)
1a75870 [CLI][Help string] Changed the show command help text to be more consistent with each other.
818dcbf [GCU] Implementing DryRun by printing patch-sorter steps/imitating config_db (sonic-net#1973)
judyjoseph added a commit that referenced this issue Jan 9, 2022
4236bc4 [config reload] Fixing config reload when timer based delayed services are disabled (#1967)
d2514e4 [GCU] Different apply-patch runs should produce same sorted steps (#1988)
2878adb [GCU] Using simulated config instead of target config when validating replace operation in NoDependencyMoveValidator (#1987)
fb8ca98 [GCU] Loading yang-models only once (#1981)
f88ee92 [GCU] Copying config_db before callding sonic_yang.loadData (#1983)
9ed0e91 [GCU] Implementing DryRun by printing patch-sorter steps/imitating config_db (#1973)
b36b5e3 [GCU] Moving PatchSorter unit-test to json file to make it easier to read/maintain (#1977)
c0fa28b [generic-config-updater] Improving CreateOnly validator and marking /LOOPBACK_INTERFACE/LOOPBACK#/vrf_name as create-only (#1969)
0559d04 [generic-config-updater] Adding non-strict mode (#1929)
b07f477 [debug dump util] FDB debug dump util changes (#1968)
6d8757a [warm/fast-reboot] Fix kexec portion to support platforms based on Device Tree (#1966)
cc1409e [Auto Techsupport] Event driven Techsupport Bug Fixes (#1986)
6c48bd5 Fix wrong help message for cable length setting (#1978)
c0bbbe3 [breakout] Fix the check  when port is not present in BREAKOUT_CFG table (#1765)
5bb8cad [doc][DPB] Update DPB related interface breakout command Info (#1438)
e6fd990 [config] Fix 'config reload -l' command to get filename by default (#1611)
bd8f7bb Update swss_ready check to check per namespace swss service (#1974)
5439f94 [soft-reboot] Add support for platforms based on Device Tree (#1963)
7c5810a [config] Add portchannel support  for static route  (#1857)
7cb6a1b preserve old order for config reload (#1964)
20bddbd [Auto-Techsupport] Issues related to Multiple Cores crashing handled (#1948)
taras-keryk pushed a commit to taras-keryk/sonic-buildimage that referenced this issue Apr 28, 2022
#### What I did
Loading sonic-yang models only once, and re-using them. This makes the sorting a lot faster.

How to verify `loadYangModel` took a lot of time?

Add the following snippet to `TestPatchSorter`
```python
from pstats import Stats
import cProfile
class TestPatchSorter(...):
    def setUp(self):
        """init each test"""
        self.pr = cProfile.Profile()
        self.pr.enable()
        print("\n<<<---")
    def tearDown(self):
        """finish any test"""
        p = Stats (self.pr)
        p.strip_dirs()
        p.sort_stats ('cumtime')
        p.print_stats ()
        print("\n--->>>")
    .
    .
    .
    # Also update verify(self, cc_ops=[], tc_ops=[]) by commenting out changes validation to avoid extra calls to loadYangModels 
    def verify(self, cc_ops=[], tc_ops=[]):
        # Arrange
        config_wrapper=ConfigWrapper()
        target_config=jsonpatch.JsonPatch(tc_ops).apply(Files.CROPPED_CONFIG_DB_AS_JSON)
        current_config=jsonpatch.JsonPatch(cc_ops).apply(Files.CROPPED_CONFIG_DB_AS_JSON)
        patch=jsonpatch.make_patch(current_config, target_config)

        # Act
        actual = self.create_patch_sorter(current_config).sort(patch)

        # Assert
        # simulated_config = current_config
        # for move in actual:
        #     simulated_config = move.apply(simulated_config)
        #     self.assertTrue(config_wrapper.validate_config_db_config(simulated_config))
        # self.assertEqual(target_config, simulated_config)

```
Run
```
> python3 -m unittest patch_sorter_test.TestPatchSorter.test_sort__dpb_1_to_4__success 
.
.
.
         48986582 function calls (48933431 primitive calls) in 104.530 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000  104.530  104.530 case.py:549(_callTestMethod)
        1    0.000    0.000  104.530  104.530 patch_sorter_test.py:1889(test_sort__dpb_1_to_4__success)
        1    0.000    0.000  104.529  104.529 patch_sorter_test.py:1933(verify)
        1    0.005    0.005  104.527  104.527 patch_sorter.py:1332(sort)
     32/1    0.006    0.000  104.077  104.077 patch_sorter.py:955(sort)
      334    0.012    0.000   99.498    0.298 patch_sorter.py:310(validate)
      492    2.140    0.004   95.810    0.195 sonic_yang_ext.py:30(loadYangModel)  <=========
```

From the above we can see profiling data about test_sort__dpb_1_to_4__success:
- Took 104.53s to complete
- loadYangModel was called 492 times
- loadYangModel took 95.810s.

loadYangModel is the method that loads the yang models from memory into SonicYang object. The loading of the YANG models should only happen once.

#### How I did it
Moved all calls to create sonic_yang object to ConfigWrapper, and each call to create a new instance just fills in the data for the yang models.

#### How to verify it
unit-test

Running profiling after the update:
```
> python3 -m unittest patch_sorter_test.TestPatchSorter.test_sort__dpb_1_to_4__success 
.
.
.
         702096 function calls (648951 primitive calls) in 2.882 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.882    2.882 case.py:549(_callTestMethod)
        1    0.000    0.000    2.882    2.882 patch_sorter_test.py:1890(test_sort__dpb_1_to_4__success)
        1    0.002    0.002    2.881    2.881 patch_sorter_test.py:1934(verify)
        1    0.000    0.000    2.874    2.874 patch_sorter.py:1332(sort)
     32/1    0.004    0.000    2.705    2.705 patch_sorter.py:955(sort)
      334    0.008    0.000    2.242    0.007 patch_sorter.py:310(validate)
      490    0.080    0.000    1.791    0.004 sonic_yang_ext.py:1043(loadData)
      332    0.043    0.000    1.655    0.005 patch_sorter.py:345(validate)
      332    0.018    0.000    1.509    0.005 gu_common.py:112(validate_config_db_config)
        .
        .
        .
        1    0.002    0.002    0.164    0.164 sonic_yang_ext.py:30(loadYangModel)
```
From the above we can see profiling data about test_sort__dpb_1_to_4__success:
- Took 2.882s to complete
- loadYangModel was called 1time
- loadYangModel took 0.164s.

[profiling-after.txt](https://github.com/Azure/sonic-utilities/files/7757252/profiling-after.txt)

#### Previous command output (if the output of a command-line utility has changed)

#### New command output (if the output of a command-line utility has changed)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants