Script to reset "stuck" BGP signaled VPLS interfaces and instances

Hi all,

From time to time on my network I have issues with certain BGP signaled VPLS suddenly stopping. I got sick of having to manually fix these so now there is a script to handle it. I know that other people are also having this problem, so hopefully this might be of use to others, as well as bringing attention to the issue since my ticket with MikroTik support (SUP-127062) has been open for a VERY LONG time and not getting much love :frowning:

I have tried all of the various digital snake oil fixes that other forum users have suggested i.e. synchronising IGP/LDP timers etc. without any success.

# Declare variables
:local ScriptName "Stuck VPLS fixer"
:local ScriptVersion "1.4"
:local countofTypeB;
 
# Print the banner with the name and version of the script
:put "Running script: $ScriptName - v$ScriptVersion";
  
# Detect if the script is already running, and if so, then exit
:if ([/system script job print count-only as-value where script=[:jobname] ] > 1) do={
    :log error "$ScriptName script is already running - Aborting";
    :error "$ScriptName script is already running - Aborting"
}
    
# Check for Type-A - VPLS interfaces without running flag
:put "Checking for Type-A stuck VPLS";
 
:if ([:len [/interface/vpls/find where dynamic=yes running=no]] = 0) do={
    :put "No Type-A stuck VPLS interfaces found";
} else={
    :put "Found $[:len [/interface/vpls/find where dynamic=yes running=no]] Type-A stuck VPLS interface(s).";
    :log warning "Found $[:len [/interface/vpls/find where dynamic=yes running=no]] stuck Type-A VPLS interface(s).";
}
  
# Reset any BGP VPLS instances that we found stuck interfaces on
:foreach vpls in=[/interface vpls find dynamic=yes running=no] do={
    :local bgpVpls [/interface vpls get $vpls bgp-vpls]
    :foreach vpls in=$bgpVpls do={
        :put "Disabling VPLS: $vpls"
        /routing/bgp/vpls/set $vpls disabled=yes
        :delay 0.1s
        :put "Enabling VPLS: $vpls"
        /routing/bgp/vpls/set $vpls disabled=no
        :delay 0.05s
    }
}
 
# Type-B - VPLS bridge ports with no DMAC
# Note that due to the methodology we might get false matches with VPLS that simply do not have any MACs learned vs a genuine loss of learning
:put "Checking for suspected Type-B stuck VPLS";
 
:foreach bridgeId in=[/interface/bridge/find] do={
    :local bridgeName [/interface/bridge/get $bridgeId name];
    :local vplsDCount [:len [/interface/bridge/host/find where bridge~$bridgeName interface~"^vpls\\d+" dynamic=yes local=no]];
    :local vplsDLCount [:len [/interface/bridge/host/find where bridge~$bridgeName interface~"^vpls\\d+" dynamic=yes local=yes]];
 
    # If the bridge being checked has hosts on vpls interfaces with the DL flags set, but not any hosts with the D flag set, then reset the VPLS instance that the bridge belongs to.
    :if ($vplsDLCount > 0 and $vplsDCount = 0) do={
        :local vplsId [/routing/bgp/vpls find bridge=$bridgeName name];
        :local vpls [/routing/bgp/vpls get $vplsId name];
        :put "Disabling VPLS instance: $vpls";
        /routing/bgp/vpls/set $vpls disabled=yes;
        :delay 0.1s;
        :put "Enabling VPLS instance: $vpls";
        /routing/bgp/vpls/set $vpls disabled=no;
        :set countofTypeB ($countofTypeB+1);
        :delay 0.05s;
    }
}
 
# Report the number of Type-B resets, if any
:if ($countofTypeB > 0) do={
    :put "Reset $countofTypeB suspected stuck Type-B VPLS instance(s).";
    :log warning "Reset $countofTypeB suspected stuck Type-B VPLS instance(s).";
}
 
:put "Completed";