Pairing a FortiGate and FortiSwitch the Right Way, Part 2: FortiLink, and Where We Actually Went Wrong

Part 1 covered the groundwork — getting the FortiGate 70G and FortiSwitch 124F onto matching FortiOS/FortiSwitchOS 7.6.6, and making sure NTP and DNS were actually solid before going anywhere near a FortiLink cable. This part covers the bit we actually attempted: the FortiLink pairing itself, what’s supposed to happen, what happened to us, and the sequence I’m going to run when we wipe both units and go again.

Short version up front, for anyone landing here mid-troubleshoot: if your FortiSwitch is stuck showing Offline under a freshly-built FortiLink interface, check NTP reachability and the fortilink-neighbor-detect / LLDP settings before you touch anything else. That’s where ours was hiding.

The process, as it’s supposed to go

FortiLink pairing, done in the right order on healthy firmware, is genuinely close to plug-and-play:

  1. Cable into an auto-discovery port. On FortiSwitchOS 3.4.0 and later, the last four ports on the switch are auto-discovery FortiLink ports by default — connect one of those to the FortiGate and the switch needs zero manual configuration to start the handshake.
  2. Build the FortiLink interface on the FortiGate. WiFi & Switch Controller → FortiLink Interface → Create New, then add the connected port(s) as interface members. FortiLink works on a single physical port, an aggregate (802.3ad), or a hardware/software switch group — anything except the HA and MGMT ports.
  3. Decide on auto-authorization. Tick Automatically authorize devices and a discovered switch goes from Unauthorized straight to provisioning with no further clicks. Leave it off and you authorize manually from WiFi & Switch Controller → Managed FortiSwitch — right-click the discovered serial and choose Authorize, or use the Authorize button at the top of the list.
  4. Let the FortiGate provision it. Once authorized, budget two to five minutes for the FortiGate to push its base configuration template — and, if you’ve got forced firmware upgrade configured, a matching firmware image too.
  5. Watch for Online, not just Authorized. A switch can sit there recognized, with a serial number and an Authorized badge, and never flip to Online. That gap — recognized-but-not-online — is almost always one of: firmware mismatch, a certificate problem, or a failed DTLS/CAPWAP handshake. All three trace back to the same small set of root causes, and ours was one of them.

That’s the textbook flow. Here’s where ours departed from it.

Where we actually got stuck

Our FortiSwitch came up as discovered — serial number visible, status Unauthorized — so the FortiLink discovery frames were clearly making it across the wire. We authorized it manually. And it sat there. Not failed, not erroring — just parked, never transitioning to Online, while client traffic kept passing through it completely normally. Genuinely one of the more disorienting states a piece of network kit can be in: it works, but it won’t manage.

Two things were stacked on top of each other, and untangling them is the actual lesson here.

This is exactly the trap flagged in Part 1, except living it is more instructive than reading about it. Pulling show system ntp on the switch showed NTP servers configured and ntpsync enable — but none of them reachable from where the switch actually sits, behind the FortiLink interface rather than out on the LAN. A packet capture on the FortiGate (diagnose sniffer packet any "port 123") confirmed it: outbound NTP requests, no replies. One-way traffic on UDP/123, going nowhere.

The fix has two parts, and missing either one leaves you exactly where we were:

a. A firewall policy that actually permits the FortiLink subnet out to your NTP source:

config firewall policy
    edit 1
        set name "fortilink-to-internet"
        set srcintf "fortilink"        <- your FortiLink interface name
        set dstintf "wan1"             <- your egress toward the internet/NTP source
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set service "all"
        set nat enable
    next
end

A more scoped service object than “all” is obviously the better long-term answer — but for getting the link up and proving the theory, permit first, tighten after.

b. NTP relayed through the FortiLink interface itself, so the switch doesn’t need its own route out to the internet at all — it just asks the FortiGate, which is sitting right there:

config system ntp
    set ntpsync enable
    set server-mode enable
    set interface "fortilink"
end

In the GUI, this lives under System → Settings, in the FortiLink interface’s Advanced → NTP server section — easy to miss because it doesn’t look like it belongs to FortiLink at first glance; it looks like a general system setting. And critically: changing this requires a reboot of the FortiSwitch to take effect. We made the config change and then sat there for ten minutes wondering why nothing had changed — because nothing had, yet. The switch was still running on its old, broken NTP config until it came back up.

