├── .gitattributes ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── Screenshot-v2.2.png ├── TestAppLPC2387+IP175CD ├── .gitignore ├── RstpTestApp.icf ├── RstpTestApp_IAR7.70.ewd ├── RstpTestApp_IAR7.70.ewp ├── RstpTestApp_IAR7.70.eww ├── debug_leds.cpp ├── debug_leds.h ├── drivers │ ├── ethernet.cpp │ ├── ethernet.h │ ├── ethernet_defs.h │ ├── event_queue.cpp │ ├── event_queue.h │ ├── gpio.cpp │ ├── gpio.h │ ├── scheduler.cpp │ ├── scheduler.h │ ├── serial_console.cpp │ ├── serial_console.h │ ├── timer.cpp │ ├── timer.h │ ├── uart.cpp │ ├── uart.h │ ├── vic.cpp │ └── vic.h ├── main.cpp ├── serial_commands.cpp ├── stp_callbacks.cpp └── test.c ├── TestAppMK66F+KSZ8794 ├── .gitignore ├── KSZ8794CNX.pdf ├── TestAppMK66F+KSZ8794.hzp ├── drivers │ ├── clock.cpp │ ├── clock.h │ ├── ethernet.cpp │ ├── ethernet.h │ ├── event_queue.cpp │ ├── event_queue.h │ ├── gpio.cpp │ ├── gpio.h │ ├── pit.cpp │ ├── pit.h │ ├── scheduler.cpp │ ├── scheduler.h │ ├── serial_console.cpp │ ├── serial_console.h │ ├── spi.cpp │ ├── spi.h │ ├── uart.cpp │ └── uart.h ├── embOSIP_SwitchBoard_V2.0_WEB_Schematic.pdf ├── main.cpp ├── switch.cpp └── switch.h ├── TestAppSTM32+88E6352 ├── .gitignore ├── 8836352.h ├── TestAppSTM32+88E6352.hzp ├── drivers │ ├── assert.cpp │ ├── assert.h │ ├── clock.cpp │ ├── clock.h │ ├── ethernet.cpp │ ├── ethernet.h │ ├── event_queue.cpp │ ├── event_queue.h │ ├── gpio.cpp │ ├── gpio.h │ ├── mpu.cpp │ ├── mpu.h │ ├── scheduler.cpp │ ├── scheduler.h │ ├── serial_console.cpp │ ├── serial_console.h │ ├── timer.cpp │ ├── timer.h │ ├── uart.cpp │ └── uart.h ├── main.cpp ├── section_placement.xml └── serial_commands.cpp ├── TestAppTM4C129+88E6352 ├── .gitignore ├── TestAppTM4C129+88E6352.hzp ├── clock.cpp ├── clock.h ├── ethernet.cpp ├── ethernet.h ├── main.cpp ├── smi.cpp ├── smi.h ├── switch.cpp ├── switch.h └── test.c ├── _help ├── BlankForm.html ├── STP_CALLBACKS.html ├── STP_CreateBridge.html ├── STP_DestroyBridge.html ├── STP_EnableLogging.html ├── STP_GetBridgeAddress.html ├── STP_GetBridgePriority.html ├── STP_GetMstConfigId.html ├── STP_GetMstConfigTable.html ├── STP_GetMstiCount.html ├── STP_GetPortAdminPointToPointMAC.html ├── STP_GetPortAutoEdge.html ├── STP_GetPortCount.html ├── STP_GetPortEnabled.html ├── STP_GetPortIdentifier.html ├── STP_GetPortOperPointToPointMAC.html ├── STP_GetPortPriority.html ├── STP_GetRootPriorityVector.html ├── STP_GetTreeIndexFromVlanNumber.html ├── STP_GetVersionString.html ├── STP_IsBridgeStarted.html ├── STP_OnBpduReceived.html ├── STP_OnOneSecondTick.html ├── STP_OnPortDisabled.html ├── STP_OnPortEnabled.html ├── STP_SetBridgeAddress.html ├── STP_SetBridgePriority.html ├── STP_SetMstConfigName.html ├── STP_SetMstConfigRevisionLevel.html ├── STP_SetMstConfigTable.html ├── STP_SetPortAdminEdge.html ├── STP_SetPortAdminPointToPointMAC.html ├── STP_SetPortAutoEdge.html ├── STP_SetPortPriority.html ├── STP_SetStpVersion.html ├── STP_StartBridge.html ├── STP_StopBridge.html ├── Screen.css ├── StpCallback_AllocAndZeroMemory.html ├── StpCallback_DebugStrOut.html ├── StpCallback_EnableBpduTrapping.html ├── StpCallback_EnableForwarding.html ├── StpCallback_EnableLearning.html ├── StpCallback_FlushFdb.html ├── StpCallback_FreeMemory.html ├── StpCallback_OnPortRoleChanged.html ├── StpCallback_OnTopologyChange.html ├── StpCallback_TransmitGetBuffer.html ├── StpCallback_TransmitReleaseBuffer.html └── Troubleshooting.txt ├── mstp-lib.vcxproj ├── mstp-lib.vcxproj.filters ├── mstp-lib ├── internal │ ├── stp.cpp │ ├── stp_base_types.cpp │ ├── stp_base_types.h │ ├── stp_bpdu.cpp │ ├── stp_bpdu.h │ ├── stp_bridge.h │ ├── stp_conditions_and_params.cpp │ ├── stp_conditions_and_params.h │ ├── stp_log.cpp │ ├── stp_log.h │ ├── stp_md5.cpp │ ├── stp_md5.h │ ├── stp_port.h │ ├── stp_procedures.cpp │ ├── stp_procedures.h │ ├── stp_sm.h │ ├── stp_sm_bridge_detection.cpp │ ├── stp_sm_l2g_port_receive.cpp │ ├── stp_sm_port_information.cpp │ ├── stp_sm_port_protocol_migration.cpp │ ├── stp_sm_port_receive.cpp │ ├── stp_sm_port_role_selection.cpp │ ├── stp_sm_port_role_transitions.cpp │ ├── stp_sm_port_state_transition.cpp │ ├── stp_sm_port_timers.cpp │ ├── stp_sm_port_transmit.cpp │ └── stp_sm_topology_change.cpp └── stp.h ├── simulator.sln └── simulator ├── bridge.cpp ├── bridge.h ├── bridge_tree.cpp ├── bridge_tree.h ├── edit_states ├── beginning_drag_es.cpp ├── create_bridge_es.cpp ├── create_wire_es.cpp ├── edit_state.h ├── move_bridges_es.cpp ├── move_port_es.cpp └── move_wire_point_es.cpp ├── edit_window.cpp ├── log_window.cpp ├── mst_config_id_editor.cpp ├── pch.cpp ├── pch.h ├── port.cpp ├── port.h ├── port_tree.cpp ├── port_tree.h ├── project.cpp ├── project_window.cpp ├── renderable_object.h ├── resource.h ├── selection.cpp ├── simulator.cpp ├── simulator.h ├── simulator.ico ├── simulator.natvis ├── simulator.rc ├── simulator.vcxproj ├── simulator.vcxproj.filters ├── targetver.h ├── test.c ├── tests ├── bpdu_tests.cpp ├── bridge_tests.cpp ├── pch.cpp ├── pch.h ├── port_tests.cpp ├── project_tests.cpp ├── test_helpers.cpp ├── test_helpers.h ├── tests.vcxproj └── tests.vcxproj.filters ├── vlan_window.cpp ├── wire.cpp └── wire.h /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # User-specific files 3 | *.suo 4 | *.user 5 | # Build results 6 | [Dd]ebug/ 7 | [Dd]ebugPublic/ 8 | [Rr]elease/ 9 | [Rr]eleases/ 10 | [Xx]64/ 11 | [Xx]86/ 12 | [Bb]uild/ 13 | [Bb]in/ 14 | [Oo]bj/ 15 | UnitTesting/ 16 | 17 | # Visual Studio 2015 cache/options directory 18 | .vs/ 19 | 20 | # MSTest test Results 21 | [Tt]est[Rr]esult*/ 22 | [Bb]uild[Ll]og.* 23 | 24 | 25 | *_i.c 26 | *_p.c 27 | *_i.h 28 | *.ilk 29 | *.meta 30 | *.obj 31 | *.pch 32 | *.pdb 33 | *.pgc 34 | *.pgd 35 | *.rsp 36 | *.sbr 37 | *.tlb 38 | *.tli 39 | *.tlh 40 | *.tmp 41 | *.tmp_proj 42 | *.log 43 | 44 | # Visual C++ cache files 45 | ipch/ 46 | *.aps 47 | *.ncb 48 | *.opendb 49 | *.opensdf 50 | *.sdf 51 | *.cachefile 52 | *.VC.db 53 | 54 | # Visual Studio profiler 55 | *.psess 56 | *.vsp 57 | *.vspx 58 | *.sap 59 | 60 | 61 | # NuGet Packages 62 | *.nupkg 63 | # The packages folder can be ignored because of Package Restore 64 | **/packages/* 65 | # except build/, which is used as an MSBuild target. 66 | !**/packages/build/ 67 | # Uncomment if necessary however generally it will be regenerated when needed 68 | #!**/packages/repositories.config 69 | # NuGet v3's project.json files produces more ignoreable files 70 | *.nuget.props 71 | *.nuget.targets 72 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "edge"] 2 | path = simulator/edge 3 | url = https://github.com/adigostin/edge.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### mstp-lib 2 | A library that implements the Multiple / Rapid Spanning Tree 3 | Protocol as defined in 802.1Q-2018. 4 | 5 | It's written in C++03 and is callable from C. 6 | 7 | I integrated the library myself in various devices made by 8 | various OEMs (ship automation, tactical networking, in-flight 9 | entertainment) and I helped others integrate it in plenty other 10 | devices. 11 | 12 | ### Simulator 13 | A Simulator application for Windows is provided - both 14 | sources and [binaries](https://github.com/adigostin/mstp-lib/releases). 15 | The Simulator lets you create networks and see the library 16 | in action. See the screenshot below. This is a project for 17 | Visual Studio 2017. 18 | 19 | ### Embedded Application Examples 20 | The repository includes sources with a couple of RSTP implementations 21 | on embedded devices with microcontrollers and switches such as 22 | Marvell, Microchip, IC+. The projects are for Rowley CrossWorks 23 | (gcc and clang compilers) and IAR Embedded Workbench (EDG compiler). 24 | 25 | These samples highlight the platform-specific 26 | code required by STP -- mostly code that writes to 27 | a few hardware registers of the switch chip. To integrate 28 | the library in your embedded application, you'll need to 29 | write platform-specific code for your particular switch IC. 30 | Drop me a message at 31 | [adigostin@gmail.com](mailto:adigostin@gmail.com) 32 | and I might be able to help. 33 | 34 | ### API Help 35 | The repository also includes 36 | [help files](https://github.com/adigostin/mstp-lib/tree/master/_help) 37 | for most of the library APIs - 38 | [some](http://htmlpreview.github.io/?https://github.com/adigostin/mstp-lib/blob/master/_help/STP_CreateBridge.html) 39 | [rather](http://htmlpreview.github.io/?https://github.com/adigostin/mstp-lib/blob/master/_help/StpCallback_TransmitGetBuffer.html) 40 | [extensive](http://htmlpreview.github.io/?https://github.com/adigostin/mstp-lib/blob/master/_help/STP_OnPortEnabled.html). 41 | 42 | ### Screenshot of the Windows Simulator 43 | ![screenshot](./Screenshot-v2.2.png "Logo Title Text 1") 44 | -------------------------------------------------------------------------------- /Screenshot-v2.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adigostin/mstp-lib/57089f9b7826a65fdd8d391a31d0598476c3488c/Screenshot-v2.2.png -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/.gitignore: -------------------------------------------------------------------------------- 1 | settings 2 | _Debug 3 | *.dep 4 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/RstpTestApp.icf: -------------------------------------------------------------------------------- 1 | /*###ICF### Section handled by ICF editor, don't touch! ****/ 2 | /*-Editor annotation file-*/ 3 | /* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */ 4 | /*-Specials-*/ 5 | define symbol __ICFEDIT_intvec_start__ = 0x00000000; 6 | /*-Memory Regions-*/ 7 | define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; 8 | define symbol __ICFEDIT_region_ROM_end__ = 0x0007DFFF; 9 | define symbol __ICFEDIT_region_RAM_start__ = 0x40000000; 10 | define symbol __ICFEDIT_region_RAM_end__ = 0x4000FFDF; 11 | /*-Sizes-*/ 12 | define symbol __ICFEDIT_size_cstack__ = 0x400; 13 | define symbol __ICFEDIT_size_svcstack__ = 0x100; 14 | define symbol __ICFEDIT_size_irqstack__ = 0x100; 15 | define symbol __ICFEDIT_size_fiqstack__ = 0x40; 16 | define symbol __ICFEDIT_size_undstack__ = 0x10; 17 | define symbol __ICFEDIT_size_abtstack__ = 0x10; 18 | define symbol __ICFEDIT_size_heap__ = 0x3000; 19 | /**** End of ICF editor section. ###ICF###*/ 20 | 21 | 22 | define memory mem with size = 4G; 23 | define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; 24 | define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; 25 | 26 | define symbol __region_USB_DMA_RAM_start__ = 0x7FD00000; 27 | define symbol __region_USB_DMA_RAM_end__ = 0x7FD01FFF; 28 | define region USB_DMA_RAM_region= mem:[from __region_USB_DMA_RAM_start__ to __region_USB_DMA_RAM_end__]; 29 | 30 | define symbol __region_EMAC_DMA_RAM_start__ = 0x7FE00000; 31 | define symbol __region_EMAC_DMA_RAM_end__ = 0x7FE03FFF; 32 | define region EMAC_DMA_RAM_region= mem:[from __region_EMAC_DMA_RAM_start__ to __region_EMAC_DMA_RAM_end__]; 33 | 34 | define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; 35 | define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { }; 36 | define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { }; 37 | define block FIQ_STACK with alignment = 8, size = __ICFEDIT_size_fiqstack__ { }; 38 | define block UND_STACK with alignment = 8, size = __ICFEDIT_size_undstack__ { }; 39 | define block ABT_STACK with alignment = 8, size = __ICFEDIT_size_abtstack__ { }; 40 | define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; 41 | 42 | initialize by copy { readwrite }; 43 | do not initialize { section .noinit }; 44 | do not initialize { section USB_DMA_RAM }; 45 | do not initialize { section EMAC_DMA_RAM }; 46 | 47 | place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; 48 | 49 | place in ROM_region { readonly }; 50 | place in RAM_region { readwrite, 51 | block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK, 52 | block UND_STACK, block ABT_STACK, block HEAP }; 53 | place in USB_DMA_RAM_region 54 | { section USB_DMA_RAM }; 55 | place in EMAC_DMA_RAM_region 56 | { section EMAC_DMA_RAM }; 57 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/RstpTestApp_IAR7.70.eww: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $WS_DIR$\RstpTestApp_IAR7.70.ewp 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/debug_leds.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "debug_leds.h" 3 | #include "internal/stp_bridge.h" 4 | #include "drivers/gpio.h" 5 | #include 6 | #include 7 | #include 8 | 9 | static const pin_t shiftRegisterData = { .port_index = 1, .bit_pos = 23 }; 10 | static const pin_t shiftRegisterLatch = { .port_index = 1, .bit_pos = 24 }; 11 | static const pin_t shiftRegisterClock = { .port_index = 1, .bit_pos = 25 }; 12 | 13 | static void write_shift_register (unsigned char data) 14 | { 15 | for (int i = 7; i >= 0; i--) 16 | { 17 | gpio_set (shiftRegisterData, data & (1u << i)); 18 | 19 | gpio_set (shiftRegisterClock); 20 | __no_operation (); 21 | __no_operation (); 22 | __no_operation (); 23 | gpio_clear (shiftRegisterClock); 24 | } 25 | 26 | // pulse on LED_LATCH 27 | gpio_set (shiftRegisterLatch); 28 | __no_operation (); 29 | __no_operation (); 30 | __no_operation (); 31 | gpio_clear (shiftRegisterLatch); 32 | } 33 | 34 | void init_debug_leds() 35 | { 36 | FIO0SET = (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 27); 37 | FIO0DIR |= ((1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 27)); 38 | 39 | FIO1SET = (1 << 23) | (1 << 24) | (1 << 25); 40 | FIO1DIR |= ((1 << 23) | (1 << 24) | (1 << 25)); 41 | 42 | gpio_clear(shiftRegisterData); 43 | gpio_make_output(shiftRegisterData); 44 | 45 | gpio_clear(shiftRegisterLatch); 46 | gpio_make_output(shiftRegisterLatch); 47 | 48 | gpio_clear(shiftRegisterClock); 49 | gpio_make_output(shiftRegisterClock); 50 | } 51 | 52 | void update_debug_leds (const STP_BRIDGE* b) 53 | { 54 | static const unsigned int cist_tree = 0; 55 | 56 | if (STP_GetPortEnabled(b, 0)) 57 | FIO0CLR = (1 << 0); 58 | else 59 | FIO0SET = (1 << 0); 60 | 61 | if (STP_IsBridgeStarted(b) && STP_GetPortLearning(b, 0, cist_tree)) 62 | FIO0CLR = (1 << 1); 63 | else 64 | FIO0SET = (1 << 1); 65 | 66 | if (STP_IsBridgeStarted(b) && STP_GetPortForwarding(b, 0, cist_tree)) 67 | FIO0CLR = (1 << 4); 68 | else 69 | FIO0SET = (1 << 4); 70 | 71 | if (STP_IsBridgeStarted(b) && STP_GetPortOperEdge(b, 0)) 72 | FIO0CLR = (1 << 5); 73 | else 74 | FIO0SET = (1 << 5); 75 | 76 | if (STP_IsBridgeStarted(b) && b->ports[0]->trees[cist_tree]->tcWhile) 77 | FIO0CLR = (1 << 27); 78 | else 79 | FIO0SET = (1 << 27); 80 | 81 | // ----------------------------------------------- 82 | 83 | unsigned char data = 0xff; 84 | if (STP_GetPortEnabled (b, 1)) 85 | data &= ~(1 << 0); 86 | if (STP_IsBridgeStarted(b) && STP_GetPortLearning (b, 1, cist_tree)) 87 | data &= ~(1 << 1); 88 | if (STP_IsBridgeStarted(b) && STP_GetPortForwarding (b, 1, cist_tree)) 89 | data &= ~(1 << 2); 90 | if (STP_IsBridgeStarted(b) && STP_GetPortOperEdge (b, 1)) 91 | data &= ~(1 << 3); 92 | if (STP_IsBridgeStarted(b) && b->ports[1]->trees[cist_tree]->tcWhile) 93 | data &= ~(1 << 4); 94 | write_shift_register(data); 95 | } 96 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/debug_leds.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "stp.h" 4 | 5 | void init_debug_leds(); 6 | void update_debug_leds (const STP_BRIDGE* b); 7 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/ethernet.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | 6 | typedef void (*ethernet_receive_handler) (uint8_t* data, size_t size); 7 | 8 | void ethernet_init (const uint8_t macAddress[6], ethernet_receive_handler rx_handler); 9 | 10 | void ethernet_send (void* data, size_t size); 11 | 12 | void ENET_MIIWriteRegister (unsigned char DevId, unsigned char RegAddr, unsigned short Value); 13 | uint16_t ENET_MIIReadRegister (unsigned char DevId, unsigned char RegAddr); 14 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/ethernet_defs.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | 5 | // Transmit descriptor control word 6 | // See LPC23xx User Manual Ch16, Table 212 7 | union EnetTxCtrl_t 8 | { 9 | unsigned int Data; 10 | struct 11 | { 12 | unsigned int Size : 11; 13 | unsigned int : 15; 14 | unsigned int Override : 1; 15 | unsigned int Huge : 1; 16 | unsigned int Pad : 1; 17 | unsigned int CRC : 1; 18 | unsigned int Last : 1; 19 | unsigned int Intr : 1; 20 | }; 21 | }; 22 | 23 | // Transmit descriptor 24 | // See LPC23xx User Manual Ch16, Table 211 25 | struct EnetDmaTxDesc_t 26 | { 27 | unsigned char* pBuffer; 28 | EnetTxCtrl_t EnetTxCtrl; 29 | }; 30 | 31 | // Transmit status 32 | // See LPC23xx User Manual Ch16, Table 211 33 | union EnetDmaTxStatus_t 34 | { 35 | unsigned int Data; 36 | struct 37 | { 38 | unsigned int :21; 39 | unsigned int CollisionCount : 4; 40 | unsigned int Defer : 1; 41 | unsigned int ExcessiveDefer : 1; 42 | unsigned int ExcessiveCollision : 1; 43 | unsigned int LateCollision : 1; 44 | unsigned int Underrun : 1; 45 | unsigned int NoDescriptor : 1; 46 | unsigned int Error : 1; 47 | }; 48 | }; 49 | 50 | // Receive descriptor control word 51 | // See LPC23xx User Manual Ch16, Table 207 52 | union EnetRxCtrl_t 53 | { 54 | uint32_t data; 55 | struct 56 | { 57 | uint32_t Size : 11; 58 | uint32_t : 20; 59 | uint32_t Intr : 1; 60 | }; 61 | }; 62 | 63 | // Receive descriptor 64 | // See LPC23xx User Manual Ch16, Table 206 65 | struct EnetDmaRxDesc_t 66 | { 67 | unsigned char* pBuffer; 68 | EnetRxCtrl_t EnetRxCtrl; 69 | }; 70 | 71 | // Receive status 72 | // See LPC23xx User Manual Ch16, Table 208 73 | union EnetDmaRxStatus_t 74 | { 75 | unsigned int Data[2]; 76 | struct 77 | { 78 | unsigned int RxSize :11; 79 | unsigned int : 7; 80 | unsigned int ControlFrame : 1; // bit 18 81 | unsigned int VLAN : 1; // bit 19 82 | 83 | unsigned int FailFilter : 1; // bit 20 84 | unsigned int Multicast : 1; // bit 21 85 | unsigned int Broadcast : 1; // bit 22 86 | unsigned int CRCError : 1; // bit 23 87 | 88 | unsigned int SymbolError : 1; // bit 24 89 | unsigned int LengthError : 1; // bit 25 90 | unsigned int RangeError : 1; // bit 26 91 | unsigned int AlignmentError : 1; // bit 27 92 | 93 | unsigned int Overrun : 1; // bit 28 94 | unsigned int NoDescriptor : 1; // bit 29 95 | unsigned int LastFlag : 1; // bit 30 96 | unsigned int Error : 1; // bit 31 97 | 98 | unsigned int SAHashCRC : 8; 99 | unsigned int : 8; 100 | unsigned int DAHashCRC : 8; 101 | unsigned int : 8; 102 | }; 103 | }; 104 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/event_queue.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | 6 | void event_queue_init (uint8_t* buffer, size_t buffer_size); 7 | bool event_queue_is_init(); 8 | bool event_queue_try_push (void(*handler)(void*, size_t), const void* payload, size_t payload_size, const char* debug_name); 9 | bool event_queue_try_push (void(*handler)(void*), void* arg, const char* debug_name); 10 | bool event_queue_try_push (void(*handler)(), const char* debug_name); 11 | void event_queue_pop_all(); 12 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/gpio.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "gpio.h" 3 | #include 4 | #include 5 | #include 6 | 7 | void gpio_init() 8 | { 9 | SCS_bit.GPIOM = 1; // Enable Fast GPIO0,1 10 | } 11 | 12 | void gpio_make_output (pin_t pin) 13 | { 14 | __istate_t save = __get_interrupt_state(); 15 | __disable_irq (); 16 | 17 | switch (pin.port_index) 18 | { 19 | case 0: FIO0DIR |= (1UL << pin.bit_pos); break; 20 | case 1: FIO1DIR |= (1UL << pin.bit_pos); break; 21 | case 2: FIO2DIR |= (1UL << pin.bit_pos); break; 22 | case 3: FIO3DIR |= (1UL << pin.bit_pos); break; 23 | case 4: FIO4DIR |= (1UL << pin.bit_pos); break; 24 | } 25 | 26 | __set_interrupt_state (save); 27 | } 28 | 29 | void gpio_set (pin_t pin, bool level) 30 | { 31 | if (level) 32 | { 33 | switch (pin.port_index) 34 | { 35 | case 0: FIO0SET = (1u << pin.bit_pos); break; 36 | case 1: FIO1SET = (1u << pin.bit_pos); break; 37 | case 2: FIO2SET = (1u << pin.bit_pos); break; 38 | case 3: FIO3SET = (1u << pin.bit_pos); break; 39 | case 4: FIO4SET = (1u << pin.bit_pos); break; 40 | } 41 | } 42 | else 43 | { 44 | switch (pin.port_index) 45 | { 46 | case 0: FIO0CLR = (1u << pin.bit_pos); break; 47 | case 1: FIO1CLR = (1u << pin.bit_pos); break; 48 | case 2: FIO2CLR = (1u << pin.bit_pos); break; 49 | case 3: FIO3CLR = (1u << pin.bit_pos); break; 50 | case 4: FIO4CLR = (1u << pin.bit_pos); break; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/gpio.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | struct pin_t 5 | { 6 | unsigned char port_index : 3; 7 | unsigned char bit_pos : 5; 8 | }; 9 | 10 | void gpio_init(); 11 | void gpio_make_output (pin_t pin); 12 | void gpio_set (pin_t pin, bool level); 13 | inline void gpio_clear (pin_t pin) { gpio_set (pin, false); } 14 | inline void gpio_set (pin_t pin) { gpio_set (pin, true); } 15 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/scheduler.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | //#include "event_queue.h" 4 | //#include 5 | #include 6 | 7 | void scheduler_init (uint32_t timer, uint32_t clock_frequency); 8 | bool scheduler_is_init(); 9 | uint32_t scheduler_get_time_ms32(); 10 | uint64_t scheduler_get_time_ms64(); 11 | void scheduler_wait (uint32_t ms); 12 | 13 | struct timer_t; 14 | 15 | timer_t* scheduler_schedule_irql_timer (void (*callback)(void*), void* callback_arg, const char* debug_name, uint32_t period_ms, bool repeatable); 16 | timer_t* scheduler_schedule_irql_timer (void (*callback)(), const char* debug_name, uint32_t period_ms, bool repeatable); 17 | timer_t* scheduler_schedule_event_timer (void (*callback)(void*), void* callback_arg, const char* debug_name, uint32_t period_ms, bool repeatable); 18 | timer_t* scheduler_schedule_event_timer (void (*callback)(), const char* debug_name, uint32_t period_ms, bool repeatable); 19 | void scheduler_cancel_timer (timer_t* timer); 20 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/serial_console.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | struct serial_command 5 | { 6 | const char* command; 7 | const char* description; 8 | void (*handler)(const char* params); 9 | }; 10 | 11 | void serial_console_init (unsigned uart_index, unsigned clock_frequency); 12 | void serial_console_register_command_set (const serial_command* commands); 13 | void serial_console_unregister_command_set (const serial_command* commands); 14 | void serial_console_enable_insert_cr_before_lf (bool enable); 15 | void indent(); 16 | void unindent(); 17 | 18 | #define ANSI_WHITEONBLACK "\x1B[0;37;40m" 19 | #define ANSI_GREENONBLACK "\x1B[0;32;40m" 20 | #define ANSI_YELLOWONBLACK "\x1B[0;33;40m" 21 | #define ANSI_BLACKONYELLOW "\x1B[0;30;43m" 22 | #define ANSI_REDONBLACK "\x1B[0;31;40m" 23 | #define ANSI_CLEAR_SCREEN "\x1B[2J" 24 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/timer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "timer.h" 3 | #include "vic.h" 4 | #include 5 | #include 6 | #include 7 | 8 | static const size_t timer_count = 4; 9 | 10 | static timer_callback callbacks[timer_count]; 11 | 12 | static void timer0_isr() 13 | { 14 | T0IR = 1; // clear interrupt flag 15 | callbacks[0](); 16 | } 17 | 18 | void timer_init (uint32_t timer, uint32_t clock_frequency, uint32_t ticks_per_second, timer_callback callback) 19 | { 20 | if (timer == 0) 21 | { 22 | PCONP_bit.PCTIM0 = 1; 23 | PCLKSEL0_bit.PCLK_TIMER0 = 1; // from main clock 24 | T0MR0 = clock_frequency / ticks_per_second; 25 | T0MCR = 3; // Interrupt and Reset on MR0 26 | T0TCR = 1; // enable it 27 | callbacks[0] = callback; 28 | VIC_SetVectoredIRQ (timer0_isr, 4, VIC_TIMER0); 29 | } 30 | else 31 | assert(false); // not implemented 32 | } 33 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/timer.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | typedef void (*timer_callback)(); 6 | 7 | void timer_init (uint32_t timer, uint32_t clock_frequency, uint32_t ticks_per_second, timer_callback callback_irql); 8 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/uart.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | typedef void (*uart_rx_callback) (unsigned uart_index, unsigned char data); 5 | 6 | void uart_init (unsigned uart_index, unsigned clock_frequency, unsigned baudrate, uart_rx_callback rx_callback); 7 | void uart_send_blocking (unsigned uart_index, unsigned char data); 8 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/vic.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "vic.h" 3 | #include 4 | #include 5 | #include 6 | 7 | static __interwork void IRQ_Handler_Thumb () 8 | { 9 | typedef void (*InterruptFunction) (); 10 | 11 | InterruptFunction function = (InterruptFunction) (unsigned int) VICADDRESS; 12 | 13 | assert (function != 0); 14 | 15 | function(); // Call vectored interrupt function. 16 | 17 | // Clear interrupt in VIC. 18 | VICADDRESS = 0; 19 | } 20 | 21 | extern "C" __irq __arm void IRQ_Handler () 22 | { 23 | IRQ_Handler_Thumb(); 24 | } 25 | 26 | void VIC_Init(void) 27 | { 28 | volatile unsigned long * pVecAdd, *pVecCntl; 29 | int i; 30 | // Assign all interrupt channels to IRQ 31 | VICINTSELECT = 0; 32 | // Disable all interrupts 33 | VICINTENCLEAR = 0xFFFFFFFF; 34 | // Clear all software interrupts 35 | VICSOFTINTCLEAR = 0xFFFFFFFF; 36 | // VIC registers can be accessed in User or privileged mode 37 | VICPROTECTION = 0; 38 | // Clear interrupt 39 | VICADDRESS = 0; 40 | 41 | // Clear address of the Interrupt Service routine (ISR) for vectored IRQs 42 | // and disable all vectored IRQ slots 43 | for(i = 0, pVecCntl = &VICVECTPRIORITY0, pVecAdd = &VICVECTADDR0; i < 32; ++i) 44 | { 45 | *pVecCntl++ = *pVecAdd++ = 0; 46 | } 47 | } 48 | 49 | /************************************************************************* 50 | * Function Name: VIC_SetVectoredIRQ 51 | * Parameters: void(*pIRQSub)() 52 | * unsigned int VicIrqSlot 53 | * unsigned int VicIntSouce 54 | * 55 | * Return: void 56 | * 57 | * Description: Init vectored interrupts 58 | * 59 | *************************************************************************/ 60 | 61 | void VIC_SetVectoredIRQ(void(*pIRQSub)(), unsigned int Priority, unsigned int VicIntSource) 62 | { 63 | // load base address of vectored address registers 64 | volatile unsigned long* pReg = &VICVECTADDR0; 65 | 66 | // Set Address of callback function to corresponding Slot 67 | *(pReg+VicIntSource) = (unsigned int) pIRQSub; 68 | 69 | // load base address of ctrl registers 70 | pReg = &VICVECTPRIORITY0; 71 | 72 | // Set source channel and enable the slot 73 | *(pReg+VicIntSource) = Priority; 74 | 75 | // Clear FIQ select bit 76 | VICINTSELECT &= ~(1u << VicIntSource); 77 | 78 | VICINTENABLE = (1u << VicIntSource); 79 | } 80 | 81 | __arm __interwork bool irq_enabled() 82 | { 83 | return (__get_CPSR () & 0x80) == 0; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/drivers/vic.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | void VIC_Init (); 5 | 6 | void VIC_SetVectoredIRQ (void(*pIRQSub)(), unsigned int Priority, unsigned int VicIntSource); 7 | 8 | __arm __interwork bool irq_enabled(); 9 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/serial_commands.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "stp.h" 3 | #include "drivers/serial_console.h" 4 | #include 5 | #include 6 | #include 7 | 8 | extern STP_BRIDGE* bridge; 9 | 10 | static void process_log_command (const char* params) 11 | { 12 | if (*params == 0) 13 | { 14 | printf ("STP logging is currently %s.\r\n", STP_IsLoggingEnabled(bridge) ? "enabled" : "disabled"); 15 | return; 16 | } 17 | 18 | if (strcasecmp(params, "on") == 0) 19 | { 20 | STP_EnableLogging (bridge, true); 21 | printf ("STP logging is now %s.\r\n", "enabled"); 22 | } 23 | else if (strcasecmp(params, "off") == 0) 24 | { 25 | STP_EnableLogging (bridge, false); 26 | printf ("STP logging is now %s.\r\n", "disabled"); 27 | } 28 | else 29 | printf ("Wrong params.\r\n"); 30 | } 31 | 32 | static void process_stp_command (const char* params) 33 | { 34 | if (*params == 0) 35 | { 36 | printf ("STP is currently %s.\r\n", STP_IsBridgeStarted(bridge) ? "enabled" : "disabled"); 37 | return; 38 | } 39 | 40 | if (strcasecmp(params, "on") == 0) 41 | { 42 | if (STP_IsBridgeStarted(bridge)) 43 | printf ("STP is already %s.\r\n", "enabled"); 44 | else 45 | { 46 | printf ("Enabling STP...\r\n"); 47 | STP_StartBridge(bridge, true); 48 | printf ("STP is now %s.\r\n", "enabled"); 49 | } 50 | } 51 | else if (strcasecmp(params, "off") == 0) 52 | { 53 | if (!STP_IsBridgeStarted(bridge)) 54 | printf ("STP is already %s.\r\n", "disabled"); 55 | else 56 | { 57 | printf ("Disabling STP...\r\n"); 58 | STP_StopBridge(bridge, true); 59 | printf ("STP is now %s.\r\n", "disabled"); 60 | } 61 | } 62 | else 63 | printf ("Wrong params.\r\n"); 64 | 65 | } 66 | 67 | extern const serial_command commands[] = { 68 | { "log", "log [on|off] - Enables or disables STP logging.", &process_log_command }, 69 | { "stp", "stp [on|off] - Enables or disables the protocol.", &process_stp_command }, 70 | { 0, 0, 0 } 71 | }; 72 | -------------------------------------------------------------------------------- /TestAppLPC2387+IP175CD/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include "stp.h" 3 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/.gitignore: -------------------------------------------------------------------------------- 1 | /* THUMB Debug 2 | /*.hzs 3 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/KSZ8794CNX.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adigostin/mstp-lib/57089f9b7826a65fdd8d391a31d0598476c3488c/TestAppMK66F+KSZ8794/KSZ8794CNX.pdf -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/clock.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | void clock_init (uint32_t external_clock_mhz); 5 | void clock_enable (void* peripheral_base_address); 6 | bool clock_enabled (void* peripheral_base_address); 7 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/ethernet.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "gpio.h" 4 | 5 | struct ethernet_pins 6 | { 7 | pin_and_af rmii_ref_clk; 8 | pin_and_af rmii_crs_dv; 9 | pin_and_af rmii_rxd0; 10 | pin_and_af rmii_rxd1; 11 | pin_and_af rmii_tx_en; 12 | pin_and_af rmii_txd0; 13 | pin_and_af rmii_txd1; 14 | pin_and_af rmii_mdio; // optional 15 | pin_and_af rmii_mdc; // optional 16 | }; 17 | 18 | struct enet_callbacks 19 | { 20 | void(*rx)(); 21 | void(*tx)(); 22 | void(*error)(); 23 | }; 24 | 25 | void enet_init (const ethernet_pins& pins, const uint8_t mac_address[6], const enet_callbacks* irql_callbacks); 26 | bool enet_is_init(); 27 | void enet_get_mac_address (uint8_t mac_address[6]); 28 | 29 | uint8_t* enet_read_get_buffer (size_t* size); 30 | void enet_read_release_buffer (uint8_t* data); 31 | 32 | uint8_t* enet_write_get_buffer (size_t len); 33 | void enet_write_release_buffer (uint8_t* data); 34 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/event_queue.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | 6 | void event_queue_init (void* buffer, size_t buffer_size); 7 | bool event_queue_is_init(); 8 | bool event_queue_try_push (void(*handler)(void*, size_t), const void* payload, size_t payload_size, const char* debug_name); 9 | bool event_queue_try_push (void(*handler)(void*), void* arg, const char* debug_name); 10 | bool event_queue_try_push (void(*handler)(), const char* debug_name); 11 | void event_queue_pop_all(); 12 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/gpio.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "gpio.h" 3 | #include "clock.h" 4 | #include 5 | 6 | static PORT_Type* port_from_gpio (GPIO_Type* gpio_port) 7 | { 8 | if (gpio_port == PTA) 9 | return PORTA; 10 | if (gpio_port == PTB) 11 | return PORTB; 12 | if (gpio_port == PTC) 13 | return PORTC; 14 | if (gpio_port == PTD) 15 | return PORTD; 16 | if (gpio_port == PTE) 17 | return PORTE; 18 | 19 | assert(false); 20 | return nullptr; 21 | } 22 | 23 | void gpio_make_output (GPIO_Type* gpio_port, uint32_t bit, bool initial_level) 24 | { 25 | auto port = port_from_gpio(gpio_port); 26 | 27 | if (!clock_enabled(port)) 28 | clock_enable(port); 29 | 30 | if (initial_level) 31 | gpio_port->PSOR = (1u << bit); 32 | else 33 | gpio_port->PCOR = (1u << bit); 34 | gpio_port->PDDR |= (1u << bit); // make pin output 35 | port->PCR[bit] = 0x0100; // make pin GPIO 36 | } 37 | 38 | void gpio_make_output (const struct pin& pin, bool initial_level) 39 | { 40 | gpio_make_output(pin.port, pin.bit, initial_level); 41 | } 42 | 43 | void gpio_make_alternate (GPIO_Type* gpio_port, uint32_t bit, uint32_t af) 44 | { 45 | auto port = port_from_gpio(gpio_port); 46 | if (!clock_enabled(port)) 47 | clock_enable(port); 48 | 49 | port->PCR[bit] = (af << 8); 50 | } 51 | 52 | void gpio_make_alternate (const pin_and_af& pinaf) 53 | { 54 | auto port = port_from_gpio(pinaf.pin.port); 55 | if (!clock_enabled(port)) 56 | clock_enable(port); 57 | 58 | port->PCR[pinaf.pin.bit] = (pinaf.af << 8); 59 | } 60 | 61 | void gpio_set (GPIO_Type* gpio_port, uint32_t bit, bool level) 62 | { 63 | if (level) 64 | gpio_port->PSOR = (1u << bit); 65 | else 66 | gpio_port->PCOR = (1u << bit); 67 | } 68 | 69 | void gpio_set (const struct pin& pin, bool level) 70 | { 71 | if (level) 72 | pin.port->PSOR = (1u << pin.bit); 73 | else 74 | pin.port->PCOR = (1u << pin.bit); 75 | } 76 | 77 | void gpio_toggle (GPIO_Type* gpio_port, uint32_t bit) 78 | { 79 | gpio_port->PTOR = (1u << bit); 80 | } 81 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/gpio.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | 6 | struct pin 7 | { 8 | GPIO_Type* port; // one of PTA, PTB... 9 | uint32_t bit; 10 | }; 11 | 12 | struct pin_and_af 13 | { 14 | struct pin pin; 15 | uint32_t af; 16 | }; 17 | 18 | void gpio_make_output (GPIO_Type* gpio_port, uint32_t bit, bool initial_level); 19 | void gpio_make_output (const struct pin& pin, bool initial_level); 20 | void gpio_make_alternate (GPIO_Type* gpio_port, uint32_t bit, uint32_t af); 21 | void gpio_make_alternate (const pin_and_af& pinaf); 22 | void gpio_set (GPIO_Type* gpio_port, uint32_t bit, bool level); 23 | void gpio_set (const struct pin& pin, bool level); 24 | void gpio_toggle (GPIO_Type* gpio_port, uint32_t bit); 25 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/pit.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "pit.h" 3 | #include "clock.h" 4 | #include 5 | 6 | static pit_callback_t callbacks[4]; 7 | 8 | void pit_init (uint32_t pit_channel, uint32_t reload_value, pit_callback_t callback) 9 | { 10 | if (!clock_enabled(PIT)) 11 | clock_enable(PIT); 12 | 13 | ::callbacks[pit_channel] = callback; 14 | PIT->CHANNEL[pit_channel].LDVAL = reload_value; 15 | PIT->CHANNEL[pit_channel].TCTRL = 3; // TIE + TEN 16 | PIT->MCR = 1; // MDIS=0, FRZ=1 17 | 18 | NVIC_EnableIRQ ((IRQn_Type)(PIT0_IRQn + pit_channel)); 19 | } 20 | 21 | extern "C" void PIT0_IRQHandler() 22 | { 23 | callbacks[0](); 24 | PIT->CHANNEL[0].TFLG = 1; 25 | } 26 | 27 | extern "C" void PIT1_IRQHandler() 28 | { 29 | callbacks[1](); 30 | PIT->CHANNEL[1].TFLG = 1; 31 | } 32 | 33 | extern "C" void PIT2_IRQHandler() 34 | { 35 | callbacks[2](); 36 | PIT->CHANNEL[2].TFLG = 1; 37 | } 38 | 39 | extern "C" void PIT3_IRQHandler() 40 | { 41 | callbacks[3](); 42 | PIT->CHANNEL[3].TFLG = 1; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/pit.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | typedef void (*pit_callback_t)(); 6 | 7 | void pit_init (uint32_t pit_channel, uint32_t reload_value, pit_callback_t callback); 8 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/scheduler.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "event_queue.h" 4 | #include 5 | 6 | void scheduler_init(); 7 | bool scheduler_is_init(); 8 | void scheduler_process_tick_irql(); 9 | uint32_t scheduler_get_time_ms32(); 10 | uint64_t scheduler_get_time_ms64(); 11 | void scheduler_wait (uint32_t ms); 12 | 13 | struct timer_t; 14 | 15 | timer_t* scheduler_schedule_irql_timer (void (*callback)(void*), void* callback_arg, const char* debug_name, uint32_t period_ms, bool repeatable); 16 | timer_t* scheduler_schedule_irql_timer (void (*callback)(), const char* debug_name, uint32_t period_ms, bool repeatable); 17 | timer_t* scheduler_schedule_event_timer (void (*callback)(void*), void* callback_arg, const char* debug_name, uint32_t period_ms, bool repeatable); 18 | timer_t* scheduler_schedule_event_timer (void (*callback)(), const char* debug_name, uint32_t period_ms, bool repeatable); 19 | void scheduler_cancel_timer (timer_t* timer); 20 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/serial_console.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | struct serial_command 5 | { 6 | const char* command; 7 | const char* description; 8 | void (*handler)(const char* params); 9 | }; 10 | 11 | void serial_console_init (void(*output)(char ch), bool echo_input, bool use_crlf); 12 | void serial_console_process_input (char ch); 13 | void serial_console_register_command_set (const serial_command* commands); 14 | void serial_console_unregister_command_set (const serial_command* commands); 15 | void indent(); 16 | void unindent(); 17 | 18 | #define ANSI_WHITEONBLACK "\x1B[0;37;40m" 19 | #define ANSI_GREENONBLACK "\x1B[0;32;40m" 20 | #define ANSI_YELLOWONBLACK "\x1B[0;33;40m" 21 | #define ANSI_BLACKONYELLOW "\x1B[0;30;43m" 22 | #define ANSI_REDONBLACK "\x1B[0;31;40m" 23 | #define ANSI_CLEAR_SCREEN "\x1B[2J" 24 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/spi.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "spi.h" 3 | #include "clock.h" 4 | 5 | void spi_init (SPI_Type* spi, const spi_pins& pins, const pin_and_af* cs_pins, size_t cs_pin_count, uint32_t baud_rate) 6 | { 7 | // TODO: assert not init 8 | 9 | clock_enable (spi); 10 | 11 | gpio_make_alternate (pins.clk); 12 | if (pins.mosi.pin.port != nullptr) 13 | gpio_make_alternate (pins.mosi); 14 | if (pins.miso.pin.port != nullptr) 15 | gpio_make_alternate (pins.miso); 16 | 17 | for (size_t i = 0; i < cs_pin_count; i++) 18 | { 19 | if (cs_pins[i].pin.port) 20 | gpio_make_alternate (cs_pins[i]); 21 | } 22 | 23 | // TODO: maybe disable the FIFOs by setting MCR[DIS_TXF] and MCR[DIS_RXF] 24 | spi->CTAR[0] = (7u << SPI_CTAR_FMSZ_SHIFT); 25 | spi->MCR = spi->MCR & ~(SPI_MCR_MDIS_MASK | SPI_MCR_HALT_MASK) | SPI_MCR_MSTR_MASK | SPI_MCR_PCSIS_MASK; 26 | } 27 | 28 | void spi_transfer_blocking (SPI_Type* spi, uint32_t cs, const uint8_t* out_data, uint8_t* in_data, size_t size) 29 | { 30 | for (size_t i = 0; i < size; i++) 31 | { 32 | while ((spi->SR & SPI_SR_TFFF_MASK) == 0) 33 | ; 34 | 35 | bool last = (i == size - 1); 36 | uint32_t pushr = spi->PUSHR & 0x03C00000u; // retain the reserved bits 37 | if (!last) 38 | pushr |= SPI_PUSHR_CONT_MASK; 39 | 40 | if (last) 41 | pushr |= SPI_PUSHR_EOQ_MASK; 42 | 43 | pushr |= (cs << SPI_PUSHR_PCS_SHIFT); 44 | pushr |= out_data[i]; 45 | spi->PUSHR = pushr; 46 | 47 | while ((spi->SR & SPI_SR_RFDF_MASK) == 0) 48 | ; 49 | uint32_t popr = spi->POPR; 50 | spi->SR = SPI_SR_RFDF_MASK; 51 | in_data[i] = (uint8_t)popr; 52 | } 53 | 54 | while ((spi->SR & SPI_SR_TCF_MASK) == 0) 55 | ; 56 | spi->SR = (SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK); 57 | } 58 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/spi.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "gpio.h" 4 | #include 5 | 6 | struct spi_pins 7 | { 8 | pin_and_af clk; 9 | pin_and_af mosi; 10 | pin_and_af miso; 11 | }; 12 | 13 | void spi_init (SPI_Type* spi, const spi_pins& pins, const pin_and_af* cs_pins, size_t cs_pin_count, uint32_t baud_rate); 14 | 15 | void spi_transfer_blocking (SPI_Type* spi, uint32_t chip_select, const uint8_t* out_data, uint8_t* in_data, size_t size); 16 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/uart.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "uart.h" 3 | 4 | void uart_init (LPUART_Type* uart) 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/drivers/uart.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "gpio.h" 4 | 5 | typedef void (*uart_rxne_callback_t)(uint8_t ch); 6 | 7 | void uart_init (LPUART_Type* uart); 8 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/embOSIP_SwitchBoard_V2.0_WEB_Schematic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adigostin/mstp-lib/57089f9b7826a65fdd8d391a31d0598476c3488c/TestAppMK66F+KSZ8794/embOSIP_SwitchBoard_V2.0_WEB_Schematic.pdf -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/switch.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "switch.h" 3 | #include "drivers/spi.h" 4 | #include "drivers/scheduler.h" 5 | 6 | static constexpr uint32_t switch_spi_chip_select = 1; 7 | 8 | void switch_init() 9 | { 10 | // TODO: Raise the SPI speed. Switch chip can go up to 50 MHz. 11 | static const struct spi_pins spi_pins = { .clk = { { PTB, 11 }, 2 }, .mosi = { { PTB, 16 }, 2 }, .miso = { { PTB, 17 }, 2 } }; 12 | static const pin_and_af spi_cs_pins[] = { { { PTB, 10 }, 2 } }; 13 | spi_init (SPI1, spi_pins, spi_cs_pins, sizeof(spi_cs_pins) / sizeof(spi_cs_pins[0]), 1000000); 14 | 15 | // Reset the switch IC, needed in case firmware restarts. 16 | gpio_make_output (PTA, 24, false); 17 | scheduler_wait(2); 18 | gpio_set (PTA, 24, true); 19 | scheduler_wait(2); 20 | 21 | // Now keep reading from the switch the Chip ID registers until we get some known values. 22 | // The dev board has a large capacitor on the switch reset pin and we have to wait quite 23 | // a bit after power up before we can talk to the switch. 24 | while (true) 25 | { 26 | auto chip_id0 = switch_read_reg(0); 27 | auto chip_id1 = switch_read_reg(1); 28 | if ((chip_id0 == 0x87) && ((chip_id1 & 0xF0) == 0x60)) 29 | break; 30 | } 31 | } 32 | 33 | void switch_write_reg (uint16_t reg, uint8_t value) 34 | { 35 | const uint8_t tx[3] = { (uint8_t)(0x40 | (reg >> 7)), (uint8_t)(reg << 1), value }; 36 | uint8_t rx[3]; 37 | spi_transfer_blocking(SPI1, switch_spi_chip_select, tx, rx, 3); 38 | } 39 | 40 | uint8_t switch_read_reg (uint16_t reg) 41 | { 42 | const uint8_t tx[3] = { (uint8_t)(0x60 | (reg >> 7)), (uint8_t)(reg << 1), 0 }; 43 | uint8_t rx[3]; 44 | spi_transfer_blocking (SPI1, switch_spi_chip_select, tx, rx, 3); 45 | return rx[2]; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /TestAppMK66F+KSZ8794/switch.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | void switch_init(); 6 | void switch_write_reg (uint16_t reg, uint8_t value); 7 | uint8_t switch_read_reg (uint16_t reg); 8 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/.gitignore: -------------------------------------------------------------------------------- 1 | TestAppSTM32+8836352 Debug 2 | *.hzs 3 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/8836352.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | enum switch_dev_addr 6 | { 7 | switch_dev_addr_phy0 = 0, 8 | switch_dev_addr_phy1 = 1, 9 | switch_dev_addr_phy2 = 2, 10 | switch_dev_addr_phy3 = 3, 11 | switch_dev_addr_phy4 = 4, 12 | switch_dev_addr_serdes = 15, 13 | switch_dev_addr_port0 = 0x10, 14 | switch_dev_addr_port1 = 0x11, 15 | switch_dev_addr_port2 = 0x12, 16 | switch_dev_addr_port3 = 0x13, 17 | switch_dev_addr_port4 = 0x14, 18 | switch_dev_addr_port5 = 0x15, 19 | switch_dev_addr_port6 = 0x16, 20 | switch_dev_addr_global1 = 0x1B, 21 | switch_dev_addr_global2 = 0x1C, 22 | switch_dev_addr_global3 = 0x1D, 23 | }; 24 | 25 | static constexpr uint8_t global2_smi_phy_command = 0x18; 26 | static constexpr uint8_t global2_smi_phy_data = 0x19; 27 | 28 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/assert.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "assert.h" 3 | #include 4 | #include 5 | 6 | extern "C" void __assert(const char *file, int line) 7 | { 8 | __disable_irq(); 9 | printf ("\r\nAssertion failed in %s, line %d.\r\n", file, line); 10 | printf ("Restarting the firmware...\r\n"); 11 | asm ("BKPT 0"); 12 | volatile bool loop = true; 13 | while(loop) 14 | ; 15 | } 16 | 17 | extern "C" void HardFault_Handler() 18 | { 19 | __disable_irq(); 20 | printf ("HardFault_Handler() called.\r\n"); 21 | printf ("Restarting the firmware...\r\n"); 22 | volatile bool loop = true; 23 | while(loop) 24 | ; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/assert.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #undef assert 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | extern void __assert(const char *__filename, int __line); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #ifdef NDEBUG 17 | #define assert(ignore) ((void)0) 18 | #else 19 | #define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__)) 20 | #endif 21 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/clock.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | enum class clock_pllsaip { div2 = 0, div4 = 1, div6 = 2, div8 = 3 }; 6 | enum class clock_pllsaidivr { div2 = 0, div4 = 1, div8 = 2, div16 = 3 }; 7 | enum class clock_pllsaidivq { 8 | div1 = 0, div2 = 1, div3 = 2, div4 = 3, 9 | div5 = 4, div6 = 5, div7 = 6, div8 = 7, 10 | div9 = 8, div10 = 9, div11 = 10, div12 = 11, 11 | div13 = 12, div14 = 13, div15 = 14, div16 = 15, 12 | div17 = 16, div18 = 17, div19 = 18, div20 = 19, 13 | div21 = 20, div22 = 21, div23 = 22, div24 = 23, 14 | div25 = 24, div26 = 25, div27 = 26, div28 = 27, 15 | div29 = 28, div30 = 29, div31 = 30, div32 = 31 16 | }; 17 | 18 | struct clock_pll_sai_init 19 | { 20 | uint32_t pllsain; // multiplier 50...432 21 | clock_pllsaip pllsaip; // divider for the 48 MHz clock for USB, RNG, SDMMC 22 | uint32_t pllsaiq; // divider for the SAI clock 2..15 23 | clock_pllsaidivq pllsaidivq; // further divider for SAI clock 24 | uint32_t pllsair; // divider for LCD clock 25 | clock_pllsaidivr pllsaidivr; // further divider for LCD clock 26 | }; 27 | 28 | void clock_init (uint32_t external_clock_mhz); // or pass 0 to use the internal 16 MHz clock 29 | void clock_enable (void* peripheral_base_address); 30 | bool clock_enabled (void* peripheral_base_address); 31 | uint32_t clock_get_apb1_prescale(); 32 | uint32_t clock_get_apb2_prescale(); 33 | uint32_t clock_get_apb1_freq(); 34 | uint32_t clock_get_apb2_freq(); 35 | uint32_t clock_get_ahb_freq(); 36 | uint32_t clock_get_sysclk_freq(); 37 | uint32_t clock_get_pll_input_freq(); 38 | uint32_t clock_get_pll_output_freq(); 39 | uint32_t clock_get_hs_freq(); 40 | uint32_t clock_get_freq (void* peripheral_base_address); 41 | void clock_init_pllsai (const clock_pll_sai_init& s); 42 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/ethernet.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "gpio.h" 4 | #include 5 | 6 | struct ethernet_pins 7 | { 8 | pin_and_af_t rmii_ref_clk; 9 | pin_and_af_t rmii_mdio; 10 | pin_and_af_t rmii_mdc; 11 | pin_and_af_t rmii_crs_dv; 12 | pin_and_af_t rmii_rxd0; 13 | pin_and_af_t rmii_rxd1; 14 | pin_and_af_t rmii_tx_en; 15 | pin_and_af_t rmii_txd0; 16 | pin_and_af_t rmii_txd1; 17 | }; 18 | 19 | using ethernet_frame_received_t = void(*)(uint8_t* packet, size_t len); 20 | 21 | struct ethernet_diags 22 | { 23 | uint32_t frames_discarded_event_queue_full; 24 | }; 25 | 26 | bool enet_init (const struct ethernet_pins& pins, const uint8_t mac_address[6], ethernet_frame_received_t frame_received); 27 | bool enet_is_init(); 28 | void enet_get_mac_address (uint8_t mac_address[6]); 29 | void enet_send_blocking (const uint8_t* buffer, size_t len); // TODO: zero-copy 30 | void enet_dump_frame (const uint8_t* frame, size_t frame_len); 31 | uint16_t enet_read_smi (uint16_t dev_addr, uint16_t reg_number); 32 | void enet_write_smi (uint16_t dev_addr, uint16_t reg_number, uint16_t value); 33 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/event_queue.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | 6 | void event_queue_init (uint8_t* buffer, size_t buffer_size); 7 | bool event_queue_is_init(); 8 | bool event_queue_try_push (void(*handler)(void*, size_t), const void* payload, size_t payload_size, const char* debug_name); 9 | bool event_queue_try_push (void(*handler)(void*), void* arg, const char* debug_name); 10 | bool event_queue_try_push (void(*handler)(), const char* debug_name); 11 | void event_queue_pop_all(); 12 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/gpio.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | 6 | struct pin_t 7 | { 8 | GPIO_TypeDef* port; 9 | uint32_t bit; 10 | }; 11 | 12 | struct pin_and_af_t 13 | { 14 | pin_t pin; 15 | uint32_t af; 16 | }; 17 | 18 | enum class pin_output_speed_t { low = 0, medium = 1, high = 2, very_high = 3 }; 19 | enum class pin_pull { none = 0, up = 1, down = 2 }; 20 | 21 | void gpio_make_input (const pin_t& pin, pin_pull pull); 22 | void gpio_make_output (const pin_t& pin, pin_output_speed_t output_speed, bool initial_level, bool open_drain = false); 23 | void gpio_make_alternate (const pin_and_af_t& pinaf, pin_output_speed_t output_speed, bool open_drain = false); 24 | bool gpio_is_output (const pin_t& pin); 25 | bool gpio_get (const pin_t& pin); 26 | void gpio_set (const pin_t& pin, bool level); 27 | void gpio_make_output (GPIO_TypeDef* port, const uint8_t* pins, size_t count, pin_output_speed_t output_speed, uint32_t initial_value); 28 | void gpio_set (GPIO_TypeDef* port, const uint8_t* pins, size_t count, uint32_t value); 29 | 30 | template 31 | struct pin_array 32 | { 33 | GPIO_TypeDef* port; 34 | uint8_t pin_numbers[size]; 35 | }; 36 | 37 | template 38 | void gpio_make_output (const pin_array& pins, pin_output_speed_t output_speed, uint32_t initial_value) 39 | { 40 | gpio_make_output (pins.port, pins.pin_numbers, count, output_speed, initial_value); 41 | } 42 | 43 | template 44 | void gpio_set (const pin_array& pins, uint32_t value) 45 | { 46 | gpio_set (pins.port, pins.pin_numbers, count, value); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/mpu.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "mpu.h" 3 | #include 4 | 5 | void mpu_disable() 6 | { 7 | // Make sure outstanding transfers are done. 8 | __DMB(); 9 | 10 | // Disable fault exceptions 11 | SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; 12 | 13 | // Disable the MPU and clear the control register 14 | MPU->CTRL = 0; 15 | } 16 | 17 | void mpu_enable (uint32_t control) 18 | { 19 | // Enable the MPU 20 | MPU->CTRL = control | MPU_CTRL_ENABLE_Msk; 21 | 22 | // Enable fault exceptions 23 | SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; 24 | 25 | // Ensure MPU setting take effects 26 | __DSB(); 27 | __ISB(); 28 | } 29 | 30 | void mpu_config_region (MPU_Region_InitTypeDef *MPU_Init) 31 | { 32 | // Check the parameters 33 | //assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number)); 34 | // assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable)); 35 | 36 | // Set the Region number 37 | MPU->RNR = MPU_Init->Number; 38 | 39 | if (MPU_Init->Enable) 40 | { 41 | // Check the parameters 42 | //assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec)); 43 | //assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission)); 44 | //assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField)); 45 | //assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable)); 46 | //assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable)); 47 | //assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable)); 48 | //assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable)); 49 | //assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size)); 50 | 51 | MPU->RBAR = MPU_Init->BaseAddress; 52 | MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) | 53 | ((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) | 54 | ((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) | 55 | ((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) | 56 | ((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) | 57 | ((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) | 58 | ((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) | 59 | ((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) | 60 | ((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos); 61 | } 62 | else 63 | { 64 | MPU->RBAR = 0x00; 65 | MPU->RASR = 0x00; 66 | } 67 | } -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/scheduler.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "event_queue.h" 4 | #include 5 | #include 6 | 7 | void scheduler_init (TIM_TypeDef* timer); 8 | bool scheduler_is_init(); 9 | uint32_t scheduler_get_time_ms32(); 10 | uint64_t scheduler_get_time_ms64(); 11 | void scheduler_wait (uint32_t ms); 12 | 13 | struct timer_t; 14 | 15 | timer_t* scheduler_schedule_irql_timer (void (*callback)(void*), void* callback_arg, const char* debug_name, uint32_t period_ms, bool repeatable); 16 | timer_t* scheduler_schedule_irql_timer (void (*callback)(), const char* debug_name, uint32_t period_ms, bool repeatable); 17 | timer_t* scheduler_schedule_event_timer (void (*callback)(void*), void* callback_arg, const char* debug_name, uint32_t period_ms, bool repeatable); 18 | timer_t* scheduler_schedule_event_timer (void (*callback)(), const char* debug_name, uint32_t period_ms, bool repeatable); 19 | void scheduler_cancel_timer (timer_t* timer); 20 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/serial_console.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "uart.h" 4 | 5 | struct serial_command 6 | { 7 | const char* command; 8 | const char* description; 9 | void (*handler)(const char* params); 10 | }; 11 | 12 | void serial_console_init (USART_TypeDef* uart, const pin_and_af_t& tx_pin, const pin_and_af_t& rx_pin); 13 | void serial_console_register_command_set (const serial_command* commands); 14 | void serial_console_unregister_command_set (const serial_command* commands); 15 | void serial_console_enable_insert_cr_before_lf (bool enable); 16 | void indent(); 17 | void unindent(); 18 | void print_binary (uint16_t val); 19 | 20 | #define ANSI_WHITEONBLACK "\x1B[0;37;40m" 21 | #define ANSI_GREENONBLACK "\x1B[0;32;40m" 22 | #define ANSI_YELLOWONBLACK "\x1B[0;33;40m" 23 | #define ANSI_BLACKONYELLOW "\x1B[0;30;43m" 24 | #define ANSI_REDONBLACK "\x1B[0;31;40m" 25 | #define ANSI_CLEAR_SCREEN "\x1B[2J" 26 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/timer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "timer.h" 3 | #include "clock.h" 4 | #include "assert.h" 5 | 6 | static constexpr volatile TIM_TypeDef* timers[14] = { TIM1, TIM2, TIM3, TIM4, TIM5, TIM6, TIM7, TIM8, TIM9, TIM10, TIM11, TIM12, TIM13, TIM14 }; 7 | static constexpr IRQn_Type timer_irqs[14] = 8 | { 9 | (IRQn_Type) -1, 10 | TIM2_IRQn, 11 | TIM3_IRQn, 12 | TIM4_IRQn, 13 | TIM5_IRQn, 14 | TIM6_DAC_IRQn, 15 | TIM7_IRQn, 16 | (IRQn_Type) -1, 17 | TIM1_BRK_TIM9_IRQn, 18 | TIM1_UP_TIM10_IRQn, 19 | TIM1_TRG_COM_TIM11_IRQn, 20 | TIM8_BRK_TIM12_IRQn, 21 | TIM8_UP_TIM13_IRQn, 22 | TIM8_TRG_COM_TIM14_IRQn 23 | }; 24 | static constexpr uint32_t timer_count = 14; 25 | 26 | static timer_callback_t callbacks[timer_count]; 27 | 28 | static uint32_t get_timer_index (volatile TIM_TypeDef* timer) 29 | { 30 | for (uint32_t i = 0; i < timer_count; i++) 31 | { 32 | if (timers[i] == timer) 33 | return i; 34 | } 35 | 36 | assert(false); 37 | return -1; 38 | } 39 | 40 | // extern "C" void TIM1_IRQHandler() - not implemented 41 | extern "C" void TIM2_IRQHandler() { TIM2->SR &= ~TIM_SR_UIF; callbacks[ 1](); } 42 | extern "C" void TIM3_IRQHandler() { TIM3->SR &= ~TIM_SR_UIF; callbacks[ 2](); } 43 | extern "C" void TIM4_IRQHandler() { TIM4->SR &= ~TIM_SR_UIF; callbacks[ 3](); } 44 | extern "C" void TIM5_IRQHandler() { TIM5->SR &= ~TIM_SR_UIF; callbacks[ 4](); } 45 | extern "C" void TIM6_DAC_IRQHandler() { TIM6->SR &= ~TIM_SR_UIF; callbacks[ 5](); } 46 | extern "C" void TIM7_IRQHandler() { TIM7->SR &= ~TIM_SR_UIF; callbacks[ 6](); } 47 | // extern "C" void TIM8_IRQHandler() - not implemented 48 | extern "C" void TIM1_BRK_TIM9_IRQHandler() { TIM9->SR &= ~TIM_SR_UIF; callbacks[ 8](); } 49 | extern "C" void TIM1_UP_TIM10_IRQHandler() { TIM10->SR &= ~TIM_SR_UIF; callbacks[ 9](); } 50 | extern "C" void TIM1_TRG_COM_TIM11_IRQHandler() { TIM11->SR &= ~TIM_SR_UIF; callbacks[10](); } 51 | extern "C" void TIM8_BRK_TIM12_IRQHandler() { TIM12->SR &= ~TIM_SR_UIF; callbacks[11](); } 52 | extern "C" void TIM8_UP_TIM13_IRQHandler() { TIM13->SR &= ~TIM_SR_UIF; callbacks[12](); } 53 | extern "C" void TIM8_TRG_COM_TIM14_IRQHandler() { TIM14->SR &= ~TIM_SR_UIF; callbacks[13](); } 54 | 55 | 56 | void timer_init (TIM_TypeDef* timer, uint32_t prescaler_value, uint32_t reload_value, timer_callback_t callback) 57 | { 58 | assert (prescaler_value <= 0xFFFF); 59 | clock_enable (timer); 60 | assert ((timer->CR1 & TIM_CR1_CEN) == 0); 61 | assert (callback != nullptr); 62 | 63 | assert (timer != TIM1); // not yet implemented - it has some complex interrrupts 64 | assert (timer != TIM8); // not yet implemented - it has some complex interrrupts 65 | assert (timer != TIM6); // not yet implemented - something about DAC 66 | 67 | if (reload_value >= 0x10000) 68 | assert ((timer == TIM2) || (timer == TIM5)); 69 | 70 | uint32_t timer_index = get_timer_index(timer); 71 | 72 | auto irq = timer_irqs[timer_index]; 73 | if (irq == -1) 74 | assert(false); // the timer is not yet implemented by this driver 75 | 76 | callbacks[timer_index] = callback; 77 | 78 | timer->PSC = prescaler_value; 79 | timer->ARR = reload_value; 80 | timer->DIER |= TIM_DIER_UIE; 81 | timer->CR1 |= TIM_CR1_CEN; 82 | 83 | NVIC_EnableIRQ (irq); 84 | } 85 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/timer.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | typedef void (*timer_callback_t)(); 6 | 7 | void timer_init (TIM_TypeDef* timer, uint32_t prescaler_value, uint32_t reload_value, timer_callback_t callback); 8 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/drivers/uart.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "gpio.h" 4 | #include 5 | #include 6 | 7 | typedef void (*uart_rxne_callback_t)(uint8_t ch); 8 | typedef void (*uart_tx_callback_t)(void* arg); 9 | 10 | void uart_init (USART_TypeDef* uart, const pin_and_af_t& tx_pin, const pin_and_af_t& rx_pin, uint32_t baud_rate, uart_rxne_callback_t rx_callback); 11 | void uart_set_baud_rate (USART_TypeDef *uart, uint32_t br); 12 | void uart_send_blocking (USART_TypeDef *uart, uint8_t ch); 13 | bool uart_is_sending (USART_TypeDef *uart); 14 | 15 | // note that the packet buffer must remain valid until the callback is called 16 | void uart_send (USART_TypeDef *uart, const uint8_t* packet, size_t len, uart_tx_callback_t callback, void* callback_arg); 17 | -------------------------------------------------------------------------------- /TestAppSTM32+88E6352/section_placement.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /TestAppTM4C129+88E6352/.gitignore: -------------------------------------------------------------------------------- 1 | /TestAppTM4C129+88E6352 clang Debug 2 | /TestAppTM4C129+88E6352 gcc Debug 3 | /TestAppTM4C129+88E6352 clang Release 4 | /TestAppTM4C129+88E6352 gcc Release 5 | *.hzs 6 | -------------------------------------------------------------------------------- /TestAppTM4C129+88E6352/clock.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | void clock_init(); 6 | uint32_t clock_get_freq(); 7 | uint32_t clock_get_time_ms(); 8 | -------------------------------------------------------------------------------- /TestAppTM4C129+88E6352/ethernet.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | 6 | typedef void (*ethernet_rx_callback)(const uint8_t* data, size_t size); 7 | 8 | void ethernet_init (const uint8_t* mac_address); 9 | void ethernet_get_device_address (uint8_t addr[6]); 10 | void ethernet_get_received (ethernet_rx_callback rx_callback); 11 | void* ethernet_transmit_get_buffer (size_t size); 12 | void ethernet_transmit_release_buffer (void* buffer); 13 | -------------------------------------------------------------------------------- /TestAppTM4C129+88E6352/smi.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "smi.h" 3 | #include 4 | #include 5 | 6 | void smi_init() 7 | { 8 | SYSCTL->RCGCSSI |= (1 << 0); // enable SSI0 clock 9 | SYSCTL->RCGCGPIO |= (1 << 0); // enable GPIOA clock 10 | GPIOA_AHB->PCTL |= 0x00FFFF00; // GPIOA pins 2, 3, 4, 5 - special function 15 11 | GPIOA_AHB->AFSEL |= (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5); // GPIOA pins 2, 3, 4, 5 - alternate function 12 | GPIOA_AHB->DEN |= (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5); // digital enable 13 | GPIOA_AHB->ODR |= (1 << 4) | (1 << 5); // pins 4 and 5 - open drain 14 | // SSInClk = SysClk / (CPSR * (1 + SCR)) 15 | // we want SSInClk = 1 MHz 16 | SSI0->CPSR = 2; 17 | SSI0->CR0 = (59 << 8) // SCR = 59 18 | | (1 << 7) // SPH = 1 19 | | (1 << 6) // SPO = 1 20 | | (0 << 4) // FRF = 0 21 | | (15 << 0); // DSS = 15 22 | SSI0->CR1 = (1 << 1); // set SSE (enable module) 23 | } 24 | 25 | 26 | static void write_16b (uint16_t value) 27 | { 28 | assert ((SSI0->SR & (1 << 2)) == 0); // RX FIFO should be empty (RNE bit) 29 | 30 | assert (SSI0->SR & (1 << 1)); // TX FIFO should be not-full (TNF bit) 31 | 32 | SSI0->DR = (uint16_t)~value; 33 | 34 | // Wait till the SSI peripheral puts in the RX FIFO what we just sent, and discard it. 35 | while ((SSI0->SR & (1 << 2)) == 0); 36 | uint16_t read_back_value = SSI0->DR; 37 | assert (read_back_value == value); 38 | } 39 | 40 | static uint16_t read_16b() 41 | { 42 | assert ((SSI0->SR & (1 << 2)) == 0); // RX FIFO should be empty 43 | 44 | assert (SSI0->SR & (1 << 1)); // TX FIFO should be not-full (TNF bit) 45 | 46 | // Send zeroes (which will keep our active-low output undriven) and read back what the switch sends us. 47 | SSI0->DR = 0; 48 | 49 | while ((SSI0->SR & (1 << 2)) == 0); 50 | uint16_t value = SSI0->DR; 51 | return value; 52 | } 53 | 54 | void smi_write (uint8_t phy_addr, uint8_t reg_addr, uint16_t data) 55 | { 56 | // https://en.wikipedia.org/wiki/Management_Data_Input/Output 57 | 58 | uint16_t command = 59 | (0b01 << 14) // ST 60 | | (0b01 << 12) // OP 61 | | (phy_addr << 7) // PA5 62 | | (reg_addr << 2) // RA5 63 | | 0b10; // TA 64 | 65 | write_16b (0xFFFF); // 16 bits of preamble are enough for 88E6352. 66 | write_16b (command); 67 | write_16b (data); 68 | } 69 | 70 | uint16_t smi_read (uint8_t phy_addr, uint8_t reg_addr) 71 | { 72 | // https://en.wikipedia.org/wiki/Management_Data_Input/Output 73 | 74 | uint16_t command = 75 | (0b01 << 14) // ST 76 | | (0b10 << 12) // OP 77 | | (phy_addr << 7) // PA5 78 | | (reg_addr << 2) // RA5 79 | | 0b10; // TA 80 | 81 | write_16b (0xFFFF); // 16 bits of preamble are enough for 88E6352. 82 | write_16b (command); 83 | return read_16b(); 84 | } 85 | -------------------------------------------------------------------------------- /TestAppTM4C129+88E6352/smi.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | void smi_init(); 6 | void smi_write (uint8_t phy_addr, uint8_t reg_addr, uint16_t data); 7 | uint16_t smi_read (uint8_t phy_addr, uint8_t reg_addr); 8 | -------------------------------------------------------------------------------- /TestAppTM4C129+88E6352/switch.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MARVELL_MDIO_H_ 3 | #define MARVELL_MDIO_H_ 4 | 5 | #include 6 | 7 | enum switch_phy 8 | { 9 | switch_phy_0 = 0, 10 | switch_phy_1 = 1, 11 | switch_phy_2 = 2, 12 | switch_phy_3 = 3, 13 | switch_phy_4 = 4, 14 | switch_phy_serdes = 15, 15 | }; 16 | 17 | enum switch_dev_addr 18 | { 19 | switch_dev_addr_port0 = 0x10, 20 | switch_dev_addr_port1 = 0x11, 21 | switch_dev_addr_port2 = 0x12, 22 | switch_dev_addr_port3 = 0x13, 23 | switch_dev_addr_port4 = 0x14, 24 | switch_dev_addr_port5 = 0x15, 25 | switch_dev_addr_port6 = 0x16, 26 | switch_dev_addr_global1 = 0x1B, 27 | switch_dev_addr_global2 = 0x1C, 28 | switch_dev_addr_global3 = 0x1D, 29 | }; 30 | 31 | void switch_power_up_phys (uint32_t mdio_addr); 32 | uint32_t switch_read_register (uint32_t mdio_addr, switch_dev_addr dev_addr, uint32_t reg_addr); 33 | void switch_write_register (uint32_t mdio_addr, switch_dev_addr dev_addr, uint32_t reg_addr, uint32_t value); 34 | uint32_t switch_read_phy_register (uint32_t mdio_addr, switch_phy phy, uint32_t reg_addr); 35 | void switch_write_phy_register (uint32_t mdio_addr, switch_phy phy, uint32_t reg_addr, uint32_t value); 36 | #endif 37 | -------------------------------------------------------------------------------- /TestAppTM4C129+88E6352/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include "../mstp-lib/stp.h" 3 | -------------------------------------------------------------------------------- /_help/BlankForm.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Untitled Page 7 | 8 | 9 |

name

10 |
11 |
12 | void __stdcall 
13 | (
14 |     unsigned int 
15 | );
16 | 
17 |

18 | Summary

19 |

20 |

21 |

22 | Parameters

23 |
24 |
25 |
26 |
27 |

28 | Return value

29 |
30 |
If the function succeeds: STATUS_SUCCESS.
31 |
If the function fails: a STATUS enumeration value 32 | other than STATUS_SUCCESS.
33 |
34 |

35 | Remarks

36 |

37 |

38 |

Function information

39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
Include headeraaa.h
Required source codeaaa.cpp
49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /_help/STP_CALLBACKS.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_CALLBACKS 7 | 8 | 9 |

STP_CALLBACKS

10 |
11 |
12 | struct STP_CALLBACKS
13 | {
14 |     STP_CALLBACK_ENABLE_BPDU_TRAPPING        enableBpduTrapping;
15 |     STP_CALLBACK_ENABLE_LEARNING             enableLearning;
16 |     STP_CALLBACK_ENABLE_FORWARDING           enableForwarding;
17 |     STP_CALLBACK_TRANSMIT_GET_BUFFER         transmitGetBuffer;
18 |     STP_CALLBACK_TRANSMIT_RELEASE_BUFFER     transmitReleaseBuffer;
19 |     STP_CALLBACK_FLUSH_FDB                   flushFdb;
20 |     STP_CALLBACK_DEBUG_STR_OUT               debugStrOut;
21 |     STP_CALLBACK_ON_TOPOLOGY_CHANGE          onTopologyChange;
22 |     STP_CALLBACK_PORT_ROLE_CHANGED           onPortRoleChanged;
23 |     STP_CALLBACK_ALLOC_AND_ZERO_MEMORY       allocAndZeroMemory;
24 |     STP_CALLBACK_FREE_MEMORY                 freeMemory;
25 | };
26 |

