Skip to content

Add support for configuring SFP modules speeds#246

Merged
vDorst merged 2 commits into
mainfrom
sfp_speed
May 31, 2026
Merged

Add support for configuring SFP modules speeds#246
vDorst merged 2 commits into
mainfrom
sfp_speed

Conversation

@logicog

@logicog logicog commented May 28, 2026

Copy link
Copy Markdown
Owner

Add configuration commands for SFP speed configuration, e.g. sfp 1 1g, which allow modules which have higher speeds to be configured to use lower speeds, such as 1gbit for a 10gbit module. This has to be supported by the module hardware.
This is supposed to address issue #245

This is now ready to merge, the 5GBit support is however missing, due to lack of test hardware.

@logicog logicog mentioned this pull request May 28, 2026

@vDorst vDorst left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not tested yet, but small comments.

Comment thread cmd_parser.c Outdated
if (cmd_words_len == 1) {
print_string("\nSlot 1 - Rate: "); print_byte(sfp_read_reg(0, 12));
print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11));
print_string("\n");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace with write_char('\n')

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

Comment thread cmd_parser.c Outdated
if (machine.n_sfp == 2) {
print_string("\nSlot 2 - Rate: "); print_byte(sfp_read_reg(1, 12));
print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11));
print_string("\n");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace with write_char('\n')

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

