Forward Error Correction (FEC) is used to control and correct errors in data transmission by sending redundant data across the VPN in anticipation of dropped packets occurring during transit. The mechanism sends out x number of redundant packets for every y number of base packets.
Adaptive FEC considers link conditions and dynamically adjusts the FEC packet ratio:
The FEC base and redundant packet relationship is dynamically adjusted based on changes to the network SLA metrics defined in the SD-WAN SLA health checks. For example, when there is no or low packet loss in the network, FEC can work on a low redundant level sending only one redundant packet for every 10 base packets. As packet loss increases, the number of redundant packets sent can rise accordingly.
FEC can be applied only to streams that are sensitive to packet loss. For Example, policies that allow the UDP based VoIP protocol can enable FEC, while TCP based traffic policies do not. This reduces unnecessary bandwidth consumption by FEC.
Because FEC does not support NPU offloading, the ability to specify streams and policies that do not require FEC allows those traffic to be offloaded. This means that all traffic suffers a performance impact.
In this example, an IPsec tunnel is configured between two FortiGates that both have FEC enabled. The tunnel is an SD-WAN zone, and an SLA health-check is used to monitor the quality of the VPN overlay. The intention is to apply FEC to UDP traffic that is passing through the VPN overlay, while allowing all other traffic to pass through without FEC. An FEC profile is configured to adaptively increase redundant levels if the link quality exceeds a 10% packet loss threshold, or the bandwidth exceeds 950 Mbps.
The DMZ interface and IPsec tunnel vd1-p1 are SD-WAN members. FEC is enabled on vd1-p1, and health-check works on vd1-p1.
On both FortiGates, enable FEC and NPU offloading on the IPsec tunnel vd1-p1:
config vpn ipsec phase1-interface edit "vd1-p1" set npu-offload enable set fec-egress enable set fec-ingress enable next end
On FortiGate A, configure SD-WAN:
The VPN overlay member (vd1-p1) must be included in the health-check and configured as the higher priority member in the SD-WAN rule.
config system sdwan set status enable config zone edit "virtual-wan-link" next end config members edit 1 set interface "dmz" set gateway 172.16.208.2 next edit 2 set interface "vd1-p1" next end config health-check edit "1" set server "18.104.22.168" set members 2 config sla edit 1 next end next end config service edit 1 set name "1" set dst "all" set src "172.16.205.0" set priority-members 2 1 next end end
On FortiGate A, create a policy to specify performing FEC on UDP traffic, and a policy for other traffic:
config firewall policy edit 1 set srcintf "port5" set dstintf "virtual-wan-link" set action accept set srcaddr "172.16.205.0" set dstaddr "all" set schedule "always" set service "ALL_UDP" set fec enable next edit 2 set srcintf "any" set dstintf "any" set action accept set srcaddr "all" set dstaddr "all" set schedule "always" set service "ALL" next end
On FortiGate A, configure FEC mapping to bind network SLA metrics and FEC base and redundant packets:
config vpn ipsec fec edit "m1" config mappings edit 1 set base 8 set redundant 2 set packet-loss-threshold 10 next edit 2 set base 9 set redundant 3 set bandwidth-up-threshold 950000 next end next end
The mappings are matched from top to bottom: packet loss greater than 10% with eight base and two redundant packets, and then uploading bandwidth greater than 950 Mbps with nine base and three redundant packets.
On FortiGate A, apply the FEC mappings on vd1-p1:
config vpn ipsec phase1-interface edit "vd1-p1" set fec-health-check "1" set fec-mapping-profile "m1" set fec-base 10 set fec-redundant 1 next end
The FEC base and redundant values are used when the link quality has not exceeded the limits specified in the FEC profile mapping. If
fec-codecis set to
xorthe base and redundant packet values will not be updated.
Send TCP and UDP traffic from PC1 to PC2, then check the sessions on FortiGate A:
# diagnose sys session list session info: proto=6 proto_state=01 duration=12 expire=3587 timeout=3600 flags=00000000 socktype=0 sockport=0 av_idx=0 use=3 origin-shaper= reply-shaper= per_ip_shaper= class_id=0 ha_id=0 policy_dir=0 tunnel=/ vlan_cos=0/255 state=may_dirty npu statistic(bytes/packets/allow_err): org=112/2/1 reply=112/2/1 tuples=2 tx speed(Bps/kbps): 0/0 rx speed(Bps/kbps): 0/0 orgin->sink: org pre->post, reply pre->post dev=15->102/102->15 gwy=172.16.209.2/172.16.205.11 hook=pre dir=org act=noop 172.16.205.11:39176->10.1.100.22:5001(0.0.0.0:0) hook=post dir=reply act=noop 10.1.100.22:5001->172.16.205.11:39176(0.0.0.0:0) pos/(before,after) 0/(0,0), 0/(0,0) misc=0 policy_id=2 pol_uuid_idx=719 auth_info=0 chk_client_info=0 vd=0 serial=00020f7a tos=ff/ff app_list=0 app=0 url_cat=0 sdwan_mbr_seq=2 sdwan_service_id=1 rpdb_link_id=ff000001 rpdb_svc_id=0 ngfwid=n/a npu_state=0x5000c00 npu info: flag=0x82/0x81, offload=8/8, ips_offload=0/0, epid=249/74, ipid=74/86, vlan=0x0000/0x0000 vlifid=74/249, vtag_in=0x0000/0x0001 in_npu=1/1, out_npu=1/1, fwd_en=0/0, qid=5/5 session info: proto=17 proto_state=00 duration=0 expire=180 timeout=0 flags=00000000 socktype=0 sockport=0 av_idx=0 use=4 origin-shaper= reply-shaper= per_ip_shaper= class_id=0 ha_id=0 policy_dir=0 tunnel=/ vlan_cos=0/255 state=may_dirty fec statistic(bytes/packets/allow_err): org=100366/67/1 reply=0/0/0 tuples=2 tx speed(Bps/kbps): 0/0 rx speed(Bps/kbps): 0/0 orgin->sink: org pre->post, reply pre->post dev=15->102/102->15 gwy=172.16.209.2/0.0.0.0 hook=pre dir=org act=noop 172.16.205.11:49052->10.1.100.22:5001(0.0.0.0:0) hook=post dir=reply act=noop 10.1.100.22:5001->172.16.205.11:49052(0.0.0.0:0) misc=0 policy_id=1 pol_uuid_idx=593 auth_info=0 chk_client_info=0 vd=0 serial=000210fa tos=ff/ff app_list=0 app=0 url_cat=0 sdwan_mbr_seq=2 sdwan_service_id=1 rpdb_link_id=ff000001 rpdb_svc_id=0 ngfwid=n/a npu_state=0x5040000 no_ofld_reason: non-npu-intf
Non-FEC protected TCP traffic is offloaded, while FEC protected UDP traffic is not offloaded
On FortiGate A, check the health-check result and the corresponding FEC base and redundant packets:
# diagnose sys sdwan health-check Health Check(1): Seq(2 vd1-p1): state(alive), packet-loss(0.000%) latency(0.168), jitter(0.021), bandwidth-up(999999), bandwidth-dw(999998), bandwidth-bi(1999997) sla_map=0x1
Because bandwidth-up is more than 950000kbps, base and redundant are set to 9 and 3:
# diagnose vpn tunnel fec vd1-p1 egress: enabled=1 base=9 redundant=3 codec=0 timeout=10(ms) encode=6621 encode_timeout=6621 encode_fail=0 tx_data=6880 tx_parity=18601 ingress: enabled=1 timeout=50(ms) fasm_cnt=0 fasm_full=0 ipsec_fec_chk_fail=0 complete=0 rx_data=0 rx_parity=0 recover=0 recover_timeout=0 recover_fail=0 rx=0 rx_fail=0
Make packet loss more than 10%, then check the health-check result and the corresponding FEC base and redundant packets again:
# diagnose sys sdwan health-check Health Check(1): Seq(2 vd1-p1): state(alive), packet-loss(15.000%) latency(0.168), jitter(0.017), bandwidth-up(999999), bandwidth-dw(999998), bandwidth-bi(1999997) sla_map=0x0
Because packet loss is more than 10%, entry one in FEC mapping is first matched, and base and redundant are set to 8 and 2:
# diagnose vpn tunnel fec vd1-p1 egress: enabled=1 base=8 redundant=2 codec=0 timeout=10(ms) encode=6670 encode_timeout=6670 encode_fail=0 tx_data=6976 tx_parity=18748 ingress: enabled=1 timeout=50(ms) fasm_cnt=0 fasm_full=0 ipsec_fec_chk_fail=0 complete=0 rx_data=0 rx_parity=0 recover=0 recover_timeout=0 recover_fail=0 rx=0 rx_fail=0