27 | Summary

28 |

29 | Structure containing pointers to application-defined STP callbacks. These callbacks 30 | implement the hardware-specific and platform-specific functionality required by STP, such 31 | as enabling forwarding on a physical port, or allocating memory, or displaying debug text 32 | generated by the STP library.

33 |

34 | Members

35 |

36 |  

37 |

38 | Remarks

39 |

40 | All these callbacks are called from within library functions such as 41 | STP_CreateBridge, STP_SetPortPriority, 42 | STP_OnBpduReceived etc. With other words, 43 | first the application calls some library function, then that function calls application's 44 | STP callbacks to do hardware-specific work, and then the function returns.

45 |

46 | The application is allowed to call from within these callbacks only Get-type library functions. 47 | Set-type library functions (those that alter the STP operation) must not be 48 | called from within these callbacks.

49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /_help/STP_DestroyBridge.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_DestroyBridge 7 | 8 | 9 |

STP_DestroyBridge

10 |
11 |
void STP_DestroyBridge (STP_BRIDGE* bridge)
12 |

13 | Summary

14 |

15 | Releases all memory allocated for the given bridge.

16 |

17 | Parameters

18 |
19 |
bridge
20 |
Pointer to a STP_BRIDGE object, obtained from 21 | STP_CreateBridge.
22 |
23 |