Comment thread cmd_parser.c Outdated
Comment on lines +1413 to +1414
} else if (cmd_compare(0, "sfp") && cmd_words_len == 3) {
parse_sfp();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed, check below is the same.
This is redundant.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

@logicog

logicog commented May 29, 2026

Copy link
Copy Markdown
Owner Author

I am very interested in the results of testing with different SFP+ modules. I had to use a fixed 1GBit module on the other side of the link, because I use an intel X520 card in a PC for testing and the linux driver seems not able to change the speed to 1GBit for a 10GBit module. I unfortunately do not have any 2.5GBit capable SFP+ modules at hand, so could not test this at all.

@logicog

logicog commented May 29, 2026

Copy link
Copy Markdown
Owner Author

I pushed the fixes for the bugs found above. There is a pre-existing issue with the sfp command: if a slot is empty, it will still print garbage, as there is no check for whether there is an SFP module inserted. Probably, there should be some kind of sfp_present() function, which checks the present pin, but I have not thought this through, yet.

@vDorst

vDorst commented May 29, 2026

Copy link
Copy Markdown
Collaborator

We can make use of machine.pin_detect. But also I2C returns an error bit when a NACK is received. We can use that to report that the module is not present.

Comment thread cmd_parser.c Outdated
@feelfree69

Copy link
Copy Markdown
Collaborator

With a DAC cable, the link is successfully established when setting sfp speed to 1g, 2g5 or 10g on both sides.
Setting to 5g seems not to work at all, it stays at 10g.

Comment thread rtlplayground.c
Comment thread cmd_parser.c Outdated
@logicog

logicog commented May 29, 2026

Copy link
Copy Markdown
Owner Author

We can make use of machine.pin_detect. But also I2C returns an error bit when a NACK is received. We can use that to report that the module is not present.

I'll try machine.pin_detect.

@logicog

logicog commented May 29, 2026

Copy link
Copy Markdown
Owner Author

Fixed the above (apart from the 5GBit setting). I added a check for the speed setting, which verifies that the slot is actually present, e.g. if the machine has only 1 slot.
Regarding the 5GBit, I found the code in the SDK, but as usual this is rather arcane. So far I am not able to see any differences to the 2.5GBit mode, but that does not make sense, unless there is not actually any support for 5GBit and it is merely handled like 2.5Gbit.

Comment thread cmd_parser.c Outdated
@feelfree69

Copy link
Copy Markdown
Collaborator

Looks good to me!

@logicog logicog changed the title WIP: Add support for configuring SFP modules speeds Add support for configuring SFP modules speeds May 29, 2026
@vDorst

vDorst commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Do we also want to support 100m? While testing with other switch which has still the original firmware, I see that is support 100mbit.
For the rest it is good to me.

@logicog

logicog commented May 30, 2026

Copy link
Copy Markdown
Owner Author

I had forgotten that 100MBit fiber modules actually existed. But I found support in the RTL-SDK, there is support for SERDES_100FX. For this to work I will need a look how difficult it is to support.

BTW: In the OEM Web-interface, do they support setting 5GBit for fiber modules? I am not sure the API version we have supports that.

logicog pushed a commit that referenced this pull request May 30, 2026
While testing #246, I noticd that SFP did not light-up while forcing
2.5gbit link. This is because RJ45 and SFP share the same LED-settings.
But RJ45 has two leds-settings.
Solution is to add settings for SFP for both managed and unmanaged
variant.
@feelfree69

Copy link
Copy Markdown
Collaborator

Personally, I would prefer merging PRs that are ready (as this one is) over adding just one more feature (that probably nobody will ever use)....

@logicog

logicog commented May 30, 2026

Copy link
Copy Markdown
Owner Author

Personally, I would prefer merging PRs that are ready (as this one is) over adding just one more feature (that probably nobody will ever use)....

You are probably right. This can be merged, and support for 100FX is then a different story. We do not even have support for those modules, yet. Not even speaking of forcing faster modules into that mode.

@logicog

logicog commented May 30, 2026

Copy link
Copy Markdown
Owner Author

The following appears to work to allow 100MBit modules:

$ git diff
diff --git a/cmd_parser.c b/cmd_parser.c
index 45308ba..b25a996 100644
--- a/cmd_parser.c
+++ b/cmd_parser.c
@@ -791,6 +791,9 @@ void parse_sfp(void)
        } else if (cmd_compare(2, "1g")) {
                print_string(" 1G\n");
                sfp_speed[slot] = SFP_SPEED_1G;
+       } else if (cmd_compare(2, "100m")) {
+               print_string(" 100M\n");
+               sfp_speed[slot] = SFP_SPEED_100M;
        } else if (cmd_compare(2, "auto")) {
                print_string(" AUTO\n");
                sfp_speed[slot] = SFP_SPEED_AUTO;
diff --git a/rtl837x_common.h b/rtl837x_common.h
index 3be8c7f..6d6abb5 100644
--- a/rtl837x_common.h
+++ b/rtl837x_common.h
@@ -94,6 +94,7 @@ struct vlan_tag {
 
 enum sfp_speeds {
        SFP_SPEED_AUTO = 0,
+       SFP_SPEED_100M,
        SFP_SPEED_1G,
        SFP_SPEED_2G5,
        SFP_SPEED_5G,
diff --git a/rtl837x_regs.h b/rtl837x_regs.h
index c1a27bb..f5bd951 100644
--- a/rtl837x_regs.h
+++ b/rtl837x_regs.h
@@ -73,6 +73,7 @@
  */
 #define SDS_SGMII              0x02
 #define SDS_1000BX_FIBER       0x04
+#define SDS_100FX              0x05
 #define SDS_QXGMII             0x0d
 #define SDS_HISGMII            0x12
 #define SDS_HSG                        0x16
diff --git a/rtlplayground.c b/rtlplayground.c
index 7499f45..6b56db3 100644
--- a/rtlplayground.c
+++ b/rtlplayground.c
@@ -927,6 +927,10 @@ void sds_config(uint8_t sds, uint8_t mode)
                v = 0x0200;
                page = 0x2e;
                break;
+       case SDS_100FX:
+               v = 0x0200;
+               page = 0x26;
+               break;
        default:
                print_string("Error in SDS Mode\n");
                return;
@@ -1170,6 +1174,8 @@ void handle_tx(void)
 
 static inline uint8_t sfp_rate_to_sds_config(register uint8_t rate)
 {
+       if (rate == 0x1 || rate == 0x2)
+               return SDS_100FX;
        if (rate == 0xc || rate == 0xd)
                return SDS_1000BX_FIBER;
        if (rate >= 0x19 && rate <= 0x20)  // Ethernet 2.5 GBit
@@ -1235,7 +1241,9 @@ void handle_sfp(void)
                                // Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit
                                delay(100); // Delay, because some modules need time to wake up
                                uint8_t rate = sfp_read_reg(sfp, 12);
-                               if (sfp_speed[sfp] == SFP_SPEED_1G)
+                               if (sfp_speed[sfp] == SFP_SPEED_100M)
+                                       rate = 0x1;
+                               else if (sfp_speed[sfp] == SFP_SPEED_1G)
                                        rate = 0xc;
                                else if (sfp_speed[sfp] == SFP_SPEED_2G5)
                                        rate = 0x19;

It seems I can make a 10GBit and a 1GBit module talk 100MBit to each other:

 sfp

Slot 1 - Rate: 0d  Encoding: 01
Delock          GLC-SX-MM       1.0 
Options: 08

Slot 2 - Rate: 67  Encoding: 06
OEM             SFP-10G-SR      2   
Options: 68
Temp: 2352
Vcc: 80a2
TX Bias: 0d2a
TX Power: 1512
RX Power: 0e9f
Laser: 0000
State: 30

> sfp 2 1g
 1G

<MODULE INSERTED>  Slot: 2  Rate: 0c  Encoding: 06  Module: OEM             SFP-10G-SR      2   

sds_config sds: 01, mode: 04

RTL837X_REG_SDS_MODES: 0x00000084

> 
<new link: 2000052000, was 2000050000>

<new link: 2000050000, was 2000052000>

<new link: 2200052000, was 2000050000>


> sfp 1 100m
 100M

<MODULE INSERTED>  Slot: 1  Rate: 01  Encoding: 01  Module: Delock          GLC-SX-MM       1.0 

sds_config sds: 00, mode: 05

RTL837X_REG_SDS_MODES: 0x00000085

> 
<new link: 2000052000, was 2200052000>

<new link: 2000050000, was 2000052000>


> sfp 2 100m
 100M

<MODULE INSERTED>  Slot: 2  Rate: 01  Encoding: 06  Module: OEM             SFP-10G-SR      2   

sds_config sds: 01, mode: 05

RTL837X_REG_SDS_MODES: 0x000000a5

> 
<new link: 2100051000, was 2000050000>


> stat

Port    State   Link    TxGood          TxBad           RxGood          RxBad
5       SFP IN  100M    0x004cfe38      0x00000000      0x004cfe37      0x00000000
1       On      2.5G    0x0042c9bf      0x00000000      0x000050dc      0x00000000
2       On      Down    0x00000000      0x00000000      0x00000000      0x00000000
3       On      Down    0x00000000      0x00000000      0x00000000      0x00000000
4       On      Down    0x00000000      0x00000000      0x00000000      0x00000000
6       SFP IN  100M    0x004cfe39      0x00000000      0x004cfe37      0x00000001

@vDorst vDorst merged commit ad64e45 into main May 31, 2026
1 check passed
@vDorst

vDorst commented May 31, 2026

Copy link
Copy Markdown
Collaborator

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants