Append Bridge vlan values

I’m attempting to set some values under the /interface bridge vlan command, namely the untagged property. Normally, I set this like so:


set bridge=BR1 tagged=ether4 [find vlan-ids=10]> .

However, I need a way to append the value to what is already present. Here’s what I’ve cobbled together so far, but it does not work correctly.

A full example is shown below.

Example:

# Script Setup
/interface bridge add name=BR1 protocol-mode=none vlan-filtering=no
/interface bridge vlan 
add bridge=BR1 untagged=ether2 vlan-ids=10

# How to Append "ether4" to array?
set bridge=BR1 untagged=([get value-name=untagged]",ether4") [find vlan-ids=10]

set untagged=([get value-name=untagged [find vlan-ids=10]],“ether4”) [find vlan-ids=10]

Is there a reason you explicitly set the untagged= parameter as this will be dynamically populated from the pvid= parameter under /interface bridge port for bridge members and /interface bridge for the bridge itself. This avoids the possibility of mismatches which will cause unexpected behaviour.

I am considering removing lines referencing the untagged member because of the reasons you note. I also needed to set the tagged member as well. I really appreciate the help. I’m looking into how to set Hybrid ports in an easy to show way.

LOL. I guess not may folks have tried scripting an existing bridge’s trunk ports in 3 years… This problem is since /interface/bridge/vlan’s vlan-ids attribute is an ARRAY type… so [find vlan-ids=10] does not work against the array type. I was hoping I was missing something google/search of forum does not offer advice here…

Now at least since 7.16, access ports can be handled automatically by the “dynamic” entries created by a /interface/vlan and setting pvid= on /interface/bridge/port - so that part has gotten easier (adding L3 /interface/vlan on vlan bridge, will add bridged to a dynamic tagged=) - so one less modification needed. But a script to “add a tagged port” is far from simple, and still working on one… got me here…

I’ve been trying create some “automated” bridged VLAN scripts (see part 1: http://forum.mikrotik.com/t/example-of-automating-vlan-creation-removal-inspecting-using-mkvlan-friends/181480/6), but the part 2 with some scripts to mange “bridge vlan filtering” part is way trickier… The only approach that I’ve found is some complex code that loops over “dynamic=no” in /interface/bridge/vlans… then :foreach over the vlan-ids ARRAY to see if matches one I’m looking for, then do a SET (or if none found, over the two loops, then ADD new /interface/bridge/vlan).

If anyone knows a better technique or trick here, I’m be curious to know.

Maybe this helps:

[find dynamic=no vlan-ids=[:if ([:len [:find $"vlan-ids" <VLAN_ID>]]) do={:return $"vlan-ids"}]]

or with function for reuse:

:local inArray do={:if ([:len [:find $1 $2]]) do={:return $1}}
... [find dynamic=no vlan-ids=[$inArray $"vlan-ids" <VLAN_ID>]]

LOL, I thought some [find (code)] trick might work – it was the embed :find in the find I didn’t think about. Good work!

Now whether a “configuration language” for a router should require turn adding access/trunk ports into a LeetCode exercise is a entirely different question :wink:.
IMO, there should be some find operator for array membership, like “[find vlan-id has <VLAN_ID>]”. They have a “in” operator, but that only works for ip-prefix.

For example even with @optio shortcut, it’s not very clean - and remove is harder. I think this is right to do tagging of a port on vlan – without a bunch of :foreach things, but would have to test this more to be 100%:

:global mktrunk do={
        :local bvid [/interface/bridge/vlan find dynamic=no vlan-ids=[:if ([:len [:find $"vlan-ids" $1]]) do={:return $"vlan-ids"}]]
        :if ([:len $bvid]=0) do={
            :set bvid [/interface/bridge/vlan add vlan-ids=$1 comment="added by $0" bridge=[/interface/bridge/find vlan-filtering=yes disabled=no]] 
        }
        /interface/bridge/vlan set $bvid tagged=([get $bvid tagged],$2)
    }

 :global rmtrunk do={
        :local bvid [/interface/bridge/vlan find dynamic=no vlan-ids=[:if ([:len [:find $"vlan-ids" $1]]) do={:return $"vlan-ids"}]]
        :local orig [/interface/bridge/vlan get $bvid tagged] 
        :local final [:toarray ""]
        :foreach i in=$orig do={ :if ($i != "$2") do={:set final ($final, $i)} }
        /interface/bridge/vlan set $bvid tagged=$final
        # optional, if there are no more tagged or untagged ports, remove bridge vlan itself        
        :if (([:len [/interface/bridge/vlan get $bvid tagged]]=0) and ([:len [/interface/bridge/vlan get $bvid untagged]]=0)) do={
            /interface/bridge/vlan remove $bvid
        }
        # while mktrunk could take an array of interface, rmtrunk must be a single interface in $2 
 }

# create
    $mktrunk 123 ether4
# update
    $mktrunk 123 ether5
# remove
    $rmtrunk 123 ether5
# note: array is only support on mktrunk, since it was automatic
    $mktrunk 123 ("ether5","ether6")
# but rmtrunk does NOT accept an array and will not find/remove anything

Anyway the above is cleaner than what I started with… So thanks!

Use function (global or pass it as argument of another function) for reuse in find command instead c/p same code in worker functions, but I agree some additional operator (or in to work for arrays too) to find value in array would be much cleaner.
1337 code is here to trick interpreter to get variable value from context when is not defined in code and having dash character in name - $“” :slight_smile:
For removing vlan, I don’t see currently simple way than filtering vlan ids array on tagged and removing vlan id value from it.

I’m not sure if this is what you are talking about, but I was looking for a way to add bridge ports to an existing vlan using cli.

:local vlanId 30
:local bridgeName "bridge"
:local newPort "sfp-sfpplus3"

:local vlanEntry [/interface bridge vlan find where bridge=$bridgeName and vlan-ids=$vlanId]

:local currentTagged [/interface bridge vlan get $vlanEntry tagged]
:put [:len $currentTagged]

:if ([:len $currentTagged] > 0) do={
    :local updatedTagged ($currentTagged, $newPort)
    /interface bridge vlan set $vlanEntry tagged=$updatedTagged
} else={
    /interface bridge vlan set $vlanEntry tagged=$newPort
}

:put ("Port " . $newPort . " added to VLAN " . $vlanId . " as tagged.")

That only work if VLAN already existed in /interface/bridge/vlan. Now you would have the bridge vlan entry if you already had a /interface/vlan in 7.16+, since one be created dynamically. But otherwise you need an “add”… not set.