Skip to content

Commit

Permalink
new function: FEC - reed-solomon
Browse files Browse the repository at this point in the history
  • Loading branch information
cnbatch committed Nov 26, 2023
1 parent 4531d38 commit 4c1c642
Show file tree
Hide file tree
Showing 41 changed files with 2,822 additions and 292 deletions.
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
- 中继节点模式

## 用法

**注意**,客户端的时间与服务端的时间务必同步,时间相差不能大于 255 秒。

### 全部用法
请前往 [Wiki 页面](https://github.com/cnbatch/kcptube/wiki),或前往[文档页面](docs/README.md)

Expand Down Expand Up @@ -168,6 +171,8 @@ encryption_algorithm=AES-GCM
| mux_tunnels | 0 - 65535 || 预设值为 0,等于不使用多路复用通道<br>该选项是指两个KCP端之间的多路复用通道数<br>仅限客户端启用|
| stun_server | STUN 服务器地址 ||listen_port 为端口范围模式时不可使用|
| log_path | 存放 Log 的目录 ||不能指向文件本身|
| fec | uint8:uint8 ||格式为 `fec=D:R`,例如可以填入 `fec=20:3`。<br>注意:D + R 的总数最大值为 255,不能超过这个数。<br>冒号两侧任意一个值为 0 表示不使用该选项。两端的设置必须相同。<br>详情请参考 [FEC使用介绍](docs/fec_zh-hans.md)|
| mtu | 正整数 ||当前网络 MTU 数值,用以自动计算 kcp_mtu|
| kcp_mtu | 正整数 ||预设值1440。调用 ikcp_setmtu() 设置的值,亦即 UDP 数据包内数据内容的长度|
| kcp | manual<br>fast1 - 6<br>regular1 - 5<br> &nbsp; ||手动设置<br>快速<br>常速<br>(末尾数字:数值越小,速度越快)|
| kcp_sndwnd | 正整数 ||预设值见下表,可以单独覆盖|
Expand All @@ -182,9 +187,9 @@ encryption_algorithm=AES-GCM
| blast | yes<br>true<br>1<br>no<br>false<br>0 ||尝试忽略 KCP 流控设置,尽可能迅速地转发数据包。可能会导致负载过大|
| \[listener\] | N/A |是<br>(仅限中继模式)|中继模式的标签,用于指定监听模式的 KCP 设置<br>该标签表示与客户端交互数据|
| \[forwarder\] | N/A |是<br>(仅限中继模式)|中继模式的标签,用于指定转运模式的 KCP 设置<br>该标签表示与服务端交互数据|
| \[custom_input\] | N/A ||自定义映射模式的标签,使用方法请参考 [自定义映射使用方法](docs/custom_ip_mappings_zh-cn.md)|
| \[custom_input_tcp\] | N/A ||自定义映射模式的标签,使用方法请参考 [自定义映射使用方法](docs/custom_ip_mappings_zh-cn.md)|
| \[custom_input_udp\] | N/A ||自定义映射模式的标签,使用方法请参考 [自定义映射使用方法](docs/custom_ip_mappings_zh-cn.md)|
| \[custom_input\] | N/A ||自定义映射模式的标签,使用方法请参考 [自定义映射使用方法](docs/custom_ip_mappings_zh-hans.md)|
| \[custom_input_tcp\] | N/A ||自定义映射模式的标签,使用方法请参考 [自定义映射使用方法](docs/custom_ip_mappings_zh-hans.md)|
| \[custom_input_udp\] | N/A ||自定义映射模式的标签,使用方法请参考 [自定义映射使用方法](docs/custom_ip_mappings_zh-hans.md)|

其中,`encryption_algorithm` 以及 `encryption_password` 在通讯的两端必须保持一致。

Expand All @@ -207,6 +212,9 @@ encryption_algorithm=AES-GCM

需要提醒的是,填写的带宽值不应超出实际带宽,以免造成发送窗口拥堵导致阻塞。

**重要提示**:<br>
KCPTube 会在 KCP 链路建立后的 5 秒左右,根据握手包的延迟值以及 outbound_bandwidth 与 inbound_bandwidth 的数值,计算并设置 KCP 的发送窗口大小。设置完成后的一段时间内,有很大机率出现流量大幅度波动的情况,甚至会出现流量突然降至 0,需要好几秒才能恢复。

#### KCP 模式预设值
| 快速模式 | kcp_sndwnd | kcp_rcvwnd|kcp_nodelay|kcp_interval|kcp_resend|kcp_nc |
| ---- | :----: | :----: | :----: | :----: | :----: |:----: |
Expand All @@ -227,10 +235,12 @@ encryption_algorithm=AES-GCM

其中,丢包率越高(高于 10%),kcp_nodelay=1 就比 kcp_nodelay=2 越有优势。在丢包率不特别高的情况下,kcp_nodelay=2 可使延迟抖动更为平滑。

如果想减少流量浪费、不介意延迟稍微增加,可以选择 regular 模式。<br />
对于不追求低延迟、只需要大流量传输的场景,请使用 **regular 3 ~ 5**。<br />
### 大流量传输
对于低丢包环境,每个模式都适合使用,区别只在于浪费的流量是多还是少,以及最高速的上限有所不同。其中 regular3 浪费的流量没那么多。<br />
建议同时开启 `blast=1` 设置。

对于高丢包环境,请考虑叠加使用 FEC 设置。详情请参考 [FEC使用介绍](docs/fec_zh-hans.md)

更多详解,请见[参数列表](docs/parameters_zh-hans.md)

### Log 文件
Expand Down Expand Up @@ -505,7 +515,7 @@ root soft nofile 300000
需要提醒的是,使用两种校验码仍然无法 100% 避免内容错误,TCP 本身也是一样。如果确实需要精确无误,请启用加密选项。
## 多路复用 (mux_tunnels=N)
KCP Tube 虽然有“多路复用”的功能,但默认并不主动打开。每接受一个入站连接,就会创建一个对应的出站连接。
KCP Tube 虽然有“多路复用”的功能,但默认并不主动打开。在不使用该功能的情况下,每接受一个入站连接,就会创建一个对应的出站连接。
原因是为了躲避运营商的 QoS。多路复用状态下,一旦某个端口号被 QoS,就会导致共用端口号的其它会话同时受阻,直到更换端口号为止。
Expand All @@ -523,7 +533,9 @@ KCP Tube 虽然有“多路复用”的功能,但默认并不主动打开。
- OpenVPN
- Wireguard
启用“多路复用”后,KCP 通道的超时时间为 30 秒。一般来说,`mux_tunnels 设置成 3 ~ 10 就够用了,不需要设置过高的数值。
启用“多路复用”后,KCPTube 会预创建 N 条链路,所有入站新连接都会从已有链路中传送数据,而不再单独创建新链路。此时 KCP 通道的超时时间为 30 秒。
一般来说,`mux_tunnels 设置成 3 ~ 10 就够用了,不需要设置过高的数值。
## 关于代码
### TCP
Expand Down
21 changes: 16 additions & 5 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Currently 3 modes are supported:
- Relay Mode

## Usage

**Reminder:** The time of the client must be synchronized with the server and the time difference cannot exceed 255 seconds.

### All Usage
Please refer [Wiki Page](https://github.com/cnbatch/kcptube/wiki), or [Document Page](docs/README_EN.md)

Expand Down Expand Up @@ -168,6 +171,8 @@ encryption_algorithm=AES-GCM
| mux_tunnels | 0 - 65535 |No | The default value is 0, which means that multiplexing is disabled. This option means how many multiplexing tunnels between two KCP endpoints.<br>Client Mode only.|
| stun_server | STUN Server's address |No| Cannot be used if listen_port option is port range mode|
| log_path | The directory where the Logs are stored |No|Cannot point to the file itself|
| fec | uint8:uint8 |No|The format is `fec=D:R`, for example `fec=20:4`. <br>Note: The maximum total value of D + R is 255 and cannot exceed this number.<br>A value of 0 on either side of the colon indicates that the option is not used. Must be the same value on both side.<br>Please refer to [The Usage of FEC](docs/fec_en.md)|
| mtu | Positive Integer |No|MTU Value of current network, is to automatically calculate the value of `kcp_mtu`|
| kcp_mtu | Positive Integer |No|This option refers to the length of the data content within a UDP packet. <br>The value set for this option refers to the value set by calling ikcp_setmtu(). <br>Default value is 1440.|
| kcp | manual<br>fast1 - 6<br>regular1 - 5<br> &nbsp; |Yes|Setup Manually<br>Fast Modes<br>Regular Speeds<br>(the number at the end: the smaller the value, the faster the speed)|
| kcp_sndwnd | Positive Integer |No|See the table below for default values, which can be overridden individually|
Expand Down Expand Up @@ -207,6 +212,9 @@ Please note that it is bps (Bits Per Second), not Bps (Bytes Per Second).

This bandwidth values should not larger than your actual bandwidth, otherwise this will cause the sending window to be congested and cause blocking.

**Important Notice**:<br>
KCPTube will calculate and set the KCP sending window size based on the delay value of the handshake packet and the values of outbound_bandwidth and inbound_bandwidth about 5 seconds after the KCP link is established. Within a period of time after the setup is completed, there is a high chance that the traffic will fluctuate significantly, or even the traffic may suddenly drop to 0, and it will take several seconds to recover.

#### KCP Mode Default Values
| Fast Mode | kcp_sndwnd | kcp_rcvwnd|kcp_nodelay|kcp_interval|kcp_resend|kcp_nc |
| ---- | :----: | :----: | :----: | :----: | :----: |:----: |
Expand All @@ -227,9 +235,10 @@ This bandwidth values should not larger than your actual bandwidth, otherwise th

Note: If the packet loss rate is high enough (higner than 10%), kcp_nodelay=1 may better than kcp_nodelay=2. If the packet loss rate is not too high, kcp_nodelay=2 can make the network latency smoother.

If you want to reduce traffic waste and also accept a little bit more latency increase, please try choosing regular modes.<br />
For scenarios that do not require low latency but only need high throughput transmission, please use **regular 3 - 5**.<br />
Enabling `blast=1` at this time is recommended.
### High-traffic transmission
For low packet loss environments, each mode is suitable for use. The difference lies only in the amount of wasted traffic and the slightly different upper limit of the highest speed.<br />Among them, regular3 wastes less traffic.<br />It is recommended to enable the `blast=1` setting at the same time.

For high packet loss environments, consider using FEC settings at the same time. For more details, please refer to the [The Usage of FEC](docs/fec_en.md).

For more details, please refer to [Parameter Details](docs/parameters_en.md).

Expand Down Expand Up @@ -506,7 +515,7 @@ The calculation speed of these two checksums is fast enough, concise and practic
It should be reminded that using two checksums still cannot completely avoid content errors, just like TCP itself. If you really need accuracy, please enable the encryption option.
## Multiplexing (mux_tunnels=N)
The function of multiplexing is not automatically enabled by default. For each incoming connection accepted, a corresponding outgoing connection is created.
The function of multiplexing is not automatically enabled by default. Without using this feature, for each incoming connection accepted, a corresponding outgoing connection is created.
The reason is to avoid the QoS of operators. Once a port number is affected by QoS in multiplexing mode, other sessions sharing the same port number will also be blocked until the port number is changed.
Expand All @@ -524,7 +533,9 @@ If you really need to use the ‘multiplexing’ function, you can refer to the
- OpenVPN
- Wireguard
The timeout period for KCP channel is 30 seconds after enabling the multiplexing function. In most cases, setting `mux_tunnels` to 3 - 10 is enough, and there is no need to set an excessively high value.
When "Multiplexing" is enabled, KCPTube will pre-create N links, and all inbound new connections will transmit data from the existing links instead of creating new links separately. At this time, the KCP channel timeout is 30 seconds.
In most cases, setting `mux_tunnels` to 3 - 10 is enough, and there is no need to set an excessively high value.
## About the codes
Expand Down
File renamed without changes.
85 changes: 85 additions & 0 deletions docs/fec_en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# FEC (Forward Error Correction) Instructions

Starting from version 20231126, KCPTube provides the FEC function to further alleviate jitter caused by packet loss.

That's right, it's Reed-Solomon coding.

## Format

The format is `fec=D:R`, where D represents the original data packets and R represents the redundant packets. The maximum total number of D + R is 255 and cannot exceed this number. As for D and R, it doesn't matter which one is bigger or smaller.

A value of 0 on either side of the colon indicates that FEC is not used.

For example, you can fill in `fec=20:4`, which means that for every 20 data packets sent, 4 redundant packets will be generated and sent.

## Precautions

The FEC settings of the sender and receiver **must** be exactly the same, otherwise FEC setting will be invalid.

## Numeric adjustment

- The amount of original data (D value) should not be too small. Setting the value too low is almost equivalent to having no effect. This value should be greater than 15.
- Of course, greater is not better, because it will take a very long time to generate redundant data at low traffic.

- The higher amount of redundant data (R value) is not always better. Excessive amount of redundant data will cause unnecessary waste.

Therefore, you need to adjust the D value and R value according to your own traffic requirements and line packet loss rate. Generally speaking, D + R > 20 should be used.

## Interaction with KCP fast retransmission mechanism

KCP itself has a fast retransmission mechanism. You can either use the preset configuration, or you can specify and enter the kcp_resend value in KCPTube in manual mode (corresponding to the fastresend inside KCP).

If the packet loss span reaches a given number of times, automatic retransmission will be triggered.

Obviously, if the D value of `fec=D:R` is too high, the packet loss rate of the current link is high, and the fastresend value is low (for example, only 2 or 3, which is fast1 ~ fast4 mode), then the automatic retransmission may be triggered and generating a large amount of traffic before the redundant data has been generated.

For fast mode, it is recommended that the D value should not be greater than 30.

### kcp_nodelay = 1 or kcp_nodelay = 2 (fast retransmission enabled)
(fast modes and regular1-2)

- When the packet loss rate is not high (less than **5%**), there is **no need to use FEC.** Just has `blast=1` enabled can get a better effect.

- When the packet loss rate is higher than 5% but less than 10%, enable `blast=1` only is also better than FEC

- When the packet loss rate is higher than 10%, adding FEC setting is necessary.
- But it would cause a significant waste of bandwidth, and the useful traffic is only one-third to one-fifth of total traffic.

### kcp_nodelay = 0 (No fast retransmission)
(regular3~5)

- When the packet loss rate is not high (less than **2%**), there is **no need to use FEC.** Just has `blast=1` enabled can get a better effect.
- The advantage of regular3 is that there is less wasted traffic. It might be the best choice.
- regular4 and regular5 are similar to regular3 at this time, but slower.

- When the packet loss rate is higher than 2% but less than 5%, enable `blast=1` only is also better than FEC

- When the packet loss rate is higher than 6%, adding FEC setting is necessary.
- The wasted traffic increases dramatically, similar to fast mode.

## Reference settings

fast1 ~ fast6, regular1, regular2 :
- `fec=15:3`
- `fec=16:5`
- `fec=20:4`
- `fec=25:5`

regular3:
- `fec=20:4`
- `fec=25:5`
- `fec=26:6`

regular4, regular5:
- `fec=20:4`
- `fec=20:5`
- `fec=25:5`
- `fec=30:6`
- `fec=20:8`

For those who desire to set a higher D value and are not concerned about high latency, please use manual configuration mode and specify a higher kcp_resend value.

If the reason for setting a higher D value is to wrap a tunnel for VPN such as OpenVPN or WireGuard, please consider using [UDP Hop](https://github.com/cnbatch/udphop).

## FEC Source Code
The FEC Library using by KCPTube is from [fecpp](https://github.com/randombit/fecpp) with some modifications.
86 changes: 86 additions & 0 deletions docs/fec_zh-hans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# 前向纠错 (FEC, Forward Error Correction) 使用说明

自 20231126 版起,KCPTube 提供了 FEC 功能,进一步缓解丢包造成的抖动。

没错,就是 Reed-Solomon 编码。

## 格式

格式为 `fec=D:R`,其中 D 表示原始数据量,R 表示冗余数据量。D + R 的总数最大值为 255,不能超过这个数。至于 D 及 R 谁大谁小,都可以。

冒号两侧任意一个值为 0 表示不使用 FEC。

例如可以填入 `fec=20:4`,表示每发送 20 个数据包,就生成并发送 4 个冗余包。

## 注意事项

收发双方的 FEC 设置**必须**完全一致,否则会导致 FEC 无效。

## 数值调整

- 原始数据量(D 值)不应该太少,数值过少等于几乎没有效果。该值最好大于 15。
- 当然了,并不是越大越好,因为在低流量时会导致很长时间才会生成冗余数据量。

- 冗余数据量(R 值)并非越多越好,过多的冗余数据量会造成不必要的浪费。

所以需要根据自己的流量需求以及线路丢包率来调整 D 值与 R 值。一般来说,应当 D + R > 19。

## 与 KCP 快速重传机制的相互影响

KCP 本身有快速重传机制,既可以使用预先设置好的配置,也可以在 KCPTube 中可以在手动模式下自行指定输入 kcp_resend 数值(对应 KCP 内部的 fastresend)。

若丢包跨越达到给定次数后,就会触发自动重传。

很显然,如果 `fec=D:R` 的 R 值过高,恰好当前链路丢包率较高,而 fastresend 值数值较低(比如只有2、3,也就是 fast1 ~ fast4 模式),可能会在冗余数据仍未生成的情况下就触发自动重传,产生大量流量。

对于 fast 模式,建议 R 值不要大于 30。

### kcp_nodelay = 1 或 kcp_nodelay = 2 (启用快速重传)
(fast 模式以及 regular1~2)

- 丢包率不高的时候(**5%** 以内),**无须使用 FEC。** 单独使用 `blast=1` 效果更好。

- 丢包率在 5% ~ 10% 的时候,单独使用 `blast=1` 的效果仍然比 FEC 更好。

- 丢包率高于 10% 的时候,叠加使用 FEC 可以使抖动更为平滑。
- 但可能会造成严重的带宽浪费,有效流量仅占总流量的三分之一到五分之一。

### kcp_nodelay = 0 (关闭快速重传)
(regular3~5)

- 丢包率不高的时候(**2%** 以内),**无须使用 FEC。** 单独使用 `blast=1` 效果更好。
- 此时 regular3 的优点是,浪费的流量没那么多。可能是最佳选择。
- 这时候 regular4-5 类似于 regular3,只不过稍微慢一点。

- 丢包率在 2% ~ 5% 的时候,单独使用 `blast=1` 的效果仍然比 FEC 更好。

- 丢包率高于 6% 的时候,就有必要叠加使用 FEC 了。
- 浪费的流量暴增,与 fast 模式相似。

## 参考设置

fast1 ~ fast6, regular1, regular2 :
- `fec=15:3`
- `fec=16:5`
- `fec=20:4`
- `fec=25:5`

regular3:
- `fec=20:4`
- `fec=25:5`
- `fec=26:6`

regular4, regular5:
- `fec=20:4`
- `fec=20:5`
- `fec=25:5`
- `fec=30:6`
- `fec=20:8`


若想设置较高的 D 值、不介意高延迟,请使用手动配置模式,自行指定较高的 kcp_resend 数值。

如果设置较高 D 值的原因是想要为 OpenVPN 或 WireGuard 之类的 VPN 套一层隧道,请考虑使用 [UDP Hop](https://github.com/cnbatch/udphop)

## FEC 源码库
KCPTube 使用的 FEC 来自于 [fecpp](https://github.com/randombit/fecpp),并作了些许修改。
Loading

0 comments on commit 4c1c642

Please sign in to comment.