- Using TCL Script: Follow the first two steps from the article below on how to enable and run TCL scripts in FortiManager: Technical Tip: How to use TCL script...existing route
Go to Device Manager -> Scripts, select type TCL Script, and select 'Create new'.
Create the following TCL script:
proc get_switch_mac_addrs {vdom_name} { # # Step 1: Check VDOM status # set status [exec "get system status\n" "# " 15] set vdom_enabled false if {![regexp {Virtual domain configuration: disable} $status]} { set vdom_enabled true } # # Step 2: Enter VDOM if enabled # if {$vdom_enabled} { puts "VDOMs are enabled. Entering VDOM: $vdom_name" exec "end\n" "# " 5 exec "config vdom\nedit $vdom_name\n" "# " 5 exec "config global\n" "# " 5 } else { puts "VDOMs are disabled. Continuing in default context." } # # Step 3: Get list of managed switches # set output [exec "get switch-controller managed-switch\n" "# " 10] if {$output eq ""} { puts "No managed switches found." return } # # Step 4: Get MAC cache output (only once) # set mac_cache [exec "diagnose switch-controller mac-cache show\n" "# " 10] # # Step 5: Loop through each switch # set current_switch "" foreach line [split $output "\n"] { if {[regexp {switch-id:\s+(\S+)} $line -> switch_id]} { puts "\n===========================" puts " Switch: $switch_id" puts "===========================" # # Find FortiSwitch MAC from mac-cache # set current_switch "" set switch_mac_found 0 foreach cache_line [split $mac_cache "\n"] { if {[regexp {^managed-switch:\s+(\S+)} $cache_line -> cache_switch]} { set current_switch $cache_switch } elseif {[regexp {^4094\s+0\s+([0-9a-fA-F:]+)} $cache_line -> mac]} { if {$current_switch eq $switch_id} { puts " FortiSwitch MAC : $mac" set switch_mac_found 1 } } } if {!$switch_mac_found} { puts " FortiSwitch MAC : <not found>" } # # Step 6: Get per-port MAC configs # set config_output [exec "show switch-controller managed-switch $switch_id\n" "# " 10] set current_port "" set port_has_mac 0 foreach cline [split $config_output "\n"] { if {[regexp {\s+edit\s+"([^"]+)"} $cline -> port]} { set current_port $port set port_has_mac 0 } elseif {[regexp {\s+set\s+mac-addr\s+([0-9a-fA-F:]+)} $cline -> port_mac]} { puts [format " %-7s: %s" $current_port $port_mac] set port_has_mac 1 } elseif {[regexp {\s+next} $cline]} { if {$port_has_mac == 0 && $current_port ne ""} { puts [format " %-7s: <no mac>" $current_port] } set current_port "" } } } } # # Step 7: Exit VDOM # if {$vdom_enabled} { exec "end\n" "# " 5 } } # # Call the function with VDOM name — replace "root" if needed # get_switch_mac_addrs "root"
Note:
- Using mac-cache (diagnose switch-controller mac-cache show), the scripts get the MAC address of connected FortiSwitches and then the MAC addresses of all physical ports of the FortiSwitch.
- The script takes into consideration whether VDOMs are enabled on the FortiGate. The default is set to 'root' (set in the last line of the script).
- The script can run on multiple FortiGates.
Sample output:

- Using JSON API with Postman: The API query below fetches the details of FortiSwitches connected to FortiGate using FortiManager.
{ "method": "get", "params": [ {
"url": "/pm/config/device/{{DEVICE_NAME}}/vdom/{{VDOM}}/switch-controller/managed-switch" } ], "id": "1", "verbose": 1, "session": "{{session}}" }
The response output of the query can be extensive depending on the number of switches connected.
In Postman, Script ('Post-run' or in older versions 'Tests') allows the use of JavaScript to show only specific output, in this case mac-addr of switch ports:

Sample script to show output as seen in the image above:
let data = pm.response.json();
let html = `
<style>
body { font-family: Arial, sans-serif; font-size: 13px; }
table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
th, td { padding: 6px; border: 1px solid #ddd; text-align: left; }
th { background-color: #f2f2f2; }
h3 { background-color: #e8e8e8; padding: 8px; border-left: 4px solid #007bff; }
</style>
`;
(data.result[0].data || []).forEach(switchObj => {
let sn = switchObj.sn || "Unknown";
html += `<h3>FortiSwitch Serial: ${sn}</h3>`;
html += `
<table>
<thead>
<tr>
<th>Port Name</th>
<th>MAC Address</th>
<th>Link Status</th>
</tr>
</thead>
<tbody>
`;
(switchObj.ports || []).forEach(port => {
html += `
<tr>
<td>${port["port-name"] || "-"}</td>
<td>${port["mac-addr"] || "-"}</td>
<td>${port["link-status"] || "-"}</td>
</tr>
`;
});
html += `</tbody></table>`;
});
pm.visualizer.set(html);
Related documents:
Tcl scripts.
Postman Scripts.
Technical Tip: How to troubleshoot TCL Scripts failed in FortiManager.
Technical Tip: How to fetch FortiAP and FortiSwitch Serials using TCL Script in FortiManager.
|