24 | Remarks

25 |

26 | The bridge must be stopped when this function is called (i.e., must have never been 27 | started, or must have been stopped with STP_StopBridge).

28 |

29 | This function may not be called from within an STP callback.

30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /_help/STP_EnableLogging.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_EnableLogging 7 | 8 | 9 |

STP_EnableLogging

10 |
11 |
12 | void STP_EnableLogging
13 | (
14 |     STP_BRIDGE* bridge,
15 |     bool        enable
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Enables or disable debug logging on a bridge.

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
enable
29 |
true to enable logging, false to disable it.
30 |
31 |

32 | Remarks

33 |

34 | Support for debug logging can be disabled by defining STP_USE_LOG=0 in 35 | the compiler options. This excludes most logging-related code from compilation, 36 | and it saves about 9 KB of Flash in a GnuARM Release build, and about 37 | 14 KB of Flash in a GnuARM Debug build.

38 | 39 | 40 | -------------------------------------------------------------------------------- /_help/STP_GetBridgeAddress.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetBridgeAddress 7 | 8 | 9 |

STP_GetBridgeAddress

10 |
11 |
12 | const struct STP_BRIDGE_ADDRESS* STP_GetBridgeAddress
13 | (
14 |     const STP_BRIDGE* bridge,
15 | );
16 | 
17 |

18 | Summary

19 |

20 | Gets the bridge address that was set with 21 | STP_CreateBridge or STP_SetBridgeAddress.

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
29 |

30 | Return Value

31 |

32 | Pointer to the bridge address.

33 |

34 | Remarks

35 |

36 | See the Remarks section in STP_SetBridgePriority for information on how the bridge priority is calculated from the bridge address.

37 |

38 | It is allowed to call this function from within an STP callback.

39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /_help/STP_GetBridgePriority.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetBridgePriority 7 | 8 | 9 |

STP_GetBridgePriority

10 |
11 |
12 | unsigned short STP_GetBridgePriority
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int       treeIndex
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Reads the bridge priority, that is, the priority component - most significant 4 bits - of 22 | the BridgeIdentifier (§13.26.2 in 802.1Q-2018).

23 |

24 | Parameters

25 |
26 |
bridge
27 |
Pointer to a STP_BRIDGE object, obtained from 28 | STP_CreateBridge.
29 |
treeIndex
30 |
The zero-based index of the spanning tree for which the bridge priority is to be 31 | returned. For STP or RSTP, this must be zero. For MSTP, this must be zero for the CIST, or 32 | 1..64 for an MSTI.
33 |
34 |

35 | Return value

36 |
37 |
The bridge priority. This is a number between 0 and 61440 (0xF000) hex, in steps of 4096 38 | (0x1000 hex).
39 |
40 |

41 | Remarks

42 |

43 | See the Remarks section at STP_SetBridgePriority 44 | for more information about the bridge priority and about the BridgeIndentifier.

45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /_help/STP_GetMstConfigId.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetMstConfigId 7 | 8 | 9 |

STP_GetMstConfigId

10 |
11 |
12 | const struct STP_MST_CONFIG_ID* STP_GetMstConfigId
13 | (
14 |     const STP_BRIDGE*  bridge,
15 | );
16 | 
17 |

18 | Summary

19 |

20 | Retrieves a pointer to the MST Configuration Identifier.

21 |

22 | Parameters

23 |
24 |
bridge
25 |
Pointer to a STP_BRIDGE object.
26 |
nameOut
27 |
Pointer to an array of chars where this function will write the name.
28 |
29 |

30 | Remarks

31 |

32 | You can call this function even while the bridge is not running MSTP.

33 |

34 | See §13.8 in 802.1Q-2018 for more information about the MST Configuration Identifier.

35 |

36 | It is allowed to call this function from within an STP callback.

37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /_help/STP_GetMstConfigTable.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetMstConfigTable 7 | 8 | 9 |

STP_GetMstConfigTable

10 |
11 |
12 | const struct STP_CONFIG_TABLE_ENTRY* STP_GetMstConfigTable
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int*      entryCountOut
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Retrieves a pointer to the MST configuration table (the VLAN to tree mapping).

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to an STP_BRIDGE object.
27 |
entryCountOut
28 |
Pointer to a variable where this function writes the number 29 | of entries available. This is maxVlanNumber + 1, 30 | where maxVlanNumber is the parameter that was 31 | passed to STP_CreateBridge.
32 |
33 |

34 | Return Value

35 |

36 | The function returns a pointer to the table kept internally by the library.

37 |

38 | Remarks

39 |

40 | You can call this function even when the bridge is not running MSTP.

41 |

42 | Element at index 0 of the table is unused and contains the value 0. Element at index 1 corresponds to VLAN 1, element at index 1 corresponds to VLAN 2 and so on. The table can contain up to 4096 elements.

43 |

44 | See §13.8 in 802.1Q-2018 for more information about the MST Configuration Identifier.

45 |

46 | It is allowed to call this function from within an STP callback.

47 |

48 | See also STP_SetMstConfigTable.

49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /_help/STP_GetMstiCount.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetMstiCount 7 | 8 | 9 |

STP_GetMstiCount

10 |
11 |
12 | unsigned int STP_GetMstiCount (const STP_BRIDGE* bridge);
13 | 
14 |

15 | Summary

16 |

17 | Returns the number of MSTIs on the bridge. This is the value passed to 18 | STP_CreateBridge.

19 |

20 | Parameters

21 |
22 |
bridge
23 |
Pointer to a STP_BRIDGE object.
24 |
25 |

26 | Return value

27 |
28 |
The MSTI count.
29 |
30 |

Remarks

31 |

It is allowed to call this function from within an STP callback.

32 | 33 | 34 | -------------------------------------------------------------------------------- /_help/STP_GetPortAdminPointToPointMAC.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetPortAdminPointToPointMAC 7 | 8 | 9 |

STP_GetPortAdminPointToPointMAC

10 |
11 |
12 | STP_ADMIN_P2P STP_GetPortAdminPointToPointMAC
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int       portIndex,
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Gets the adminPointToPointMAC variable for a given port.

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
portIndex
29 |
The index of the port.
30 |
31 |

32 | Remarks

33 |

34 | See §11.3 in 802.1AC-2016 for more information.

35 |

36 | This function may be called from within an STP callback.

37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /_help/STP_GetPortAutoEdge.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetPortAutoEdge 7 | 8 | 9 |

STP_GetPortAutoEdge

10 |
11 |
12 | bool STP_GetPortAutoEdge
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int       portIndex,
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Gets the AutoEdge variable for a given port.

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
portIndex
29 |
The index of the port.
30 |
31 |

32 | Remarks

33 |

34 | See §13.27.18 in 802.1Q-2018 for more information.

35 |

36 | The STP Library initializes this variable to TRUE, as recommended in the standard.

37 |

38 | This function may be called from within an STP callback.

39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /_help/STP_GetPortCount.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetPortCount 7 | 8 | 9 |

STP_GetPortCount

10 |
11 |
12 | unsigned int STP_GetPortCount (const STP_BRIDGE* bridge);
13 | 
14 |

15 | Summary

16 |

17 | Returns the number of ports on the bridge. This is the value passed to 18 | STP_CreateBridge.

19 |

20 | Parameters

21 |
22 |
bridge
23 |
Pointer to a STP_BRIDGE object.
24 |
25 |

26 | Return value

27 |
28 |
The port count.
29 |
30 |

31 | Remarks 32 |

33 |

It is allowed to call this function from within an STP callback.

34 | 35 | 36 | -------------------------------------------------------------------------------- /_help/STP_GetPortEnabled.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetPortEnabled 7 | 8 | 9 |

STP_GetPortEnabled

10 |
11 |
12 | bool STP_GetPortEnabled
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int       portIndex
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Reads the portEnabled variable (§13.27.45 in 802.1Q-2018).

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
portIndex
29 |
The zero-based index of the port.
30 |
31 |

32 | Return value

33 |
34 |
This function returns true if STP_OnPortEnabled was called last. 35 | It returns false if STP_OnPortDisabled was called last, 36 | or the bridge was just created with STP_CreateBridge.
37 |
38 |

39 | Remarks

40 |

41 | It is allowed to call this function from within an STP callback.

42 | 43 | 44 | -------------------------------------------------------------------------------- /_help/STP_GetPortIdentifier.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetPortIdentifier 7 | 8 | 9 |

STP_GetPortIdentifier

10 |
11 |
12 | unsigned short STP_GetPortIdentifier
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int       portIndex,
16 |     unsigned int       treeIndex
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Returns the port identifier portId for a given port and a given tree.

23 |

24 | Parameters

25 |
26 |
bridge
27 |
Pointer to a STP_BRIDGE object.
28 |
portIndex
29 |
The zero-based index of the port.
30 |
treeIndex
31 |
The zero-based index of the spanning tree for which the portId is to be read. For 32 | STP or RSTP, this must be zero. For MSTP, this must be zero for the CIST, or 1..64 for an 33 | MSTI.
34 |
35 |

36 | Return value

37 |
38 |
The port identifier. This is a number between 0 and 244, in steps of 16.
39 |
40 |

41 | Remarks

42 |

43 | See §13.27.46 in 802.1Q-2018 for more details.

44 |

45 | It is allowed to call this function from within an STP callback.

46 | 47 | 48 | -------------------------------------------------------------------------------- /_help/STP_GetPortOperPointToPointMAC.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetPortOperPointToPointMAC 7 | 8 | 9 |

STP_GetPortOperPointToPointMAC

10 |
11 |
12 | bool STP_GetPortOperPointToPointMAC
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int       portIndex,
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Gets the operPointToPointMAC variable for a given port.

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
portIndex
29 |
The index of the port.
30 |
31 |

32 | Remarks

33 |

34 | See §11.3 in 802.1AC-2016 for more information.

35 |

36 | This function may be called from within an STP callback.

37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /_help/STP_GetPortPriority.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetPortPriority 7 | 8 | 9 |

STP_GetPortPriority

10 |
11 |
12 | unsigned char STP_GetPortPriority
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int       portIndex,
16 |     unsigned int       treeIndex
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Reads the priority component - most significant 4 bits - of the portId. See §13.27.46 in 23 | 802.1Q-2018 for more details.

24 |

25 | Parameters

26 |
27 |
bridge
28 |
Pointer to a STP_BRIDGE object, obtained from 29 | STP_CreateBridge.
30 |
portIndex
31 |
The zero-based index of the port.
32 |
treeIndex
33 |
The zero-based index of the spanning tree for which the port priority is to be read. For 34 | STP or RSTP, this must be zero. For MSTP, this must be zero for the CIST, or 1..64 for an 35 | MSTI.
36 |
37 |

38 | Return value

39 |
40 |
The port priority. This is a number between 0 and 244, in steps of 16.
41 |
42 |

43 | Remarks

44 |

45 | It is allowed to call this function from within an STP callback.

46 | 47 | 48 | -------------------------------------------------------------------------------- /_help/STP_GetTreeIndexFromVlanNumber.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetTreeIndexFromVlanNumber 7 | 8 | 9 |

STP_GetTreeIndexFromVlanNumber

10 |
11 |
12 | unsigned int STP_GetTreeIndexFromVlanNumber
13 | (
14 |     const STP_BRIDGE*  bridge,
15 |     unsigned int       vlanNumber
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Retrieves a tree index mapped to a given VLAN.

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object.
27 |
vlanNumber
28 |
The VLAN number. This must be between zero (inclusive) and the maxVlanNumber 29 | parameter that was passed to STP_CreateBridge (inclusive).
30 |
31 |

32 | Return value

33 |
34 |
The tree index mapped to the specified VLAN.
35 |
36 |

37 | Remarks

38 |

39 | You can call this function from within an STP callback.

40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /_help/STP_GetVersionString.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetVersionString 7 | 8 | 9 |

STP_GetVersionString

10 |
11 |
12 | const char* STP_GetVersionString
13 | (
14 |     enum STP_VERSION version
15 | );
16 | 
17 |

18 | Summary

19 |

20 | Converts an STP_VERSION value to its string representation.

21 |

22 | Parameters

23 |
24 |
version
25 |
One of the STP_VERSION_XXX values.
26 |
27 |

28 | Remarks

29 |

30 | The function checks with an assertion that the parameter is a known enum value.

31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /_help/STP_IsBridgeStarted.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_IsBridgeStarted 7 | 8 | 9 |

STP_IsBridgeStarted

10 |
11 |
12 | bool STP_IsBridgeStarted (const STP_BRIDGE* bridge);
13 | 
14 |

15 | Summary

16 |

17 | Checks whether a bridge is started or stopped.

18 |

19 | Parameters

20 |
21 |
bridge
22 |
Pointer to a STP_BRIDGE object, obtained from 23 | STP_CreateBridge.
24 |
25 |

26 | Return value

27 |
28 |
true if the bridge is started, false if the bridge is stopped.
29 |
30 |

31 | Remarks

32 |

33 | A bridge can be started by calling STP_StartBridge, and 34 | stopped by calling STP_StopBridge.

35 |

36 | It is allowed to call this function from within an STP callback.

37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /_help/STP_OnBpduReceived.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_OnBpduReceived 7 | 8 | 9 |

STP_OnBpduReceived

10 |
11 |
12 | void STP_OnBpduReceived
13 | (
14 |     STP_BRIDGE*          bridge,
15 |     unsigned int         portIndex,
16 |     const unsigned char* bpdu,
17 |     unsigned int         bpduSize,
18 |     unsigned int         timestamp
19 | );
20 | 
21 |

22 | Summary

23 |

24 | Function which the application must call upon receiving a BPDU packet from a physical 25 | port.

26 |

27 | Parameters

28 |
29 |
bridge
30 |
Pointer to an STP_BRIDGE object, obtained from 31 | STP_CreateBridge.
32 |
portIndex
33 |
The index of the port from which this BPDU was received. This information is usually 34 | inserted by the switch IC into the Ethernet frame, after the switch IC was 35 | configured to do so by 36 | StpCallback_EnableBpduTrapping.
37 |
bpdu
38 |
Pointer to the BPDU payload, located in an Ethernet frame just after the LLC field.
39 |
bpduSize
40 |
Size of the BPDU payload.
41 |
timestamp
42 |
A timestamp used for the debug log.
43 |
44 |

45 | Remarks

46 |

47 | Execution of this function is a potentially lengthy process. 48 | It may call various callbacks multiple times.

49 | 50 |

51 | It is allowed to call this function for stopped bridges. In this case it will ignore the BPDU and return immediately.

52 |

53 | This function validates the length of the BPDU before processing its content. It ignores 54 | truncated BPDUs.

55 |

56 | It is recommended that the application, before passing a received BPDU frame to the STP 57 | library, performs a check for malformed frames by comparing the value in the 58 | EtherType/Size field of the frame to the length of the received frame. Such malformed 59 | frames should be discarded, not passed to the STP library.

60 | 61 |

62 | It is recommended that the application, after receiving a BPDU from the bridge IC 63 | and before passing the BPDU to this function, checks that it has up-to-date 64 | information about the "operational" status of the physical port from which it received the 65 | BPDU. Depending on the hardware particularities, it is possible that an application first 66 | 1) receives an Ethernet packet from a physical port, and then 2) 67 | receives information from that port about the link having just been established (e.g., 68 | cable just connected). If the application finds itself in this condition upon receiving a 69 | BPDU, it should first call STP_OnPortEnabled, and 70 | only then STP_OnBpduReceived; the timestamp should be the same value for both calls.

71 |

72 | This function may not be called from within an STP callback.

73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /_help/STP_OnOneSecondTick.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_OnOneSecondTick 7 | 8 | 9 |

STP_OnOneSecondTick