2. A default that quietly changed underneath us

Even with NTP sorted, there was a second gremlin — and this one is genuinely subtle, because it’s a behavioural default change between point releases that doesn’t announce itself anywhere obvious.

Starting in FortiOS 7.6.1, the fortilink-neighbor-detect setting on FortiLink-enabled interfaces — which controls how the FortiGate discovers connected FortiSwitches — defaults to lldp instead of the older fortilink mode. This is a deliberate, documented direction-of-travel change (FortiLink’s own discovery protocol is gradually being superseded by LLDP- and CAPWAP-based discovery), but it has a sharp edge: if your FortiGate didn’t already have lldp-reception and lldp-transmission enabled — globally and on the FortiLink interface — before you upgraded into 7.6.1 or later, the interface ends up configured to discover switches via a protocol it isn’t actually sending or receiving. The result is exactly the symptom we saw: a switch that’s clearly on the wire, clearly passing traffic, and stubbornly invisible to the controller.

Two ways to fix it — pick whichever matches how you want the fabric to behave going forward, not just which is faster:

Enable LLDP properly (the forward-looking option, since this is where Fortinet’s headed):

config system global
    set lldp-reception enable
    set lldp-transmission enable
end

config system interface
    edit <FortiLink_Interface_Name>
        set lldp-reception enable
        set lldp-transmission enable
    next
end

…or roll the discovery method back to the classic behaviour (useful if you’re not ready to deal with LLDP-wide implications yet):

config system interface
    edit <FortiLink_Interface_Name>
        set fortilink-neighbor-detect fortilink
    next
end

One wrinkle worth knowing about before you go looking for it: hardware-switch-based FortiLink interfaces don’t expose fortilink-neighbor-detect directly. On those, the stp (Spanning Tree) setting does double duty — enable implicitly selects LLDP-based discovery, disable selects classic FortiLink discovery. If you’re on a hardware-switch FortiLink and hunting for a setting that the docs say should be there, that’s why you can’t find it: you’re tuning it via STP instead.

And the detail that made this one sting more than it should have: this only bites you on a 7.6.0 → 7.6.1-or-later upgrade path. Older branches (7.4.x and earlier) shipped with fortilink-neighbor-detect set to fortilink, and that setting is preserved across the upgrade — so anyone coming from 7.4 lands on 7.6.6 with the old behaviour intact and never sees this. It’s specifically the 7.6.0-as-a-starting-point crowd who get the rug pulled. Worth checking your own upgrade path against this before assuming it doesn’t apply to you.

The redo plan

When we factory-reset both units and run this again, the order is non-negotiable, and every step on this list exists because skipping it is what put us here:

  1. Firmware first, fully, on both devices — FortiGate 70G and FortiSwitch 124F both confirmed on 7.6.6, verified with get system status after every hop, not just the last one.
  2. NTP and DNS proven working before any FortiLink interface existsget system ntp status showing a small, stable offset; DNS resolution confirmed for whatever FQDN the NTP config actually uses. Not “configured.” Proven, with a command that shows a synced clock holding steady.
  3. The outbound policy for NTP traffic in place pre-emptively — not discovered three hours later via a packet capture taken in mild despair.
  4. fortilink-neighbor-detect and the global/interface LLDP settings checked explicitly — and set deliberately, not left to whatever the firmware’s default happens to be on this particular build. This is the one I’d never have thought to check without having been bitten by it first.
  5. Cable in, build the FortiLink interface, authorize — and then watch for Online, not just Authorized. If it parks at Authorized-but-not-Online for more than a few minutes, NTP and the discovery-protocol setting are now the first two things I check, in that order — not the last two.

If that sequence gets us a switch showing Online with a green light and a clean diagnose switch physical-ports linerate, I’ll come back and update this post — or write the “and here’s what actually happened when we tried it properly” follow-up. Either way, the lesson that’s already banked, regardless of how the redo goes: on Fortinet kit, the boring infrastructure services — time and name resolution — aren’t a footnote to the interesting configuration. They’re a prerequisite for it, and skipping past them mentally is exactly how you end up writing a post like this one instead of a much shorter one that just says “cabled it in, worked first time.”