10 |
11 |
12 | void STP_OnOneSecondTick
13 | (
14 |     STP_BRIDGE*   bridge,
15 |     unsigned int  timestamp
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Function which the application must call approximately once every second.

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
timestamp
29 |
A timestamp used for the debug log.
30 |
31 |

32 | Remarks

33 |

34 | If the application runs multiple bridges, is it recommended that a single periodic timer 35 | is set up, and that this function is called for each bridge when this timer triggers, with the same 36 | value for timestamp 37 | for all bridges. This makes it easier to 38 | visualize in the debug log which tick triggered which actions on which 39 | bridge.

40 | 41 |

42 | Execution of this function is a potentially lengthy process. 43 | It may call various callbacks multiple times.

44 |

45 | It is allowed to call this function for stopped bridges. In this case it will return 46 | immediately.

47 |

48 | If many devices are wired in the same STP network, it is recommended that the timer 49 | period is not identical on all devices, but spread a little around the one-second value 50 | (for instance, between 950 and 1050 ms). This helps avoid bursts of STP activity occurring 51 | on all devices at the same time. Note that there's still a chance these bursts are 52 | once in a while synchronized accross the network, so the whole system must still be 53 | designed to handle them.

54 |

55 | This function may not be called from within an STP callback.

56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /_help/STP_OnPortDisabled.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_OnPortDisabled 7 | 8 | 9 |

STP_OnPortDisabled

10 |
11 |
12 | void STP_OnPortDisabled
13 | (
14 |     STP_BRIDGE*   bridge,
15 |     unsigned int  portIndex,
16 |     unsigned int  timestampMilliseconds
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Function which the application must call when 23 | the operational state of a port changes to FALSE. See the Remarks section of this page for 24 | more details, and also the Remarks section of 25 | STP_OnPortEnabled.

26 |

27 | Parameters

28 |
29 |
bridge
30 |
Pointer to a STP_BRIDGE object, obtained from 31 | STP_CreateBridge.
32 |
portIndex
33 |
The index of the port whose operational state has just changed to FALSE.
34 |
timestamp
35 |
A timestamp used for the debug log.
36 |
37 |

38 | Remarks

39 |

40 | Also see the Remarks section of STP_OnPortEnabled.

41 |

42 | It is allowed to call this function for already disabled ports.

43 | 44 |

45 | Execution of this function is a potentially lengthy process. 46 | It may call various callbacks multiple times.

47 |

48 | This function may not be called from within an STP callback.

49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /_help/STP_SetBridgeAddress.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetBridgeAddress 7 | 8 | 9 |

STP_SetBridgeAddress

10 |
11 |
12 | void STP_SetBridgeAddress
13 | (
14 |     STP_BRIDGE*           bridge,
15 |     const unsigned char*  address,
16 |     unsigned int          timestamp
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Function which the application must call every time the MAC address 23 | of the management microcontroller/processor changes, for example when 24 | the end user changes it in a web interface or a CLI.

25 |

26 | Parameters

27 |
28 |
bridge
29 |
Pointer to an STP_BRIDGE object, obtained from 30 | STP_CreateBridge.
31 |
address
32 |
The new MAC address.
33 |
timestamp
34 |
A timestamp used for the debug log.
35 |
36 |

37 | Remarks

38 |

39 | Execution of this function is a potentially lengthy process. 40 | It may call various callbacks multiple times.

41 |

42 | See the Remarks section in STP_SetBridgePriority for information on how the bridge priority is calculated from the bridge address.

43 |

44 | This function may not be called from within an STP callback.

45 | 46 | 47 | -------------------------------------------------------------------------------- /_help/STP_SetBridgePriority.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetBridgePriority 7 | 18 | 19 | 20 |

STP_SetBridgePriority

21 |
22 |
23 | void STP_SetBridgePriority
24 | (
25 |     STP_BRIDGE*     bridge,
26 |     unsigned int    treeIndex,
27 |     unsigned short  bridgePriority,
28 |     unsigned int    timestamp
29 | );
30 | 
31 |

32 | Summary

33 |

34 | Sets the settable priority component - most significant 4 bits - of the BridgeIdentifier 35 | (§13.26.2 in 802.1Q-2018).

36 |

37 | Parameters

38 |
39 |
bridge
40 |
Pointer to a STP_BRIDGE object, obtained from 41 | STP_CreateBridge.
42 |
treeIndex
43 |
The index of the spanning tree for which bridge priority is to be set. For STP or RSTP, 44 | this must be zero. For MSTP, this must be zero for the CIST, or 1..64 for an MSTI.
45 |
bridgePriority
46 |
A value specifiying the bridge priority. Must be between 0 and 61440 (0xF000 hex), in 47 | steps of 4096 (0x1000 hex).
48 |
timestamp
49 |
A timestamp used for the debug log.
50 |
51 |

52 | Remarks

53 |

54 | Default priority is 32768 (0x8000 hex). This default priority is assigned to a bridge when 55 | it is created with STP_CreateBridge.

56 |

57 | The BridgeIdentifier for a given spanning tree is usually represented as 58 | 8000.01-02-03-04-05-06 and consists of:

60 |
    61 |
  • 4 bits set by this function. These are the most 62 | significant bits.
  • 63 |
  • 12 bits with the "system ID extension", which for 64 | STP and RSTP 65 | is zero, and for MSTP is populated by the library with the tree index (zero for the CIST, 66 | 1..64 for MSTIs)
  • 67 |
  • 48 bits with the MAC address. These are the least 68 | significant bits, and they are settable with 69 | STP_SetBridgeAddress.
  • 70 |
71 |

72 | Execution of this function is a potentially lengthy process. 73 | It may call various callbacks multiple times.

74 |

75 | This function may not be called from within an STP callback.

76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /_help/STP_SetMstConfigName.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetMstConfigName 7 | 8 | 9 |

STP_SetMstConfigName

10 |
11 |
12 | void STP_SetMstConfigName
13 | (
14 |     STP_BRIDGE*   bridge,
15 |     const char*   name,
16 |     unsigned int  timestamp
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Sets the Name field of the MST Configuration Identifier.

23 |

24 | Parameters

25 |
26 |
bridge
27 |
Pointer to a STP_BRIDGE object.
28 |
name
29 |
The new name. This must be a null-terminated string of up to 32 characters (up to 33 30 | with the null-terminator).
31 |
timestamp
32 |
A timestamp used for the debug log.
33 |
34 |

35 | Remarks

36 |

37 | This function may be called only for MSTP bridges (i.e., if STP_VERSION_MSTP was passed 38 | to STP_CreateBridge or 39 | STP_SetStpVersion).

40 |

41 | See §13.8 in 802.1Q-2018 for more information about the MST Configuration Identifier.

42 |

43 | If this function is not called, a default configuration name is used which is generated by 44 | STP_CreateBridge. See the Remarks section there for 45 | more information.

46 |

47 | This function may not be called from within an STP callback.

48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /_help/STP_SetMstConfigRevisionLevel.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_GetMstConfigRevisionLevel 7 | 8 | 9 |

STP_SetMstConfigRevisionLevel

10 |
11 |
12 | void STP_SetMstConfigRevisionLevel (STP_BRIDGE* bridge, unsigned short revisionLevel);
13 | 
14 |

15 | Summary

16 |

17 | Sets the Revision Level field of the MST Configuration Identifier.

18 |

19 | Parameters

20 |
21 |
22 |
bridge
23 |
Pointer to a STP_BRIDGE object.
24 |
revisionLevel
25 |
The new Revision Level value.
26 |
27 |
28 | 29 |

30 | Remarks

31 |

32 | This function may be called only for MSTP bridges (i.e., if STP_VERSION_MSTP was passed 33 | to STP_CreateBridge or 34 | STP_SetStpVersion).

35 |

36 | See §13.8 in 802.1Q-2018 for more information about the MST Configuration Identifier.

37 |

38 | If this function is not called, a default revision level is used which is generated by 39 | STP_CreateBridge. See the Remarks section there for 40 | more information.

41 |

42 | This function may not be called from within an STP callback.

43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /_help/STP_SetMstConfigTable.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetMstConfigTable 7 | 8 | 9 |

STP_SetMstConfigTable

10 |
11 |
12 | void STP_SetMstConfigTable
13 | (
14 |     STP_BRIDGE*                   bridge,
15 |     const STP_CONFIG_TABLE_ENTRY* entries,
16 |     unsigned int                  entryCount,
17 |     unsigned int                  timestamp
18 | );
19 | 
20 |

21 | Summary

22 |

23 | Sets the 24 | MST Config Table (VLAN to MSTID mapping) and computes the Digest field of the MST Configuration Identifier.

25 |

26 | Parameters

27 |
28 |
bridge
29 |
Pointer to a STP_BRIDGE object.
30 |
table
31 |
Pointer to an array of STP_CONFIG_TABLE_ENTRY, where each entry specifies a mapping 32 | between a VLAN and its corresponding MSTID. First entry is unused and must be zero; second entry 33 | specifies the tree mapped to VLAN 1; third entry specifies the tree mapped to VLAN 2; and so on.
34 |
entryCount
35 |
The number of entries in table. This must be equal to 1 + maxVlanNumber, 36 | where maxVlanNumber is the value that was passes to STP_CreateBridge.
37 |
timestamp
38 |
A timestamp used for the debug log.
39 |
40 |

41 | Remarks

42 |

43 | This function 44 | can be called also when the bridge isn't running MSTP.

45 |

46 | See §13.8 in 802.1Q-2018 for more information about the MST Configuration Identifier.

47 |

48 | The caller must not attempt to map a VLAN to a non-existent tree, i.e., 49 | the table passed to this function must contain values in the treeIndex field that are <=  50 | mstiCount parameter that was specified in the 51 | call to STP_CreateBridge. The STP library raises assertions for invalid values.

52 |

53 | The STP library computes the Digest as described in 13.7.d) in 802.1Q-2018.

54 |

55 | If this function is not called, a default mapping is used which is generated by 56 | STP_CreateBridge. See the Remarks section there for 57 | more information.

58 |

59 | This function may not be called from within an STP callback.

60 |

61 | See also STP_GetMstConfigTable.

62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /_help/STP_SetPortAdminEdge.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetPortAdminEdge 7 | 8 | 9 |

STP_SetPortAdminEdge

10 |
11 |
12 | void STP_SetPortAdminEdge
13 | (
14 |     STP_BRIDGE*   bridge,
15 |     unsigned int  portIndex,
16 |     bool          adminEdge
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Sets the AdminEdge parameter for a given port.

23 |

24 | Parameters

25 |
26 |
bridge
27 |
Pointer to a STP_BRIDGE object, obtained from 28 | STP_CreateBridge.
29 |
portIndex
30 |
The index of the port for which the AdminEdge parameter is to be set.
31 |
newAdminEdge
32 |
The new value of the AdminEdge parameter.
33 |
34 |

35 | Remarks

36 |

37 | See §13.27.1 in 802.1Q-2018 for more information.

38 |

39 | The current library code was not tested in scenarios where this function is called after the bridge 40 | has been started. It was only tested in scenarios where this function is called once, after STP_CreateBridge is 41 | called, and before STP_StartBridge is called.

42 | 43 |

44 | Execution of this function is a potentially lengthy process. 45 | It may call various callbacks multiple times.

46 |

47 | When a port is configured as Edge by calling this function with adminEdge true, the 48 | library will still be sending BPDUs to that port, and will still need to receive and 49 | process BPDUs from that port. This is not a characteristic of this particular library; it is a 50 | characteristic of the STP protocol itself. This behavior is useful in case the end user 51 | configures a port as Edge by mistake (e.g., correctly configures a port as Edge in one 52 | location but later moves the switch to another location and doesn't remember to 53 | reconfigure that port.)

54 |

55 | This function may not be called from within an STP callback.

56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /_help/STP_SetPortAdminPointToPointMAC.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetPortAdminPointToPointMAC 7 | 8 | 9 |

STP_SetPortAdminPointToPointMAC

10 |
11 |
12 | void STP_SetPortAdminPointToPointMAC
13 | (
14 |     STP_BRIDGE*    bridge,
15 |     unsigned int   portIndex,
16 |     STP_ADMIN_P2P  adminPointToPointMAC
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Sets the adminPointToPointMAC variable for a given port.

23 |

24 | Parameters

25 |
26 |
bridge
27 |
Pointer to a STP_BRIDGE object, obtained from 28 | STP_CreateBridge.
29 |
portIndex
30 |
The index of the port.
31 |
adminPointToPointMAC
32 |
One of the STP_ADMIN_P2P values.
33 |
34 |

35 | Remarks

36 |

37 | See §11.3 in 802.1AC-2016 for more information.

38 |

39 | Execution of this function is a potentially lengthy process. 40 | It may call various callbacks multiple times.

41 |

42 | This function may not be called from within an STP callback.

43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /_help/STP_SetPortAutoEdge.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetPortAutoEdge 7 | 8 | 9 |

STP_SetPortAutoEdge

10 |
11 |
12 | void STP_SetPortAutoEdge
13 | (
14 |     STP_BRIDGE*   bridge,
15 |     unsigned int  portIndex,
16 |     bool          autoEdge
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Sets the AutoEdge parameter for a given port.

23 |

24 | Parameters

25 |
26 |
bridge
27 |
Pointer to a STP_BRIDGE object, obtained from 28 | STP_CreateBridge.
29 |
portIndex
30 |
The index of the port for which the AutoEdge parameter is to be set.
31 |
newAutoEdge
32 |
The new value of the AutoEdge parameter.
33 |
34 |

35 | Remarks

36 |

37 | For more information, see §13.27.18 in 802.1Q-2018.

38 |

39 | The STP Library initializes this variable to TRUE, as recommended in the standard.

40 | 41 |

42 | Execution of this function is a potentially lengthy process. 43 | It may call various callbacks multiple times.

44 |

45 | This function may not be called from within an STP callback.

46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /_help/STP_SetPortPriority.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetPortPriority 7 | 8 | 9 |

STP_SetPortPriority

10 |
11 |
12 | void STP_SetPortPriority
13 | (
14 |     STP_BRIDGE*    bridge,
15 |     unsigned int   portIndex,
16 |     unsigned int   treeIndex,
17 |     unsigned char  portPriority,
18 |     unsigned int   timestamp
19 | );
20 | 
21 |

22 | Summary

23 |

24 | Sets the priority component - most significant 4 bits - of the portId.

25 |

26 | Parameters

27 |
28 |
bridge
29 |
Pointer to a STP_BRIDGE object, obtained from 30 | STP_CreateBridge.
31 |
portIndex
32 |
The zero-based index of the port.
33 |
treeIndex
34 |
The zero-based index of the spanning tree for which the port priority is to be set. For 35 | STP or RSTP, this must be zero. For MSTP, this must be zero for the CIST, or 1..64 for an 36 | MSTI.
37 |
portPriority
38 |
A value between 0 and 240, in steps of 16.
39 |
timestamp
40 |
A timestamp used for the debug log.
41 |
42 |

43 | Remarks

44 |

45 | See §13.27.46 in 46 | 802.1Q-2018 for more details.

47 |

48 | Execution of this function is a potentially lengthy process. 49 | It may call various callbacks multiple times.

50 |

51 | This function may not be called from within an STP callback.

52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /_help/STP_SetStpVersion.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_SetStpVersion 7 | 8 | 9 |

STP_SetStpVersion

10 |
11 |
12 | void STP_SetStpVersion
13 | (
14 |     STP_BRIDGE*       bridge,
15 |     enum STP_VERSION  version
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Sets the STP version of the bridge, referred to as ForceProtocolVersion in the STP 22 | standard.

23 |

24 | Parameters

25 |
26 |
bridge
27 |
Pointer to an STP_BRIDGE object.
28 |
protocolVersion
29 |
One of the STP_VERSION values.
30 |
31 |

32 | Remarks

33 |

34 | See §13.7.2 in 801.1Q-2018 for more information.

35 |

36 | Execution of this function is a potentially lengthy process. 37 | It may call various callbacks multiple times.

38 |

39 | This function may not be called from within an STP callback.

40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /_help/STP_StartBridge.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_StartBridge 7 | 8 | 9 |

STP_StartBridge

10 |
11 |
12 | void STP_StartBridge
13 | (
14 |     STP_BRIDGE*   bridge,
15 |     unsigned int  timestamp
16 | );
17 | 
18 |

19 | Summary

20 |

Starts the Spanning Tree Protocol on a bridge. 21 |

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to a STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
timestamp
29 |
A timestamp used for the debug log.
30 |
31 |

32 | Remarks

33 |

34 | Starting the Spanning Tree Protocol from application code is usually a 35 | three-step procedure:

36 |
    37 |
  • a call to STP_CreateBridge, which allocates 38 | internal structures and initializes all parameters to default values;
  • 39 |
  • various calls to functions such as STP_SetBridgePriority 40 | and STP_SetStpVersion, possibly with values 41 | read from a configuration file; the protocol is not yet started, so there won't 42 | be any STP activity with temporary parameters.
  • 43 |
  • a call to this function, which starts the protocol directly with 44 | application-specified parameters.
  • 45 |
46 |

47 | The 48 | application must not call this function for already-started bridges.

49 | 50 |

51 | Execution of this function is a potentially lengthy process. 52 | It may call various callbacks multiple times.

53 |

54 | This function may not be called from within an STP callback.

55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /_help/STP_StopBridge.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | STP_StopBridge 7 | 8 | 9 |

STP_StopBridge

10 |
11 |
12 | void STP_StopBridge
13 | (
14 |     STP_BRIDGE*   bridge,
15 |     unsigned int  timestamp
16 | );
17 | 
18 |

19 | Summary

20 |

21 | Stops the Spanning Tree Protocol.

22 |

23 | Parameters

24 |
25 |
bridge
26 |
Pointer to an STP_BRIDGE object, obtained from 27 | STP_CreateBridge.
28 |
timestamp
29 |
A timestamp used for the debug log.
30 |
31 |

32 | Remarks

33 |

34 | This function calls StpCallback_EnableBpduTrapping 35 | to restore the switch to its default, non-STP-capable, state.

36 |

37 | This function re-enables learning and forwarding. It does so by calling 38 | StpCallback_EnableLearning and 39 | StpCallback_EnableForwarding 40 | for every tree of every port that had either of them disabled.

41 |

42 | This function may not be called from within an STP callback.

43 | 44 | 45 | -------------------------------------------------------------------------------- /_help/Screen.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | font-family: 'Calibri', 'Times New Roman' 4 | } 5 | 6 | dd 7 | { 8 | margin-bottom: 7px; 9 | } 10 | 11 | li 12 | { 13 | margin-bottom: 7px; 14 | } 15 | pre 16 | { 17 | background-color: #CCCCCC; 18 | } 19 | 20 | dt 21 | { 22 | font-family: monospace; 23 | } 24 | 25 | .function_information_table_left_cell 26 | { 27 | padding-right: 30px; 28 | background-color: #C0C0C0; 29 | vertical-align: top; 30 | } 31 | -------------------------------------------------------------------------------- /_help/StpCallback_AllocAndZeroMemory.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_AllocAndZeroMemory 7 | 8 | 9 |

StpCallback_AllocAndZeroMemory

10 |
11 |
12 | void* StpCallback_AllocAndZeroMemory (unsigned int size);
13 | 
14 |

15 | Summary

16 |

17 | Application-defined function that allocates and zeroes-out memory for STP use. 18 | (The library does not call standard memory-allocation functions, because most embedded 19 | applications don't have a heap to allocate from.)

20 |

21 | StpCallback_AllocAndZeroMemory is a placeholder name used throughout this documentation. The 22 | application may name this callback differently.

23 |

24 | Parameters

25 |
26 |
size
27 |
The application receives in this parameter the size of the required memory block.
28 |
29 |

30 | Return value

31 |
32 |
The application must return a pointer to the allocated and zeroed-out memory block.
33 |
34 |

35 | Remarks

36 |

37 | The STP library does not currenly support out-of-memory conditions. It 38 | verifies with an assert() that the pointer returned by this callback is not NULL.

39 |

40 | See the remarks section in 41 | STP_CreateBridge, for information about how and when the STP library allocates memory.

42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /_help/StpCallback_DebugStrOut.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_DebugStrOut 7 | 8 | 9 |

StpCallback_DebugStrOut

10 |
11 |
12 | void StpCallback_DebugStrOut
13 | (
14 |     const STP_BRIDGE* bridge,
15 |     int               portIndex,
16 |     int               treeIndex,
17 |     const char*       nullTerminatedString,
18 |     unsigned int      stringLength,
19 |     bool              flush
20 | );
21 | 
22 |

Summary

23 |

24 | Application-defined callback that processes debug text generated by the STP library. It 25 | usually sends this text to a PC for displaying in a program such as Hyperterminal. 26 |

27 |

28 | StpCallback_DebugStrOut is a placeholder name used throughout this documentation. The 29 | application may name this callback differently.

30 |

Parameters

31 |
32 |
bridge
33 |
The application receives in this parameter a pointer to the bridge object returned by 34 | STP_CreateBridge.
35 |
portIndex
36 |
The application receives in this parameter either: 37 |
    38 |
  • the zero-based index of a port, if the debug text is relevant only to that port, or
  • 39 |
  • -1 if the debug text is relevant to all ports (e.g., contains information about the 40 | bridge).
  • 41 |
42 |
43 |
treeIndex
44 |
The application receives in this parameter either: 45 |
    46 |
  • the zero-based index of a spanning tree, if the debug text is relevant only to 47 | that spanning tree, or
  • 48 |
  • -1 if the debug text is relevant to all spanning trees.
  • 49 |
50 |
51 |
nullTerminatedString
52 |
The application receives in this parameter a pointer to the null-terminated debug text.
53 |
stringLength
54 |
The length of the text (the value that strlen() would return).
55 |
flush
56 |
The application receives in this parameter a value which can be used as a hint for 57 | flushing any debug text that the application might have buffered.
58 |
59 |

Remarks

60 |

61 | The length of the debug text passed to this function, including the null terminator, is 62 | lower than or equal to the debugLogBufferSize parameter specified in the call to 63 | STP_CreateBridge.

64 |

65 | Logging is enabled or disabled by calling 66 | STP_EnableLogging. When a bridge is created, logging for that bridge is disabled.

67 |

68 | Line ending used by the STP library is "\r\n".

69 |

70 | The application may choose to buffer the text it receives in this callback. If it does so, 71 | it should flush its buffer when the library passes true in the flush parameter.

72 |

73 | The library sometimes calls this callback only for flushing, without any text (so 74 | nullTerminatedString pointing to a null character, 75 | stringLength = 0, and flush = true).

76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /_help/StpCallback_EnableForwarding.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_EnableForwarding 7 | 8 | 9 |

StpCallback_EnableForwarding

10 |
11 |
12 | void StpCallback_EnableForwarding
13 | (
14 |     const STP_BRIDGE* bridge,
15 |     unsigned int      portIndex,
16 |     unsigned int      treeIndex,
17 |     bool              enable,
18 |     unsigned int      timestamp
19 | );
20 | 
21 |

22 | Summary

23 |

24 | Application-defined function that must enable or disable forwarding on a physical port.

25 |

26 | StpCallback_EnableForwarding is a placeholder name used throughout this documentation. The 27 | application may name this callback differently.

28 |

29 | Parameters

30 |
31 |
bridge
32 |
The application receives in this parameter a pointer to the bridge object returned by 33 | STP_CreateBridge.
34 |
portIndex
35 |
The application receives in this parameter the zero-based index of the port for which 36 | forwarding is to be enabled or disabled.
37 |
treeIndex
38 |
The application receives in this parameter the zero-based index of the spanning tree for 39 | which forwarding is to be enabled or disabled. For STP or RSTP, this is always zero. For 40 | MSTP, this is zero for CIST, or 1..64 for a MSTI.
41 |
enable
42 |
The application receives in this parameter true if forwarding is to be enabled, 43 | false if the forwarding is to be disabled.
44 |
timestamp
45 |
The application receives in this parameter the timestamp that it passed to the function 46 | that called this callback (STP_OnBpduReceived, STP_OnPortEnabled etc.) 47 | Useful for debugging and troubleshooting.
48 |
49 |

50 | Remarks

51 |

In complex networks, and especially in MSTP mode, the STP library can call 52 | this function dozens of times in a row, with various combinations of parameters. 53 | This is due to the protocol itself (i.e., it is not a characteristic of this 54 | particular library). For that reason, the implementation of this function 55 | should not take more than a few milliseconds. Usually all this function needs 56 | to do is write a few bytes to the internal registers of the switch IC.

57 |

This function must wait until the hardware has finished enabling or disabling forwarding 58 | (i.e., it must not just initiate the hardware action and return).

59 | 60 | 61 | -------------------------------------------------------------------------------- /_help/StpCallback_EnableLearning.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_EnableLearning 7 | 8 | 9 |

StpCallback_EnableLearning

10 |
11 |
12 | void StpCallback_EnableLearning
13 | (
14 |     const STP_BRIDGE* bridge,
15 |     unsigned int      portIndex,
16 |     unsigned int      treeIndex,
17 |     bool              enable,
18 |     unsigned int      timestamp
19 | );
20 | 
21 |

Summary

22 |

23 | See StpCallback_EnableForwarding. All 24 | information from that callback applies to this callback as well, except that learning 25 | is enabled/disabled, not 26 | forwarding. 27 |

28 |

29 | StpCallback_EnableLearning is a placeholder name used throughout this documentation. The 30 | application may name this callback differently.

31 | 32 | 33 | -------------------------------------------------------------------------------- /_help/StpCallback_FlushFdb.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_FlushFdb 7 | 8 | 9 |

StpCallback_FlushFdb

10 |
11 |
12 | void StpCallback_FlushFdb
13 | (
14 |     const STP_BRIDGE*        bridge,
15 |     unsigned int             portIndex,
16 |     unsigned int             treeIndex,
17 |     enum STP_FLUSH_FDB_TYPE  flushType,
18 |     unsigned int             timestamp
19 | );
20 | 
21 |

22 | Summary

23 |

Application-defined function that flushes FDB entries (MAC-to-port associations) 24 | on a physical port. 25 |

26 |

27 | StpCallback_FlushFdb is a placeholder name used throughout this documentation. The 28 | application may name this callback differently.

29 |

30 | Parameters

31 |
32 |
bridge
33 |
The application receives in this parameter a pointer to the bridge object returned by 34 | STP_CreateBridge.
35 |
portIndex
36 |
The application receives in this parameter the index of the port on which FDB entries are to be flushed.
37 |
treeIndex
38 |
The application receives in this parameter the index of the spanning tree for which FDB 39 | entries are to be flushed. For STP or RSTP, this is always zero. For MSTP, this is zero 40 | for CIST, or 1..64 for a MSTI.
41 |
flushType
42 |
The application receives in this parameter a value representing the type of flushing it 43 | must perform. See the Remarks section for more information.
44 |
timestamp
45 |
The application receives in this parameter the timestamp that it passed to the function 46 | that called this callback (STP_OnBpduReceived, STP_OnPortEnabled etc.) 47 | Useful for debugging and troubleshooting.
48 |
49 |

Remarks

50 |

In complex networks, and especially in MSTP mode, the STP library can call 51 | this function dozens of times in a row, with various combinations of parameters. 52 | This is due to the protocol itself (i.e., it is not a characteristic of this 53 | particular library). For that reason, the implementation of this function 54 | should not take more than a few milliseconds. Usually all this function needs 55 | to do is write a few bytes to the internal registers of the switch IC.

56 |

If flushType is STP_FLUSH_FDB_TYPE_IMMEDIATE, the application must flush the FDB entries 57 | and return after the flush is completed in hardware. This value is received for RSTP and 58 | MSTP bridges (i.e., when STP_VERSION_RSTP or STP_VERSION_MSTP was passed to 59 | STP_CreateBridge or STP_SetStpVersion).

60 |

If flushType is STP_FLUSH_FDB_TYPE_RAPID_AGEING, the application must initiate FDB 61 | flushing and return without waiting for flushing to be completed in hardware. This 62 | behavior is used in legacy STP (pre-RSTP) bridges (i.e., when STP_VERSION_LEGACY_STP 63 | was passed to STP_CreateBridge or 64 | STP_SetStpVersion).

65 | 66 | 67 | -------------------------------------------------------------------------------- /_help/StpCallback_FreeMemory.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_FreeMemory 7 | 8 | 9 |

StpCallback_FreeMemory

10 |
11 |
12 | void StpCallback_FreeMemory (void* p);
13 | 
14 |

15 | Summary

16 |

17 | Application-defined function that frees memory previously allocated with 18 | StpCallback_AllocAndZeroMemory.

19 |

20 | StpCallback_FreeMemory is a placeholder name used throughout this documentation. The 21 | application may name this callback differently.

22 |

23 | Parameters

24 |
25 |
p
26 |
The application receives in this parameter a pointer to the memory block to be freed.
27 |
28 |

29 | Remarks

30 |

31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /_help/StpCallback_OnPortRoleChanged.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_OnPortRoleChanged 7 | 8 | 9 |

StpCallback_OnPortRoleChanged

10 |
11 |
12 | void StpCallback_OnPortRoleChanged
13 | (
14 |     const struct STP_BRIDGE* bridge,
15 |     unsigned int             portIndex,
16 |     unsigned int             treeIndex,
17 |     enum STP_PORT_ROLE       role,
18 |     unsigned int             timestamp
19 | );
20 | 
21 |

22 | Summary

23 |

24 | Application-defined function that is called by the STP library 25 | immediately after it changes a port role.

26 |

27 | Parameters

28 |
29 |
bridge
30 |
The application receives in this parameter a pointer to the STP_BRIDGE object.
31 |
portIndex
32 |
The application receives in this parameter the index of the port whose role has changed.
33 |
treeIndex
34 |
The application receives in this parameter the index of the spanning tree on which the port role changed (always 0 for LegacySTP and RSTP).
35 |
role
36 |
The new port role.
37 |
timestamp
38 |
The application receives in this parameter the timestamp that it passed to the function 39 | that called this callback (STP_OnBpduReceived, STP_OnPortEnabled etc.) 40 | Useful for debugging and troubleshooting.
41 |
42 |

43 | Remarks

44 |

45 | The application should implement this callback if it needs to update some user interface as ports change role. An Ethernet switch, for example, has a web interface where the user can inspect the state of each port; the code in this callback would refresh the displayed information to make sure the user sees up-to-date information about the port.

46 | 47 |

48 | StpCallback_OnTopologyChanged is a placeholder name used throughout this documentation. The 49 | application may name this callback differently.

50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /_help/StpCallback_OnTopologyChange.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_OnTopologyChange 7 | 8 | 9 |

StpCallback_OnTopologyChange

10 |
11 |
12 | void StpCallback_OnTopologyChange
13 | (
14 |     const struct STP_BRIDGE* bridge,
15 |     unsigned int treeIndex,
16 |     unsigned int timestamp
17 | );
18 | 
19 |

20 | Summary

21 |

22 | Application-defined function that is called by the STP library when it detects a change in the network topology on the local bridge.

23 |

24 | This callback allows the application to implement the following:

25 |
    26 |
  • from 802.1Q-2018: 12.8.1.2.3, c) and d) and 12.8.1.1.3, b) and c);
  • 27 |
  • from IEEE8021-SPANNING-TREE-MIB: ieee8021SpanningTreeTimeSinceTopologyChange and ieee8021SpanningTreeTopChanges.
  • 28 |
29 |

30 | Parameters

31 |
32 |
bridge
33 |
The application receives in this parameter a pointer to an STP_BRIDGE object.
34 |
treeIndex
35 |
The application receives in this parameter the zero-based index of the spanning tree on which the topology change ocurred. For STP or RSTP, this is always zero. For 36 | MSTP, this is zero for CIST, or 1..64 for a MSTI.
37 |
timestamp
38 |
The application receives in this parameter the timestamp that it passed to the function 39 | that called this callback (STP_OnBpduReceived, STP_OnPortEnabled etc.) 40 | Useful for debugging and troubleshooting.
41 |
42 |

43 | Remarks

44 |

45 | The library calls this callback only as long as the bridge is running at least RSTP (see STP_CreateBridge, STP_SetStpVersion). The detection of topology changes in LegacySTP mode (as per 8.5.3.12 in 802.1D-1998) is not yet implemented.

46 |

47 | The STP library calls this callback when it detects a topology change 48 | on the local bridge (i.e., a non-edge port transitioning to/from the forwarding state while the bridge is not isolated).

49 | 50 |

51 | StpCallback_OnTopologyChange is a placeholder name used throughout this documentation. The 52 | application may name this callback differently.

53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /_help/StpCallback_TransmitReleaseBuffer.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | StpCallback_TransmitReleaseBuffer 7 | 8 | 9 |

StpCallback_TransmitReleaseBuffer

10 |
11 |
12 | void StpCallback_TransmitReleaseBuffer
13 | (
14 |     const STP_BRIDGE* bridge,
15 |     void* bufferReturnedByGetBuffer
16 | );
17 | 
18 |

Summary

19 |

20 | Used together with StpCallback_TransmitGetBuffer to transmit a BPDU generated by the STP library. 21 |

22 |

Parameters

23 |
24 |
bridge
25 |
The application receives in this parameter a pointer to the bridge object returned by 26 | STP_CreateBridge.
27 |
bufferReturnedByGetBuffer
28 |
The application receives in this parameter the same value it returned from StpCallback_TransmitGetBuffer. The callback implementation may or may not need this value.
29 |
30 |

Remarks

31 |

32 | This callback is called by the STP library only if StpCallback_TransmitGetBuffer returned a 33 | non-NULL address. 34 |

35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /_help/Troubleshooting.txt: -------------------------------------------------------------------------------- 1 | - Make sure your switch (the hardware) isn't forwarding incoming BPDUs between ports. It must only forward BPDUs to the microcontroller running the STP. 2 | 3 | 4 | - Make sure your switch (the hardware) isn't broadcasting to all ports the BPDUs generated by the STP library. 5 | 6 | 7 | - Make sure your application is getting the incoming BPDUs. From your last mail I understand that the STP library works correctly while it is sending BPDUs (while it is the root), but isn't working right while the Cisco is sending BPDUs (while Cisco is the root). There's a possiblity your application isn't getting the incoming BPDUs. 8 | 9 | 10 | - Make sure you're correctly stripping the headers of the received BPDU frames (the VLAN tag should be striped too, if any). 11 | 12 | 13 | - Make sure you're not flooding the Ethernet communication driver of your device with incoming frames, from the office network for instance. This leads to BPDU loss, and then to STP malfunction. This was especially a problem for me in the early development stages of my Ethernet driver for LPC2000. 14 | 15 | 16 | - If you use IP-based communication to check connectivity to your device, make sure you flush the ARP table and send "gratuituous" ARPs whenever connectivity changes (forwarding and/or learning enabled/disabled on any port by STP). I am improving this in the new version of the library. 17 | 18 | 19 | - I don't know what Cisco switches you have there, but play a bit with the STP-related options. I once had some Cisco switches that sometimes wouldn't work with my devices, without any logic that I could see. The problem was some RSTP-related setting ("portfast" i.i.r.c.) which was conflicting with the RSTP functionality. 20 | 21 | 22 | - I don't know what compiler you're using, but make sure everything is byte-aligned in base_types.h and bpdu.h. The way I wrote that code, everything ends up byte-aligned on IAR and on VC++, but I'm not sure about other compilers. -------------------------------------------------------------------------------- /mstp-lib/internal/stp_base_types.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #include "stp_base_types.h" 6 | #include "stp_log.h" 7 | 8 | bool STP_BRIDGE_ADDRESS::operator== (const STP_BRIDGE_ADDRESS& rhs) const 9 | { 10 | return memcmp (this->bytes, rhs.bytes, 6) == 0; 11 | } 12 | 13 | bool STP_BRIDGE_ADDRESS::operator != (const STP_BRIDGE_ADDRESS& rhs) const 14 | { 15 | return memcmp (this->bytes, rhs.bytes, 6) != 0; 16 | } 17 | 18 | // ============================================================================ 19 | 20 | const char* GetPortRoleName (STP_PORT_ROLE role) 21 | { 22 | if (role == STP_PORT_ROLE_MASTER) 23 | return "Master"; 24 | else if (role == STP_PORT_ROLE_ROOT) 25 | return "Root"; 26 | else if (role == STP_PORT_ROLE_DESIGNATED) 27 | return "Designated"; 28 | else if (role == STP_PORT_ROLE_ALTERNATE) 29 | return "Alternate"; 30 | else if (role == STP_PORT_ROLE_BACKUP) 31 | return "Backup"; 32 | else if (role == STP_PORT_ROLE_DISABLED) 33 | return "Disabled"; 34 | else 35 | { 36 | assert (false); 37 | return NULL; 38 | } 39 | } 40 | 41 | // ============================================================================ 42 | 43 | void PORT_ID::Set (unsigned char priority, unsigned short portNumber) 44 | { 45 | assert ((priority & 0x0F) == 0); 46 | assert ((portNumber >= 1) && (portNumber <= 0xFFF)); 47 | 48 | _high = priority | (unsigned char) (portNumber >> 8); 49 | _low = (unsigned char) portNumber; 50 | } 51 | 52 | void PORT_ID::Reset () 53 | { 54 | _high = 0; 55 | _low = 0; 56 | } 57 | 58 | unsigned char PORT_ID::GetPriority () const 59 | { 60 | assert (_low != 0); // structure was not initialized; it must have been initialized with Set() 61 | return _high & 0xF0; 62 | } 63 | 64 | void PORT_ID::SetPriority (unsigned char priority) 65 | { 66 | assert (_low != 0); // structure was not initialized; it must have been initialized with Set() 67 | assert ((priority & 0x0F) == 0); 68 | 69 | _high = priority | (_high & 0x0F); 70 | } 71 | 72 | unsigned short PORT_ID::GetPortNumber () const 73 | { 74 | assert (_low != 0); // structure was not initialized; it must have been initialized with Set() 75 | 76 | return ((unsigned short) _high & 0x0F) | _low; 77 | } 78 | 79 | unsigned short PORT_ID::GetPortIdentifier () const 80 | { 81 | assert (_low != 0); // structure was not initialized; it must have been initialized with Set() 82 | 83 | unsigned short id = (((unsigned short) _high) << 8) | (unsigned short) _low; 84 | return id; 85 | } 86 | 87 | bool PORT_ID::IsBetterThan (const PORT_ID& rhs) const 88 | { 89 | assert (_low != 0); // structure was not initialized; it must have been initialized with Set() 90 | 91 | unsigned short lv = (((unsigned short) this->_high) << 8) | (unsigned short) this->_low; 92 | unsigned short rv = (((unsigned short) rhs._high) << 8) | (unsigned short) rhs._low; 93 | 94 | bool better = (lv < rv); 95 | return better; 96 | } 97 | 98 | bool TIMES::operator== (const TIMES& other) const 99 | { 100 | return (this->ForwardDelay == other.ForwardDelay) 101 | && (this->HelloTime == other.HelloTime) 102 | && (this->MaxAge == other.MaxAge) 103 | && (this->MessageAge == other.MessageAge) 104 | && (this->remainingHops == other.remainingHops); 105 | } 106 | 107 | bool TIMES::operator!= (const TIMES& other) const 108 | { 109 | return !this->operator==(other); 110 | } 111 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_conditions_and_params.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #ifndef MSTP_LIB_CONDS_AND_PARAMS_H 6 | #define MSTP_LIB_CONDS_AND_PARAMS_H 7 | 8 | #include "stp_base_types.h" 9 | 10 | // 13.28 State machine conditions and parameters 11 | bool allSptAgree (const STP_BRIDGE*); 12 | bool allSynced (const STP_BRIDGE*, PortIndex, TreeIndex); 13 | bool allTransmitReady (const STP_BRIDGE*, PortIndex); 14 | const PRIORITY_VECTOR& BestAgreementPriority(); 15 | bool cist (const STP_BRIDGE*, TreeIndex); 16 | bool cistRootPort (const STP_BRIDGE*, PortIndex); 17 | bool cistDesignatedPort (const STP_BRIDGE*, PortIndex); 18 | unsigned short EdgeDelay (const STP_BRIDGE*, PortIndex); 19 | unsigned short forwardDelay (const STP_BRIDGE*, PortIndex); 20 | unsigned short FwdDelay (const STP_BRIDGE*, PortIndex); 21 | unsigned short HelloTime (const STP_BRIDGE*, PortIndex); 22 | unsigned short MaxAge (const STP_BRIDGE*, PortIndex); 23 | bool msti (const STP_BRIDGE*, TreeIndex); 24 | bool mstiDesignatedOrTCpropagatingRootPort (const STP_BRIDGE*, PortIndex); 25 | bool mstiMasterPort (const STP_BRIDGE*, PortIndex); 26 | bool operPointToPoint (const STP_BRIDGE*, PortIndex); 27 | bool rcvdAnyMsg (const STP_BRIDGE*, PortIndex); 28 | bool rcvdCistMsg (const STP_BRIDGE*, PortIndex); 29 | bool rcvdMstiMsg (const STP_BRIDGE*, PortIndex, TreeIndex); 30 | bool reRooted (const STP_BRIDGE*, PortIndex, TreeIndex); 31 | bool rstpVersion (const STP_BRIDGE*); 32 | bool spt (const STP_BRIDGE*); 33 | bool stpVersion (const STP_BRIDGE*); 34 | bool updtCistInfo (const STP_BRIDGE*, PortIndex); 35 | bool updtMstiInfo (const STP_BRIDGE*, PortIndex, TreeIndex); 36 | bool rcvdXstMsg (const STP_BRIDGE*, PortIndex, TreeIndex); 37 | bool updtXstInfo (const STP_BRIDGE*, PortIndex, TreeIndex); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_log.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #ifndef MSTP_LIB_LOG_H 6 | #define MSTP_LIB_LOG_H 7 | 8 | #include "../stp.h" 9 | 10 | #if STP_USE_LOG 11 | struct STP_BRIDGE; 12 | 13 | void STP_Log (STP_BRIDGE* bridge, int port, int tree, const char* format, ...); 14 | void STP_FlushLog (STP_BRIDGE* bridge); 15 | void STP_Indent (STP_BRIDGE* bridge); 16 | void STP_Unindent (STP_BRIDGE* bridge); 17 | 18 | #define LOG(b,p,t,...) ((void) ( !(b)->loggingEnabled || (STP_Log(b,p,t,__VA_ARGS__), 0))) 19 | #define FLUSH_LOG(b) ((void) ( !(b)->loggingEnabled || (STP_FlushLog(b), 0))) 20 | #define LOG_INDENT(b) ((void) ( !(b)->loggingEnabled || (STP_Indent(b), 0))) 21 | #define LOG_UNINDENT(b) ((void) ( !(b)->loggingEnabled || (STP_Unindent(b), 0))) 22 | #else 23 | #define LOG(b,p,t,...) ((void)0) 24 | #define FLUSH_LOG(b) ((void)0) 25 | #define LOG_INDENT(b) ((void)0) 26 | #define LOG_UNINDENT(b) ((void)0) 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_md5.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #ifndef MSTP_LIB_HMAC_MD5_H 6 | #define MSTP_LIB_HMAC_MD5_H 7 | 8 | // Data structure for MD5 (Message Digest) computation 9 | struct MD5_CTX 10 | { 11 | unsigned int i [2]; // number of _bits_ handled mod 2^64 12 | unsigned int buf [4]; // scratch buffer 13 | unsigned char in [64]; // input buffer 14 | }; 15 | 16 | struct HMAC_MD5_CONTEXT : MD5_CTX 17 | { 18 | unsigned char digest[16]; // actual digest after HMAC_MD5_End call 19 | }; 20 | 21 | void HMAC_MD5_Init (HMAC_MD5_CONTEXT* context); 22 | void HMAC_MD5_Update (HMAC_MD5_CONTEXT* context, const void* text, unsigned int text_len); 23 | void HMAC_MD5_End (HMAC_MD5_CONTEXT* context); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_procedures.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #ifndef MSTP_LIB_PROCEDURES_H 6 | #define MSTP_LIB_PROCEDURES_H 7 | 8 | #include "stp_base_types.h" 9 | 10 | bool betterorsameInfo (STP_BRIDGE*, PortIndex, TreeIndex, INFO_IS newInfoIs); 11 | void clearAllRcvdMsgs (STP_BRIDGE*, PortIndex); 12 | void clearReselectTree (STP_BRIDGE*, TreeIndex); 13 | void disableForwarding (STP_BRIDGE*, PortIndex, TreeIndex, unsigned int timestamp); 14 | void disableLearning (STP_BRIDGE*, PortIndex, TreeIndex, unsigned int timestamp); 15 | void enableForwarding (STP_BRIDGE*, PortIndex, TreeIndex, unsigned int timestamp); 16 | void enableLearning (STP_BRIDGE*, PortIndex, TreeIndex, unsigned int timestamp); 17 | bool fromSameRegion (STP_BRIDGE*, PortIndex); 18 | void newTcDetected (STP_BRIDGE*, PortIndex, TreeIndex); 19 | void newTcWhile (STP_BRIDGE*, PortIndex, TreeIndex, unsigned int timestamp); 20 | void pseudoRcvMsgs (STP_BRIDGE*, PortIndex); 21 | RCVD_INFO rcvInfo (STP_BRIDGE*, PortIndex, TreeIndex); 22 | void rcvMsgs (STP_BRIDGE*, PortIndex); 23 | void rcvAgreements (STP_BRIDGE*, PortIndex); 24 | void recordAgreement (STP_BRIDGE*, PortIndex, TreeIndex); 25 | void recordDispute (STP_BRIDGE*, PortIndex, TreeIndex); 26 | void recordMastered (STP_BRIDGE*, PortIndex, TreeIndex); 27 | void recordPriority (STP_BRIDGE*, PortIndex, TreeIndex); 28 | void recordProposal (STP_BRIDGE*, PortIndex, TreeIndex); 29 | void recordTimes (STP_BRIDGE*, PortIndex, TreeIndex); 30 | void setReRootTree (STP_BRIDGE*, TreeIndex); 31 | void setSelectedTree (STP_BRIDGE*, TreeIndex); 32 | void setSyncTree (STP_BRIDGE*, TreeIndex); 33 | void setTcFlags (STP_BRIDGE*, PortIndex, TreeIndex); 34 | void setTcPropTree (STP_BRIDGE*, PortIndex, TreeIndex); 35 | void syncMaster (STP_BRIDGE*); 36 | void txConfig (STP_BRIDGE*, PortIndex, unsigned int timestamp); 37 | void txRstp (STP_BRIDGE*, PortIndex, unsigned int timestamp); 38 | void txTcn (STP_BRIDGE*, PortIndex, unsigned int timestamp); 39 | void updtAgreement (STP_BRIDGE*, PortIndex, TreeIndex); 40 | void updtBPDUVersion (STP_BRIDGE*, PortIndex); 41 | void updtDigest (STP_BRIDGE*, PortIndex); 42 | void updtRcvdInfoWhile (STP_BRIDGE*, PortIndex, TreeIndex); 43 | void updtRolesTree (STP_BRIDGE*, TreeIndex); 44 | void updtRolesDisabledTree (STP_BRIDGE*, TreeIndex); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_sm_l2g_port_receive.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | // This file implements 13.40 from 802.1Q-2018. 6 | 7 | #include "stp_procedures.h" 8 | #include "stp_conditions_and_params.h" 9 | #include "stp_bridge.h" 10 | #include 11 | 12 | using namespace L2GPortReceive; 13 | 14 | #if STP_USE_LOG 15 | static const char* GetStateName (State state) 16 | { 17 | switch (state) 18 | { 19 | case INIT: return "INIT"; 20 | case PSEUDO_RECEIVE: return "PSEUDO_RECEIVE"; 21 | case DISCARD: return "DISCARD"; 22 | case L2GP: return "L2GP"; 23 | default: return "(undefined)"; 24 | } 25 | } 26 | #endif 27 | 28 | // ============================================================================ 29 | 30 | // Returns the new state, or 0 when no transition is to be made. 31 | static State CheckConditions (const STP_BRIDGE* bridge, PortIndex givenPort, State state) 32 | { 33 | PORT* port = bridge->ports [givenPort]; 34 | 35 | // ------------------------------------------------------------------------ 36 | // Check global conditions. 37 | 38 | if (bridge->BEGIN || !port->isL2gp || !port->portEnabled) 39 | { 40 | if (state == INIT) 41 | { 42 | // The entry block for this state has been executed already. 43 | return (State)0; 44 | } 45 | 46 | return INIT; 47 | } 48 | 49 | // ------------------------------------------------------------------------ 50 | // Check exit conditions from each state. 51 | 52 | if (state == INIT) 53 | return L2GP; 54 | 55 | if (state == PSEUDO_RECEIVE) 56 | return L2GP; 57 | 58 | if (state == DISCARD) 59 | return L2GP; 60 | 61 | if (state == L2GP) 62 | { 63 | if (!port->enableBPDUrx && port->rcvdBpdu && !rcvdAnyMsg (bridge, givenPort)) 64 | return DISCARD; 65 | 66 | if ((port->pseudoInfoHelloWhen == 0) && !rcvdAnyMsg (bridge, givenPort)) 67 | return PSEUDO_RECEIVE; 68 | 69 | return (State)0; 70 | } 71 | 72 | assert (false); 73 | return (State)0; 74 | } 75 | 76 | static void InitState (STP_BRIDGE* bridge, PortIndex givenPort, State state, unsigned int timestamp) 77 | { 78 | PORT* port = bridge->ports[givenPort]; 79 | 80 | if (state == INIT) 81 | { 82 | port->pseudoInfoHelloWhen = 0; 83 | } 84 | else if (state == PSEUDO_RECEIVE) 85 | { 86 | port->rcvdInternal = true; 87 | pseudoRcvMsgs (bridge, givenPort); 88 | port->edgeDelayWhile = bridge->MigrateTime; 89 | port->pseudoInfoHelloWhen = HelloTime (bridge, givenPort); 90 | } 91 | else if (state == DISCARD) 92 | { 93 | port->rcvdBpdu = false; 94 | } 95 | else if (state == L2GP) 96 | { 97 | } 98 | else 99 | assert (false); 100 | } 101 | 102 | const StateMachine L2GPortReceive::sm = 103 | { 104 | #if STP_USE_LOG 105 | "L2GPortReceive", 106 | &GetStateName, 107 | #endif 108 | &CheckConditions, 109 | &InitState 110 | }; 111 | 112 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_sm_port_protocol_migration.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | // This file implements 13.32 from 802.1Q-2018 6 | 7 | #include "stp_procedures.h" 8 | #include "stp_conditions_and_params.h" 9 | #include "stp_bridge.h" 10 | #include 11 | 12 | using namespace PortProtocolMigration; 13 | 14 | #if STP_USE_LOG 15 | static const char* GetStateName (State state) 16 | { 17 | switch (state) 18 | { 19 | case CHECKING_RSTP: return "CHECKING_RSTP"; 20 | case SELECTING_STP: return "SELECTING_STP"; 21 | case SENSING: return "SENSING"; 22 | default: return "(undefined)"; 23 | } 24 | } 25 | #endif 26 | 27 | // ============================================================================ 28 | 29 | // Returns the new state, or 0 when no transition is to be made. 30 | static State CheckConditions (const STP_BRIDGE* bridge, PortIndex givenPort, State state) 31 | { 32 | PORT* port = bridge->ports[givenPort]; 33 | 34 | // ------------------------------------------------------------------------ 35 | // Check global conditions. 36 | 37 | if (bridge->BEGIN) 38 | { 39 | if (state == CHECKING_RSTP) 40 | { 41 | // The entry block for this state has been executed already. 42 | return (State)0; 43 | } 44 | 45 | return CHECKING_RSTP; 46 | } 47 | 48 | // ------------------------------------------------------------------------ 49 | // Check exit conditions from each state. 50 | 51 | if (state == CHECKING_RSTP) 52 | { 53 | if (port->mDelayWhile == 0) 54 | return SENSING; 55 | 56 | if ((port->mDelayWhile != bridge->MigrateTime) && !port->portEnabled) 57 | return CHECKING_RSTP; 58 | 59 | return (State)0; 60 | } 61 | 62 | if (state == SELECTING_STP) 63 | { 64 | if ((port->mDelayWhile == 0) || !port->portEnabled || port->mcheck) 65 | return SENSING; 66 | 67 | return (State)0; 68 | } 69 | 70 | if (state == SENSING) 71 | { 72 | if (port->sendRSTP && port->rcvdSTP) 73 | return SELECTING_STP; 74 | 75 | if (!port->portEnabled || port->mcheck || ((rstpVersion(bridge) && !port->sendRSTP && port->rcvdRSTP))) 76 | return CHECKING_RSTP; 77 | 78 | return (State)0; 79 | } 80 | 81 | assert (false); 82 | return (State)0; 83 | } 84 | 85 | // ============================================================================ 86 | 87 | static void InitState (STP_BRIDGE* bridge, PortIndex givenPort, State state, unsigned int timestamp) 88 | { 89 | PORT* port = bridge->ports[givenPort]; 90 | 91 | if (state == CHECKING_RSTP) 92 | { 93 | port->mcheck = false; 94 | port->sendRSTP = rstpVersion(bridge); 95 | port->mDelayWhile = bridge->MigrateTime; 96 | } 97 | else if (state == SELECTING_STP) 98 | { 99 | port->sendRSTP = false; 100 | port->mDelayWhile = bridge->MigrateTime; 101 | } 102 | else if (state == SENSING) 103 | { 104 | port->rcvdRSTP = port->rcvdSTP = false; 105 | } 106 | else 107 | assert (false); 108 | } 109 | 110 | const StateMachine PortProtocolMigration::sm = 111 | { 112 | #if STP_USE_LOG 113 | "PortProtocolMigration", 114 | &GetStateName, 115 | #endif 116 | &CheckConditions, 117 | &InitState 118 | }; 119 | 120 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_sm_port_receive.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | // This file implements 13.31 from 802.1Q-2018. 6 | 7 | #include "stp_procedures.h" 8 | #include "stp_conditions_and_params.h" 9 | #include "stp_bridge.h" 10 | #include 11 | 12 | using namespace PortReceive; 13 | 14 | #if STP_USE_LOG 15 | static const char* GetStateName (State state) 16 | { 17 | switch (state) 18 | { 19 | case DISCARD: return "DISCARD"; 20 | case RECEIVE: return "RECEIVE"; 21 | default: return "(undefined)"; 22 | } 23 | } 24 | #endif 25 | 26 | // ============================================================================ 27 | 28 | // Returns the new state, or 0 when no transition is to be made. 29 | static State CheckConditions (const STP_BRIDGE* bridge, PortIndex givenPort, State state) 30 | { 31 | PORT* port = bridge->ports[givenPort]; 32 | 33 | // ------------------------------------------------------------------------ 34 | // Check global conditions. 35 | 36 | if (bridge->BEGIN 37 | || ((port->rcvdBpdu || (port->edgeDelayWhile != bridge->MigrateTime)) && !port->portEnabled)) 38 | { 39 | if (state == DISCARD) 40 | { 41 | // The entry block for this state has been executed already. 42 | return (State)0; 43 | } 44 | 45 | return DISCARD; 46 | } 47 | 48 | // ------------------------------------------------------------------------ 49 | // Check exit conditions from each state. 50 | 51 | if (state == DISCARD) 52 | { 53 | if (port->rcvdBpdu && port->portEnabled && port->enableBPDUrx) 54 | return RECEIVE; 55 | 56 | return (State)0; 57 | } 58 | 59 | if (state == RECEIVE) 60 | { 61 | if (port->rcvdBpdu && port->portEnabled && port->enableBPDUrx && !rcvdAnyMsg (bridge, givenPort)) 62 | return RECEIVE; 63 | 64 | return (State)0; 65 | } 66 | 67 | assert (false); 68 | return (State)0; 69 | } 70 | 71 | // ============================================================================ 72 | 73 | static void InitState (STP_BRIDGE* bridge, PortIndex givenPort, State state, unsigned int timestamp) 74 | { 75 | PORT* port = bridge->ports[givenPort]; 76 | 77 | if (state == DISCARD) 78 | { 79 | port->rcvdBpdu = port->rcvdRSTP = port->rcvdSTP = false; 80 | port->agreedMisorder = true; port->agreedN = port->agreedND = port->agreeND = 0; port->agreeN = 1; 81 | clearAllRcvdMsgs (bridge, givenPort); 82 | port->edgeDelayWhile = bridge->MigrateTime; 83 | } 84 | else if (state == RECEIVE) 85 | { 86 | updtBPDUVersion (bridge, givenPort); 87 | port->rcvdInternal = fromSameRegion (bridge, givenPort); 88 | rcvMsgs (bridge, givenPort); 89 | port->operEdge = port->isolate = port->rcvdBpdu = false; 90 | port->edgeDelayWhile = bridge->MigrateTime; 91 | } 92 | else 93 | assert (false); 94 | } 95 | 96 | const StateMachine PortReceive::sm = 97 | { 98 | #if STP_USE_LOG 99 | "PortReceive", 100 | &GetStateName, 101 | #endif 102 | &CheckConditions, 103 | &InitState 104 | }; 105 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_sm_port_role_selection.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | // This file implements 13.36 from 802.1Q-2018. 6 | 7 | #include "stp_procedures.h" 8 | #include "stp_bridge.h" 9 | #include 10 | 11 | using namespace PortRoleSelection; 12 | 13 | #if STP_USE_LOG 14 | static const char* GetStateName (State state) 15 | { 16 | switch (state) 17 | { 18 | case INIT_TREE: return "INIT_TREE"; 19 | case ROLE_SELECTION:return "ROLE_SELECTION"; 20 | default: return "(undefined)"; 21 | } 22 | } 23 | #endif 24 | 25 | // ============================================================================ 26 | 27 | // Returns the new state, or 0 when no transition is to be made. 28 | static State CheckConditions (const STP_BRIDGE* bridge, TreeIndex givenTree, State state) 29 | { 30 | // ------------------------------------------------------------------------ 31 | // Check global conditions. 32 | 33 | if (bridge->BEGIN) 34 | { 35 | if (state == INIT_TREE) 36 | { 37 | // The entry block for this state has been executed already. 38 | return (State)0; 39 | } 40 | 41 | return INIT_TREE; 42 | } 43 | 44 | // ------------------------------------------------------------------------ 45 | // Check exit conditions from each state. 46 | 47 | if (state == INIT_TREE) 48 | return ROLE_SELECTION; 49 | 50 | if (state == ROLE_SELECTION) 51 | { 52 | for (unsigned int portIndex = 0; portIndex < bridge->portCount; portIndex++) 53 | { 54 | if (bridge->ports [portIndex]->trees [givenTree]->reselect) 55 | return ROLE_SELECTION; 56 | } 57 | 58 | return (State)0; 59 | } 60 | 61 | assert (false); 62 | return (State)0; 63 | } 64 | 65 | // ============================================================================ 66 | 67 | static void InitState (STP_BRIDGE* bridge, TreeIndex givenTree, State state, unsigned int timestamp) 68 | { 69 | if (state == INIT_TREE) 70 | { 71 | updtRolesDisabledTree (bridge, givenTree); 72 | } 73 | else if (state == ROLE_SELECTION) 74 | { 75 | clearReselectTree (bridge, givenTree); 76 | updtRolesTree (bridge, givenTree); 77 | setSelectedTree (bridge, givenTree); 78 | } 79 | else 80 | assert (false); 81 | } 82 | 83 | const StateMachine PortRoleSelection::sm = 84 | { 85 | #if STP_USE_LOG 86 | "PortRoleSelection", 87 | &GetStateName, 88 | #endif 89 | &CheckConditions, 90 | &InitState 91 | }; 92 | 93 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_sm_port_state_transition.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | // This file implements 13.38 from 802.1Q-2018. 6 | 7 | #include "stp_procedures.h" 8 | #include "stp_bridge.h" 9 | #include 10 | 11 | using namespace PortStateTransition; 12 | 13 | #if STP_USE_LOG 14 | static const char* GetStateName (State state) 15 | { 16 | switch (state) 17 | { 18 | case DISCARDING: return "DISCARDING"; 19 | case LEARNING: return "LEARNING"; 20 | case FORWARDING: return "FORWARDING"; 21 | default: return "(undefined)"; 22 | } 23 | } 24 | #endif 25 | 26 | // ============================================================================ 27 | 28 | // Returns the new state, or 0 when no transition is to be made. 29 | static State CheckConditions (const STP_BRIDGE* bridge, PortAndTree pt, State state) 30 | { 31 | PortIndex givenPort = pt.portIndex; 32 | TreeIndex givenTree = pt.treeIndex; 33 | 34 | PORT* port = bridge->ports [givenPort]; 35 | PORT_TREE* tree = port->trees [givenTree]; 36 | 37 | // ------------------------------------------------------------------------ 38 | // Check global conditions. 39 | 40 | if (bridge->BEGIN) 41 | { 42 | if (state == DISCARDING) 43 | { 44 | // The entry block for this state has been executed already. 45 | return (State)0; 46 | } 47 | 48 | return DISCARDING; 49 | } 50 | 51 | // ------------------------------------------------------------------------ 52 | // Check exit conditions from each state. 53 | 54 | if (state == DISCARDING) 55 | { 56 | if (tree->learn) 57 | return LEARNING; 58 | 59 | return (State)0; 60 | } 61 | 62 | if (state == LEARNING) 63 | { 64 | if (!tree->learn) 65 | return DISCARDING; 66 | 67 | if (tree->forward) 68 | return FORWARDING; 69 | 70 | return (State)0; 71 | } 72 | 73 | if (state == FORWARDING) 74 | { 75 | if (!tree->forward) 76 | return DISCARDING; 77 | 78 | return (State)0; 79 | } 80 | 81 | assert (false); 82 | return (State)0; 83 | } 84 | 85 | // ============================================================================ 86 | 87 | static void InitState (STP_BRIDGE* bridge, PortAndTree pt, State state, unsigned int timestamp) 88 | { 89 | PortIndex givenPort = pt.portIndex; 90 | TreeIndex givenTree = pt.treeIndex; 91 | 92 | PORT* port = bridge->ports[givenPort]; 93 | PORT_TREE* tree = port->trees [givenTree]; 94 | 95 | if (state == DISCARDING) 96 | { 97 | disableLearning (bridge, givenPort, givenTree, timestamp); 98 | tree->learning = false; 99 | disableForwarding (bridge, givenPort, givenTree, timestamp); 100 | tree->forwarding = false; 101 | } 102 | else if (state == LEARNING) 103 | { 104 | enableLearning (bridge, givenPort, givenTree, timestamp); 105 | tree->learning = true; 106 | } 107 | else if (state == FORWARDING) 108 | { 109 | enableForwarding (bridge, givenPort, givenTree, timestamp); 110 | tree->forwarding = true; 111 | } 112 | else 113 | assert (false); 114 | } 115 | 116 | const StateMachine PortStateTransition::sm = 117 | { 118 | #if STP_USE_LOG 119 | "PortStateTransition", 120 | &GetStateName, 121 | #endif 122 | &CheckConditions, 123 | &InitState 124 | }; 125 | -------------------------------------------------------------------------------- /mstp-lib/internal/stp_sm_port_timers.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | // This file implements 13.30 from 802.1Q-2018. 6 | 7 | #include "stp_procedures.h" 8 | #include "stp_bridge.h" 9 | #include 10 | 11 | using namespace PortTimers; 12 | 13 | #if STP_USE_LOG 14 | static const char* GetStateName (State state) 15 | { 16 | switch (state) 17 | { 18 | case ONE_SECOND: return "ONE_SECOND"; 19 | case TICK: return "TICK"; 20 | default: return "(undefined)"; 21 | } 22 | } 23 | #endif 24 | 25 | // ============================================================================ 26 | 27 | // Returns the new state, or 0 when no transition is to be made. 28 | static State CheckConditions (const STP_BRIDGE* bridge, PortIndex givenPort, State state) 29 | { 30 | PORT* port = bridge->ports[givenPort]; 31 | 32 | // ------------------------------------------------------------------------ 33 | // Check global conditions. 34 | 35 | if (bridge->BEGIN) 36 | { 37 | if (state == ONE_SECOND) 38 | { 39 | // The entry block for this state has been executed already. 40 | return (State)0; 41 | } 42 | 43 | return ONE_SECOND; 44 | } 45 | 46 | // ------------------------------------------------------------------------ 47 | // Check exit conditions from each state. 48 | 49 | if (state == ONE_SECOND) 50 | { 51 | if (port->tick) 52 | return TICK; 53 | 54 | return (State)0; 55 | } 56 | 57 | if (state == TICK) 58 | return ONE_SECOND; 59 | 60 | assert (false); 61 | return (State)0; 62 | } 63 | 64 | // ============================================================================ 65 | 66 | static void InitState (STP_BRIDGE* bridge, PortIndex givenPort, State state, unsigned int timestamp) 67 | { 68 | PORT* port = bridge->ports[givenPort]; 69 | 70 | if (state == ONE_SECOND) 71 | { 72 | port->tick = false; 73 | } 74 | else if (state == TICK) 75 | { 76 | if (port->helloWhen > 0) port->helloWhen--; 77 | if (port->mDelayWhile > 0) port->mDelayWhile--; 78 | if (port->edgeDelayWhile > 0) port->edgeDelayWhile--; 79 | if (port->txCount > 0) port->txCount--; 80 | if (port->pseudoInfoHelloWhen > 0) port->pseudoInfoHelloWhen--; 81 | 82 | for (unsigned int treeIndex = 0; treeIndex < bridge->treeCount(); treeIndex++) 83 | { 84 | PORT_TREE* portTree = port->trees [treeIndex]; 85 | 86 | if (portTree->tcWhile > 0) portTree->tcWhile--; 87 | if (portTree->fdWhile > 0) portTree->fdWhile--; 88 | if (portTree->rcvdInfoWhile > 0) portTree->rcvdInfoWhile--; 89 | if (portTree->rrWhile > 0) portTree->rrWhile--; 90 | if (portTree->tcDetected > 0) portTree->tcDetected--; 91 | if (portTree->rbWhile > 0) portTree->rbWhile--; 92 | } 93 | } 94 | } 95 | 96 | const StateMachine PortTimers::sm = 97 | { 98 | #if STP_USE_LOG 99 | "PortTimers", 100 | &GetStateName, 101 | #endif 102 | &CheckConditions, 103 | &InitState 104 | }; 105 | -------------------------------------------------------------------------------- /simulator/bridge_tree.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #pragma once 6 | #include "object.h" 7 | #include "win32/com_ptr.h" 8 | 9 | class bridge; 10 | 11 | using edge::object; 12 | using edge::uint32_p; 13 | using edge::temp_string_p; 14 | using edge::property_change_args; 15 | using edge::nvp; 16 | using edge::concrete_type; 17 | 18 | extern const nvp bridge_priority_nvps[]; 19 | extern const char bridge_priority_type_name[]; 20 | using bridge_priority_p = edge::enum_property; 21 | 22 | class bridge_tree : public object 23 | { 24 | using base = object; 25 | 26 | bridge* const _parent; 27 | size_t const _tree_index; 28 | 29 | SYSTEMTIME _last_topology_change; 30 | uint32_t _topology_change_count; 31 | 32 | friend class bridge; 33 | 34 | void on_topology_change (unsigned int timestamp); 35 | static void on_bridge_property_changing (void* arg, object* obj, const property_change_args& args); 36 | static void on_bridge_property_changed (void* arg, object* obj, const property_change_args& args); 37 | 38 | public: 39 | bridge_tree (bridge* parent, size_t tree_index); 40 | 41 | uint32_t bridge_priority() const; 42 | void set_bridge_priority (uint32_t priority); 43 | 44 | std::array root_priorty_vector() const; 45 | std::string root_bridge_id() const; 46 | uint32_t external_root_path_cost() const; 47 | std::string regional_root_id() const; 48 | uint32_t internal_root_path_cost() const; 49 | std::string designated_bridge_id() const; 50 | std::string designated_port_id() const; 51 | std::string receiving_port_id() const; 52 | 53 | uint32_t hello_time() const; 54 | uint32_t max_age() const; 55 | uint32_t bridge_forward_delay() const; 56 | uint32_t message_age() const; 57 | uint32_t remaining_hops() const; 58 | 59 | uint32_t topology_change_count() const { return _topology_change_count; } 60 | 61 | static const bridge_priority_p bridge_priority_property; 62 | static const temp_string_p root_id_property; 63 | static const uint32_p external_root_path_cost_property; 64 | static const temp_string_p regional_root_id_property; 65 | static const uint32_p internal_root_path_cost_property; 66 | static const temp_string_p designated_bridge_id_property; 67 | static const temp_string_p designated_port_id_property; 68 | static const temp_string_p receiving_port_id_property; 69 | static const uint32_p hello_time_property; 70 | static const uint32_p max_age_property; 71 | static const uint32_p forward_delay_property; 72 | static const uint32_p message_age_property; 73 | static const uint32_p remaining_hops_property; 74 | static const uint32_p topology_change_count_property; 75 | static const edge::property* const _properties[]; 76 | static const edge::xtype _type; 77 | const concrete_type* type() const override final { return &_type; } 78 | }; 79 | 80 | -------------------------------------------------------------------------------- /simulator/edit_states/edit_state.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #pragma once 6 | #include "..\simulator.h" 7 | #include "win32\window.h" 8 | 9 | struct edit_state_deps 10 | { 11 | project_window_i* pw; 12 | edit_window_i* ew; 13 | project_i* project; 14 | selection_i* selection; 15 | }; 16 | 17 | class edit_state abstract 18 | { 19 | protected: 20 | project_window_i* const _pw; 21 | edit_window_i* const _ew; 22 | project_i* const _project; 23 | selection_i* const _selection; 24 | 25 | public: 26 | edit_state (const edit_state_deps& deps) 27 | : _pw(deps.pw), _ew(deps.ew), _selection(deps.selection), _project(deps.project) 28 | { } 29 | 30 | virtual ~edit_state() { } 31 | virtual void process_mouse_button_down (edge::mouse_button button, UINT modifierKeysDown, const mouse_location& location) { } 32 | virtual void process_mouse_button_up (edge::mouse_button button, UINT modifierKeysDown, const mouse_location& location) { } 33 | virtual void process_mouse_move (const mouse_location& location) { } 34 | virtual std::optional process_key_or_syskey_down (UINT virtualKey, UINT modifierKeys) { return std::nullopt; } 35 | virtual std::optional process_key_or_syskey_up (UINT virtualKey, UINT modifierKeys) { return std::nullopt; } 36 | virtual void render (ID2D1DeviceContext* dc) { } 37 | virtual bool completed() const = 0; 38 | virtual HCURSOR cursor() const { return LoadCursor(nullptr, IDC_ARROW); } 39 | }; 40 | 41 | std::unique_ptr create_state_move_bridges (const edit_state_deps& deps); 42 | std::unique_ptr create_state_move_port (const edit_state_deps& deps); 43 | std::unique_ptr create_state_create_bridge (const edit_state_deps& deps); 44 | std::unique_ptr create_state_create_wire (const edit_state_deps& deps); 45 | std::unique_ptr CreateStateMoveWirePoint (const edit_state_deps& deps, wire* wire, size_t pointIndex); 46 | std::unique_ptr CreateStateBeginningDrag (const edit_state_deps& deps, 47 | renderable_object* clickedObject, 48 | edge::mouse_button button, 49 | UINT modifierKeysDown, 50 | const mouse_location& location, 51 | HCURSOR cursor, 52 | std::unique_ptr&& stateMoveThreshold, 53 | std::unique_ptr&& stateButtonUp); 54 | -------------------------------------------------------------------------------- /simulator/edit_states/move_bridges_es.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #include "pch.h" 6 | #include "edit_state.h" 7 | #include "bridge.h" 8 | #include "win32/utility_functions.h" 9 | 10 | class move_bridges_es : public edit_state 11 | { 12 | using base = edit_state; 13 | 14 | D2D1_POINT_2F _first_bridge_initial_location; 15 | D2D1_SIZE_F _offset_first_bridge; 16 | 17 | struct info 18 | { 19 | bridge* b; 20 | D2D1_SIZE_F offset_from_first; 21 | }; 22 | 23 | std::vector _infos; 24 | bool _completed = false; 25 | 26 | public: 27 | using base::base; 28 | 29 | virtual void process_mouse_button_down (edge::mouse_button button, UINT modifierKeysDown, const mouse_location& location) override final 30 | { 31 | auto firstBridge = static_cast(_selection->objects()[0]); assert (firstBridge != nullptr); 32 | _first_bridge_initial_location = firstBridge->location(); 33 | 34 | for (auto o : _selection->objects()) 35 | { 36 | auto b = dynamic_cast(o); assert (b != nullptr); 37 | _infos.push_back ({ b, b->location() - firstBridge->location() }); 38 | } 39 | 40 | _offset_first_bridge = location.w - firstBridge->location(); 41 | } 42 | 43 | virtual void process_mouse_move (const mouse_location& location) override final 44 | { 45 | auto firstBridgeLocation = location.w - _offset_first_bridge; 46 | _infos[0].b->set_location(firstBridgeLocation); 47 | for (size_t i = 1; i < _infos.size(); i++) 48 | _infos[i].b->set_location (firstBridgeLocation + _infos[i].offset_from_first); 49 | } 50 | 51 | virtual std::optional process_key_or_syskey_down (UINT virtualKey, UINT modifierKeys) override final 52 | { 53 | if (virtualKey == VK_ESCAPE) 54 | { 55 | _infos[0].b->set_location (_first_bridge_initial_location); 56 | for (size_t i = 1; i < _infos.size(); i++) 57 | _infos[i].b->set_location (_first_bridge_initial_location + _infos[i].offset_from_first); 58 | 59 | _completed = true; 60 | ::InvalidateRect (_ew->hwnd(), nullptr, FALSE); 61 | return 0; 62 | } 63 | 64 | return std::nullopt; 65 | } 66 | 67 | virtual void process_mouse_button_up (edge::mouse_button button, UINT modifierKeysDown, const mouse_location& location) override final 68 | { 69 | _project->SetChangedFlag(true); 70 | _completed = true; 71 | } 72 | 73 | virtual bool completed() const override final { return _completed; } 74 | }; 75 | 76 | std::unique_ptr create_state_move_bridges (const edit_state_deps& deps) { return std::make_unique(deps); } 77 | -------------------------------------------------------------------------------- /simulator/edit_states/move_port_es.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #include "pch.h" 6 | #include "edit_state.h" 7 | #include "bridge.h" 8 | #include "port.h" 9 | 10 | class move_port_es : public edit_state 11 | { 12 | typedef edit_state base; 13 | port* _port; 14 | side _initialSide; 15 | float _initialOffset; 16 | bool _completed = false; 17 | 18 | public: 19 | using base::base; 20 | 21 | virtual void process_mouse_button_down (edge::mouse_button button, UINT modifierKeysDown, const mouse_location& location) override final 22 | { 23 | assert (_selection->objects().size() == 1); 24 | _port = dynamic_cast(_selection->objects().front()); 25 | assert (_port != nullptr); 26 | _initialSide = _port->side(); 27 | _initialOffset = _port->offset(); 28 | } 29 | 30 | virtual void process_mouse_move (const mouse_location& location) override final 31 | { 32 | _port->bridge()->SetCoordsForInteriorPort (_port, location.w); 33 | } 34 | 35 | virtual std::optional process_key_or_syskey_down (UINT virtualKey, UINT modifierKeys) override final 36 | { 37 | if (virtualKey == VK_ESCAPE) 38 | { 39 | _port->SetSideAndOffset (_initialSide, _initialOffset); 40 | _completed = true; 41 | return 0; 42 | } 43 | 44 | return std::nullopt; 45 | } 46 | 47 | virtual void process_mouse_button_up (edge::mouse_button button, UINT modifierKeysDown, const mouse_location& location) override final 48 | { 49 | _project->SetChangedFlag(true); 50 | _completed = true; 51 | } 52 | 53 | virtual bool completed() const override final { return _completed; } 54 | }; 55 | 56 | std::unique_ptr create_state_move_port (const edit_state_deps& deps) { return std::make_unique(deps); } 57 | -------------------------------------------------------------------------------- /simulator/edit_states/move_wire_point_es.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #include "pch.h" 6 | #include "edit_state.h" 7 | #include "wire.h" 8 | #include "port.h" 9 | 10 | class MoveWirePointES : public edit_state 11 | { 12 | typedef edit_state base; 13 | 14 | wire* const _wire; 15 | size_t const _pointIndex; 16 | wire_end const _initialPoint; 17 | POINT _first_down_location; 18 | 19 | enum substate 20 | { 21 | waiting_first_down, 22 | waiting_first_up, 23 | waiting_second_down, 24 | waiting_second_up, 25 | down, 26 | }; 27 | 28 | substate _substate = waiting_first_down; 29 | 30 | public: 31 | MoveWirePointES (const edit_state_deps& deps, wire* wire, size_t pointIndex) 32 | : base(deps), _wire(wire), _pointIndex(pointIndex), _initialPoint(wire->points()[pointIndex]) 33 | { } 34 | 35 | virtual bool completed() const override final { return _substate == down; } 36 | 37 | virtual void process_mouse_button_down (edge::mouse_button button, UINT modifierKeysDown, const mouse_location& location) override final 38 | { 39 | base::process_mouse_button_down (button, modifierKeysDown, location); 40 | 41 | if (button != edge::mouse_button::left) 42 | return; 43 | 44 | if (_substate == waiting_first_down) 45 | { 46 | _first_down_location = location.pt; 47 | _substate = waiting_first_up; 48 | } 49 | } 50 | 51 | virtual void process_mouse_move (const mouse_location& location) override 52 | { 53 | base::process_mouse_move(location); 54 | 55 | auto port = _ew->GetCPAt (location.d, SnapDistance); 56 | if (port != nullptr) 57 | { 58 | auto alreadyConnectedWire = _project->GetWireConnectedToPort(port); 59 | if (alreadyConnectedWire.first == nullptr) 60 | _wire->set_point(_pointIndex, port); 61 | } 62 | else 63 | _wire->set_point(_pointIndex, location.w); 64 | 65 | if (_substate == waiting_first_up) 66 | { 67 | RECT rc = { _first_down_location.x, _first_down_location.y, _first_down_location.x, _first_down_location.y }; 68 | InflateRect (&rc, GetSystemMetrics(SM_CXDRAG), GetSystemMetrics(SM_CYDRAG)); 69 | if (!PtInRect(&rc, location.pt)) 70 | _substate = waiting_second_up; 71 | } 72 | } 73 | 74 | virtual void process_mouse_button_up (edge::mouse_button button, UINT modifierKeysDown, const mouse_location& location) override final 75 | { 76 | if (_substate == waiting_second_up) 77 | { 78 | _project->SetChangedFlag(true); 79 | _substate = down; 80 | } 81 | } 82 | 83 | virtual std::optional process_key_or_syskey_down (UINT virtualKey, UINT modifierKeys) override final 84 | { 85 | if (virtualKey == VK_ESCAPE) 86 | { 87 | _wire->set_point(_pointIndex, _initialPoint); 88 | _substate = down; 89 | return 0; 90 | } 91 | 92 | return std::nullopt; 93 | } 94 | 95 | virtual void render (ID2D1DeviceContext* rt) override final 96 | { 97 | auto& point = _wire->points()[_pointIndex]; 98 | if (std::holds_alternative(point)) 99 | _ew->RenderSnapRect (rt, std::get(point)->GetCPLocation()); 100 | } 101 | 102 | virtual HCURSOR cursor() const override final { return LoadCursor(nullptr, IDC_CROSS); } 103 | }; 104 | 105 | std::unique_ptr CreateStateMoveWirePoint (const edit_state_deps& deps, wire* wire, size_t pointIndex) 106 | { 107 | return std::unique_ptr(new MoveWirePointES(deps, wire, pointIndex)); 108 | } 109 | -------------------------------------------------------------------------------- /simulator/pch.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "pch.h" 3 | 4 | -------------------------------------------------------------------------------- /simulator/pch.h: -------------------------------------------------------------------------------- 1 |  2 | #pragma once 3 | 4 | #define NOMINMAX 5 | #define _USE_MATH_DEFINES 6 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 7 | #define _WIN7_PLATFORM_UPDATE // Needed by wincodec.h 8 | 9 | #include "targetver.h" 10 | 11 | // C/C++ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | // Windows 36 | #define _COM_NO_STANDARD_GUIDS_ 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #undef DrawText 51 | 52 | #include "assert.h" 53 | -------------------------------------------------------------------------------- /simulator/port_tree.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #pragma once 6 | #include "object.h" 7 | #include "win32/com_ptr.h" 8 | #include "stp.h" 9 | 10 | class bridge; 11 | class port; 12 | 13 | using edge::size_t_p; 14 | using edge::size_t_property_traits; 15 | using edge::uint32_p; 16 | using edge::bool_p; 17 | using edge::float_p; 18 | using edge::backed_string_p; 19 | using edge::temp_string_p; 20 | using edge::property; 21 | using edge::type; 22 | using edge::concrete_type; 23 | using edge::xtype; 24 | using edge::value_property; 25 | using edge::typed_object_collection_property; 26 | using edge::property_change_args; 27 | using edge::side; 28 | using edge::binary_reader; 29 | using edge::out_stream_i; 30 | using edge::nvp; 31 | 32 | extern const nvp port_priority_nvps[]; 33 | extern const char port_priority_type_name[]; 34 | using port_priority_p = edge::enum_property; 35 | 36 | extern const nvp port_role_nvps[]; 37 | extern const char port_role_type_name[]; 38 | using port_role_p = edge::enum_property; 39 | 40 | extern const char stp_disabled_text[]; 41 | 42 | class port_tree : public edge::object 43 | { 44 | using base = edge::object; 45 | 46 | friend port; 47 | 48 | port* const _port; 49 | size_t const _tree_index; 50 | ULONGLONG _flush_tick_count = 0; 51 | bool _flush_text_visible = false; 52 | 53 | static UINT_PTR _flush_timer; 54 | static std::unordered_set _trees; 55 | 56 | static void on_bridge_property_changing (void* arg, object* obj, const property_change_args& args); 57 | static void on_bridge_property_changed (void* arg, object* obj, const property_change_args& args); 58 | static void CALLBACK flush_timer_proc (HWND hwnd, UINT, UINT_PTR, DWORD); 59 | 60 | public: 61 | port_tree (port* port, size_t tree_index); 62 | ~port_tree(); 63 | 64 | uint32_t priority() const; 65 | void set_priority (uint32_t priority); 66 | 67 | uint32_t internal_port_path_cost() const; 68 | uint32_t admin_internal_port_path_cost() const; 69 | void set_admin_internal_port_path_cost (uint32_t value); 70 | 71 | bool learning() const; 72 | bool forwarding() const; 73 | STP_PORT_ROLE role() const; 74 | 75 | void flush_fdb (unsigned int timestamp); 76 | 77 | bool fdb_flush_text_visible() const { return _flush_text_visible; } 78 | 79 | size_t tree_index() const { return _tree_index; } 80 | 81 | static const size_t_p tree_index_property; 82 | static const port_priority_p priority_property; 83 | static const bool_p learning_property; 84 | static const bool_p forwarding_property; 85 | static const port_role_p role_property; 86 | static const uint32_p admin_internal_port_path_cost_property; 87 | static const uint32_p internal_port_path_cost_property; 88 | static const property* const _properties[]; 89 | static const xtype _type; 90 | const concrete_type* type() const override final { return &_type; } 91 | }; 92 | -------------------------------------------------------------------------------- /simulator/renderable_object.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #pragma once 6 | #include "collection.h" 7 | #include "win32/com_ptr.h" 8 | #include "win32/zoomable_window.h" 9 | 10 | struct drawing_resources 11 | { 12 | edge::com_ptr _dWriteFactory; 13 | edge::com_ptr _poweredFillBrush; 14 | edge::com_ptr _unpoweredBrush; 15 | edge::com_ptr _brushWindowText; 16 | edge::com_ptr _brushWindow; 17 | edge::com_ptr _brushHighlight; 18 | edge::com_ptr _brushDiscardingPort; 19 | edge::com_ptr _brushLearningPort; 20 | edge::com_ptr _brushForwarding; 21 | edge::com_ptr _brushNoForwardingWire; 22 | edge::com_ptr _brushLoop; 23 | edge::com_ptr _brushTempWire; 24 | edge::com_ptr _strokeStyleForwardingWire; 25 | edge::com_ptr _strokeStyleNoForwardingWire; 26 | edge::com_ptr _regularTextFormat; 27 | edge::com_ptr _smallTextFormat; 28 | edge::com_ptr _smallBoldTextFormat; 29 | edge::com_ptr _strokeStyleSelectionRect; 30 | }; 31 | 32 | class renderable_object : public edge::owned_object 33 | { 34 | public: 35 | struct ht_result 36 | { 37 | renderable_object* object; 38 | int code; 39 | bool operator==(const ht_result& other) const { return (this->object == other.object) && (this->code == other.code); } 40 | bool operator!=(const ht_result& other) const { return (this->object != other.object) || (this->code != other.code); } 41 | }; 42 | 43 | struct invalidate_e : public edge::event { }; 44 | invalidate_e::subscriber invalidated() { return invalidate_e::subscriber(this); } 45 | 46 | virtual void render_selection (const edge::zoomable_i* zoomable, ID2D1RenderTarget* rt, const drawing_resources& dos) const = 0; 47 | virtual ht_result hit_test (const edge::zoomable_i* zoomable, D2D1_POINT_2F dLocation, float tolerance) = 0; 48 | virtual D2D1_RECT_F extent() const = 0; 49 | 50 | protected: 51 | template 52 | void set_and_invalidate (const tpd_* pd, typename tpd_::value_t& field, typename tpd_::value_t value) 53 | { 54 | this->on_property_changing(pd); 55 | field = value; 56 | this->on_property_changed(pd); 57 | this->event_invoker()(this); 58 | } 59 | }; 60 | 61 | struct project_i; 62 | 63 | class project_child : public renderable_object 64 | { 65 | friend class project; 66 | 67 | project_i* _project = nullptr; 68 | 69 | protected: 70 | virtual void on_added_to_project(project_i* project) 71 | { 72 | assert (_project == nullptr); 73 | _project = project; 74 | } 75 | 76 | virtual void on_removing_from_project(project_i* project) 77 | { 78 | assert (_project == project); 79 | _project = nullptr; 80 | } 81 | 82 | public: 83 | project_i* project() const { return _project; } 84 | }; 85 | -------------------------------------------------------------------------------- /simulator/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by simulator.rc 4 | // 5 | #define IDI_DESIGNER 107 6 | #define IDD_DIALOG_VLAN 108 7 | #define IDR_CONTEXT_MENU_EMPTY_SPACE 130 8 | #define IDR_CONTEXT_MENU_BRIDGE 131 9 | #define IDR_CONTEXT_MENU_PORT 132 10 | #define IDR_MAIN_MENU 133 11 | #define IDD_DIALOG_MST_CONFIG_ID 134 12 | #define IDR_ACCELERATOR1 135 13 | #define IDR_CONTEXT_MENU_LOG_WINDOW 136 14 | #define IDC_BUTTON_EDIT_MST_CONFIG_TABLE 1005 15 | #define IDC_COMBO_SELECTED_VLAN 1009 16 | #define IDC_EDIT_SELECTED_TREE 1010 17 | #define IDC_COMBO_NEW_WINDOW_VLAN 1011 18 | #define IDC_STATIC_CONFIG_TABLE 1012 19 | #define IDC_LIST_CONFIG_TABLE 1013 20 | #define IDC_BUTTON_USE_DEFAULT_CONFIG_TABLE 1014 21 | #define IDC_BUTTON_USE_TEST1_CONFIG_TABLE 1017 22 | #define IDC_STATIC_HINT_NOT_MSTP 1021 23 | #define IDC_STATIC_EXTENT 1025 24 | #define ID_NEW_BRIDGE 32772 25 | #define ID_PORT_AUTO_EDGE 32773 26 | #define ID_PORT_ADMIN_EDGE 32774 27 | #define ID_BRIDGE_ENABLE_STP 32775 28 | #define ID_BRIDGE_DISABLE_STP 32776 29 | #define ID_PASTE_BRIDGE 32777 30 | #define ID_FILE 32778 31 | #define ID_VIEW 32779 32 | #define ID_VIEW_PROPERTIES 32780 33 | #define ID_VIEW_STPLOG 32781 34 | #define ID_VIEW_VLANS 32782 35 | #define ID_FILE_NEW 32783 36 | #define ID_FILE_OPEN 32784 37 | #define ID_FILE_SAVEAS 32785 38 | #define ID_FILE_EXIT 32786 39 | #define ID_FILE_SAVE 32787 40 | #define ID_EDIT 32788 41 | #define ID_HELP 32791 42 | #define ID_HELP_ABOUT 32792 43 | #define ID_PAUSE_SIMULATION 32793 44 | #define ID_RESUME_SIMULATION 32794 45 | #define ID_FILE_RECENT 32795 46 | #define ID_RECENT_FILE_FIRST 32796 47 | #define ID_RECENT_FILE_LAST 32815 48 | #define ID_CLEAR_ALL_LOGS 32816 49 | #define IDC_STATIC -1 50 | 51 | // Next default values for new objects 52 | // 53 | #ifdef APSTUDIO_INVOKED 54 | #ifndef APSTUDIO_READONLY_SYMBOLS 55 | #define _APS_NO_MFC 1 56 | #define _APS_NEXT_RESOURCE_VALUE 137 57 | #define _APS_NEXT_COMMAND_VALUE 32817 58 | #define _APS_NEXT_CONTROL_VALUE 1026 59 | #define _APS_NEXT_SYMED_VALUE 110 60 | #endif 61 | #endif 62 | -------------------------------------------------------------------------------- /simulator/simulator.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adigostin/mstp-lib/57089f9b7826a65fdd8d391a31d0598476c3488c/simulator/simulator.ico -------------------------------------------------------------------------------- /simulator/simulator.natvis: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0 6 | 1 7 | 2 8 | 3 9 | 4 10 | 5 11 | 6 12 | 7 13 | 8 14 | 9 15 | A 16 | B 17 | C 18 | D 19 | E 20 | F 21 | 22 | 23 | 24 | 0 25 | 1 26 | 2 27 | 3 28 | 4 29 | 5 30 | 6 31 | 7 32 | 8 33 | 9 34 | A 35 | B 36 | C 37 | D 38 | E 39 | F 40 | 41 | 42 | 43 | {*(natvis::hex_dummy_high*)(&vh)}{*(natvis::hex_dummy_low*)(&vh)}{*(natvis::hex_dummy_high*)(&vl)}{*(natvis::hex_dummy_low*)(&vl)} 44 | 45 | 46 | {*(uint16_nbo*)(&bytes[0])}{*(uint16_nbo*)(&bytes[2])}{*(uint16_nbo*)(&bytes[4])} 47 | 48 | 49 | {_priorityAndMstid}.{_address} 50 | 51 | 52 | {(vhh << 24) | (vhl << 16) | (vlh << 8) | vll} 53 | 54 | 55 | {*(uint16_nbo*)this} 56 | 57 | 58 | {RootId}-{ExternalRootPathCost}-{RegionalRootId}-{InternalRootPathCost}-{DesignatedBridgeId}-{DesignatedPortId} 59 | 60 | -------------------------------------------------------------------------------- /simulator/simulator.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {44c75b95-8381-4205-bb9c-ff949707452e} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | edit_states 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | edit_states 32 | 33 | 34 | edit_states 35 | 36 | 37 | 38 | edit_states 39 | 40 | 41 | edit_states 42 | 43 | 44 | 45 | 46 | edit_states 47 | 48 | 49 | edit_states 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /simulator/targetver.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | // Including SDKDDKVer.h defines the highest available Windows platform. 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | #include 8 | #define _WIN32_WINNT _WIN32_WINNT_WIN7 9 | #include 10 | -------------------------------------------------------------------------------- /simulator/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include "stp.h" 3 | -------------------------------------------------------------------------------- /simulator/tests/bridge_tests.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #include "pch.h" 6 | #include "bridge.h" 7 | #include "test_helpers.h" 8 | 9 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 10 | 11 | TEST_CLASS(bridge_tests) 12 | { 13 | TEST_METHOD(create_bridge_test1) 14 | { 15 | uint32_t port_count = 4; 16 | uint32_t msti_count = 0; 17 | mac_address address = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }; 18 | auto b = std::make_unique(port_count, msti_count, address); 19 | } 20 | 21 | TEST_METHOD(disable_stp_test1) 22 | { 23 | uint32_t port_count = 4; 24 | uint32_t msti_count = 0; 25 | mac_address address = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }; 26 | auto b = std::make_unique(port_count, msti_count, address); 27 | 28 | auto get_root_bridge_id = [&b] { return b->trees()[0]->root_bridge_id(); }; 29 | 30 | b->set_stp_enabled(true); 31 | get_root_bridge_id(); 32 | 33 | b->set_stp_enabled(false); 34 | Assert::ExpectException(get_root_bridge_id); 35 | 36 | b->set_stp_enabled(true); 37 | get_root_bridge_id(); 38 | } 39 | 40 | TEST_METHOD(undefined_role_test) 41 | { 42 | STP_PORT_ROLE role_from_callback = STP_PORT_ROLE_UNDEFINED; 43 | auto bridge = test_bridge(4, 0, 0, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }); 44 | bridge.port_role_changed = [&role_from_callback](size_t portIndex, size_t treeIndex, enum STP_PORT_ROLE role) 45 | { 46 | role_from_callback = role; 47 | }; 48 | 49 | Assert::AreEqual (STP_PORT_ROLE_UNDEFINED, role_from_callback); 50 | 51 | STP_StartBridge(bridge, 0); 52 | 53 | Assert::AreEqual (STP_PORT_ROLE_DISABLED, role_from_callback); 54 | } 55 | 56 | TEST_METHOD(receive_more_mstis_on_same_mst_config) 57 | { 58 | size_t port_count = 4; 59 | size_t msti_count = 5; 60 | test_bridge bridge0 (port_count, msti_count, 16, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }); 61 | STP_SetStpVersion (bridge0, STP_VERSION_MSTP, 0); 62 | STP_SetMstConfigName (bridge0, "ABC", 0); 63 | STP_StartBridge (bridge0, 0); 64 | STP_OnPortEnabled (bridge0, 0, 100, true, 0); 65 | 66 | msti_count = 4; 67 | test_bridge bridge1 (port_count, msti_count, 16, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x70 }); 68 | STP_SetStpVersion (bridge1, STP_VERSION_MSTP, 0); 69 | STP_SetMstConfigName (bridge1, "ABC", 0); 70 | STP_StartBridge (bridge1, 0); 71 | STP_OnPortEnabled (bridge1, 0, 100, true, 0); 72 | 73 | exchange_bpdus (bridge0, 0, bridge1, 0); // shouldn't crash 74 | } 75 | 76 | TEST_METHOD(test_designated_bridge_priority_on_msti) 77 | { 78 | test_bridge bridge (4, 4, 16, { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }); 79 | STP_SetStpVersion (bridge, STP_VERSION_MSTP, 0); 80 | STP_SetBridgePriority (bridge, 1, 0x6000, 0); 81 | STP_StartBridge (bridge, 0); 82 | 83 | // First 8 bytes are RootId and for MSTIs must always be zero (see definition of PRIORITY_VECTOR in stp_base_types.h) 84 | unsigned char rpv[36]; 85 | STP_GetRootPriorityVector(bridge, 1, rpv); 86 | uint64_t root_id; 87 | memcpy (&root_id, rpv, 8); 88 | Assert::AreEqual (0ull, root_id); 89 | } 90 | }; 91 | -------------------------------------------------------------------------------- /simulator/tests/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /simulator/tests/pch.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #define NOMINMAX 5 | #define _USE_MATH_DEFINES 6 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 7 | #define _WIN7_PLATFORM_UPDATE // Needed by wincodec.h 8 | 9 | #include "targetver.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | -------------------------------------------------------------------------------- /simulator/tests/project_tests.cpp: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #include "pch.h" 6 | #include "bridge.h" 7 | #include "wire.h" 8 | #include "simulator.h" 9 | #include "test_helpers.h" 10 | 11 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 12 | 13 | extern const project_factory_t project_factory; 14 | 15 | TEST_CLASS(project_tests) 16 | { 17 | public: 18 | TEST_METHOD(TestMethod1) 19 | { 20 | uint32_t port_count = 4; 21 | uint32_t msti_count = 0; 22 | auto p = project_factory(); 23 | p->insert_bridge(0, std::make_unique(port_count, msti_count, mac_address{ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 })); 24 | p->insert_bridge(1, std::make_unique(port_count, msti_count, mac_address{ 0x10, 0x20, 0x30, 0x40, 0x50, 0x70 })); 25 | p->insert_bridge(2, std::make_unique(port_count, msti_count, mac_address{ 0x10, 0x20, 0x30, 0x40, 0x50, 0x80 })); 26 | 27 | auto w = std::make_unique(); 28 | w->set_p0(p->bridges()[1]->ports()[2].get()); 29 | w->set_p1(p->bridges()[2]->ports()[3].get()); 30 | p->insert_wire(0, std::move(w)); 31 | 32 | Assert::AreEqual (p->bridges()[1]->ports()[2].get(), std::get(p->wires()[0]->p0())); 33 | Assert::AreEqual (p->bridges()[2]->ports()[3].get(), std::get(p->wires()[0]->p1())); 34 | 35 | p->remove_bridge((size_t)0); 36 | 37 | Assert::AreEqual (p->bridges()[0]->ports()[2].get(), std::get(p->wires()[0]->p0())); 38 | Assert::AreEqual (p->bridges()[1]->ports()[3].get(), std::get(p->wires()[0]->p1())); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /simulator/tests/test_helpers.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #pragma once 6 | #include "CppUnitTest.h" 7 | #include "stp.h" 8 | #include "port.h" 9 | 10 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 11 | 12 | namespace Microsoft::VisualStudio::CppUnitTestFramework 13 | { 14 | template<> 15 | static inline std::wstring ToString(port* p) 16 | { 17 | return L"port"; 18 | } 19 | 20 | template<> 21 | static inline std::wstring ToString (const STP_PORT_ROLE& role) 22 | { 23 | std::string_view str = STP_GetPortRoleString(role); 24 | return std::wstring (str.begin(), str.end()); 25 | } 26 | } 27 | 28 | class test_bridge 29 | { 30 | STP_BRIDGE* stp_bridge; 31 | 32 | static void* StpCallback_AllocAndZeroMemory (unsigned int size); 33 | static void StpCallback_FreeMemory (void* p); 34 | static void* StpCallback_TransmitGetBuffer (const STP_BRIDGE* bridge, unsigned int portIndex, unsigned int bpduSize, unsigned int timestamp); 35 | static void StpCallback_TransmitReleaseBuffer (const STP_BRIDGE* bridge, void* bufferReturnedByGetBuffer); 36 | static void StpCallback_OnPortRoleChanged (const STP_BRIDGE* bridge, unsigned int portIndex, unsigned int treeIndex, STP_PORT_ROLE role, unsigned int timestamp); 37 | static const STP_CALLBACKS callbacks; 38 | 39 | std::vector tx_buffer; 40 | size_t tx_buffer_port_index; 41 | 42 | public: 43 | test_bridge (size_t port_count, size_t msti_count, uint16_t max_vlan_number, const std::array& bridge_address); 44 | test_bridge (const test_bridge&) = delete; 45 | test_bridge& operator= (const test_bridge&) = delete; 46 | ~test_bridge(); 47 | 48 | operator STP_BRIDGE* () const { return stp_bridge; } 49 | 50 | using tx_queue = std::queue>; 51 | std::unordered_map tx_queues; 52 | std::function port_role_changed; 53 | }; 54 | 55 | bool exchange_bpdus (test_bridge& one, size_t one_port, test_bridge& other, size_t other_port); 56 | -------------------------------------------------------------------------------- /simulator/tests/tests.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /simulator/wire.h: -------------------------------------------------------------------------------- 1 | 2 | // This file is part of the mstp-lib library, available at https://github.com/adigostin/mstp-lib 3 | // Copyright (c) 2011-2020 Adi Gostin, distributed under Apache License v2.0. 4 | 5 | #pragma once 6 | #include "renderable_object.h" 7 | #include "win32/utility_functions.h" 8 | #include "win32/xml_serializer.h" 9 | 10 | class port; 11 | struct project_i; 12 | 13 | using loose_wire_end = D2D1_POINT_2F; 14 | using connected_wire_end = port*; 15 | using serialized_connected_end = std::pair; 16 | using wire_end = std::variant; 17 | 18 | using edge::type; 19 | using edge::concrete_type; 20 | using edge::xtype; 21 | using edge::property; 22 | using edge::typed_property; 23 | using edge::uint32_p; 24 | using edge::ui_visible; 25 | using edge::object; 26 | using edge::out_stream_i; 27 | using edge::binary_reader; 28 | using edge::com_ptr; 29 | 30 | struct wire_end_property_traits 31 | { 32 | static constexpr char type_name[] = "wire_end"; 33 | using value_t = wire_end; 34 | static void to_string (value_t from, std::string& to); 35 | static void from_string (std::string_view from, value_t& to); 36 | static void serialize (value_t from, out_stream_i* to) { assert(false); } 37 | static void deserialize (binary_reader& from, value_t& to) { assert(false); } 38 | }; 39 | using wire_end_p = typed_property; 40 | 41 | class wire : public project_child, public edge::deserialize_i 42 | { 43 | using base = project_child; 44 | 45 | std::array _points; 46 | 47 | public: 48 | wire() = default; 49 | wire (wire_end firstEnd, wire_end secondEnd); 50 | 51 | // deserialize_i 52 | virtual void on_deserializing() override; 53 | virtual void on_deserialized() override; 54 | 55 | const std::array& points() const { return _points; } 56 | wire_end point (size_t i) const { return _points[i]; } 57 | void set_point (size_t i, wire_end point); 58 | 59 | wire_end p0() const { return _points[0]; } 60 | void set_p0 (wire_end p0) { set_point(0, p0); } 61 | void set_p0 (port* p0) { set_point(0, p0); } 62 | wire_end p1() const { return _points[1]; } 63 | void set_p1 (wire_end p1) { set_point(1, p1); } 64 | void set_p1 (port* p1) { set_point(1, p1); } 65 | 66 | D2D1_POINT_2F point_coords (size_t pointIndex) const; 67 | 68 | void render (ID2D1RenderTarget* rt, const drawing_resources& dos, bool forwarding, bool hasLoop) const; 69 | 70 | virtual void render_selection (const edge::zoomable_i* zoomable, ID2D1RenderTarget* rt, const drawing_resources& dos) const override final; 71 | virtual ht_result hit_test (const edge::zoomable_i* zoomable, D2D1_POINT_2F dLocation, float tolerance) override final; 72 | virtual D2D1_RECT_F extent() const override; 73 | 74 | static const wire_end_p p0_property; 75 | static const wire_end_p p1_property; 76 | static const property* const _properties[]; 77 | static const xtype _type; 78 | virtual const concrete_type* type() const override { return &_type; } 79 | }; 80 | --------------------------------------------------------------------------------