diff --git a/cfgmgr/stpmgr.cpp b/cfgmgr/stpmgr.cpp index f0cb631644..a3c7c311f3 100644 --- a/cfgmgr/stpmgr.cpp +++ b/cfgmgr/stpmgr.cpp @@ -91,6 +91,8 @@ void StpMgr::doStpGlobalTask(Consumer &consumer) STP_BRIDGE_CONFIG_MSG msg; memset(&msg, 0, sizeof(STP_BRIDGE_CONFIG_MSG)); + enum L2_PROTO_MODE old_l2ProtoEnabled = l2ProtoEnabled; + KeyOpFieldsValuesTuple t = it->second; string key = kfvKey(t); @@ -143,11 +145,75 @@ void StpMgr::doStpGlobalTask(Consumer &consumer) } memcpy(msg.base_mac_addr, macAddress.getMac(), 6); + + /* Send once when PVST/MSTP is enabled first time */ + if ((l2ProtoEnabled == L2_MSTP) && (old_l2ProtoEnabled == L2_NONE)) + { + SWSS_LOG_INFO("Populating VLANs for STP mode change: %d -> %d", old_l2ProtoEnabled, l2ProtoEnabled); + + // Get all existing VLANs from state table instead of iterating 1-4095 + vector vlanKeys; + m_stateVlanTable.getKeys(vlanKeys); + + SWSS_LOG_INFO("Found %zu configured VLANs to populate", vlanKeys.size()); + + for (const auto& vlanKey : vlanKeys) + { + STP_MST_VLAN_PORT_MAP *vlan_msg = NULL; + vector port_list; + uint16_t portCnt = 0; + int len; + + // Extract VLAN ID from key (e.g., "Vlan100" -> 100) + string vlanIdStr = vlanKey.substr(4); + int vlan_id = stoi(vlanIdStr); + + // Skip reserved VLANs (e.g., VLAN 4095) + if (vlan_id == 4095) + continue; + + // Get all port members for this VLAN + portCnt = (uint16_t)getAllVlanMem(vlanKey, port_list); + if (!portCnt) + continue; + + SWSS_LOG_DEBUG("VLAN %d has %d ports", vlan_id, portCnt); + len = (int)(sizeof(STP_MST_VLAN_PORT_MAP) + (portCnt * sizeof(PORT_LIST))); + + vlan_msg = (STP_MST_VLAN_PORT_MAP *)calloc(1, len); + if (!vlan_msg) + { + SWSS_LOG_ERROR("calloc failed for vlan %d", vlan_id); + // Continue processing other VLANs instead of returning + continue; + } + + // Populate port list + PORT_LIST *attr = vlan_msg->port_list; + for (size_t i = 0; i < port_list.size(); i++) + { + snprintf(attr[i].intf_name, IFNAMSIZ, "%s", port_list[i].intf_name); + attr[i].tagging_mode = port_list[i].mode; + SWSS_LOG_DEBUG(" Port[%zu]: %s Mode %d", i, port_list[i].intf_name, port_list[i].mode); + } + + // Fill in VLAN message + vlan_msg->port_count = portCnt; + vlan_msg->vlan_id = (uint16_t)vlan_id; + vlan_msg->stp_mode = l2ProtoEnabled; + vlan_msg->add = true; + + // Send message to STP daemon + sendMsgStpd(STP_MST_VLAN_PORT_LIST_CONFIG, len, (void *)vlan_msg, (L2_PROTO_MODE)vlan_msg->stp_mode); + + free(vlan_msg); + } + } } else if (op == DEL_COMMAND) { msg.opcode = STP_DEL_COMMAND; - + msg.stp_mode = l2ProtoEnabled; // Free Up all instances FREE_ALL_INST_ID(); @@ -165,10 +231,11 @@ void StpMgr::doStpGlobalTask(Consumer &consumer) SWSS_LOG_ERROR("ebtables del failed for PVST %d", ret_pvst); } l2ProtoEnabled = L2_NONE; + } // Send the message to the daemon - sendMsgStpd(STP_BRIDGE_CONFIG, sizeof(msg), (void *)&msg); + sendMsgStpd(STP_BRIDGE_CONFIG, sizeof(msg), (void *)&msg, (L2_PROTO_MODE)msg.stp_mode); // Move to the next item it = consumer.m_toSync.erase(it); @@ -329,7 +396,7 @@ void StpMgr::doStpVlanTask(Consumer &consumer) deallocL2Instance(vlan_id); } - sendMsgStpd(STP_VLAN_CONFIG, len, (void *)msg); + sendMsgStpd(STP_VLAN_CONFIG, len, (void *)msg, l2ProtoEnabled); if (msg) free(msg); @@ -399,7 +466,7 @@ void StpMgr::doStpMstGlobalTask(Consumer &consumer) msg.opcode = STP_DEL_COMMAND; } - sendMsgStpd(STP_MST_GLOBAL_CONFIG, sizeof(msg), (void *)&msg); + sendMsgStpd(STP_MST_GLOBAL_CONFIG, sizeof(msg), (void *)&msg, l2ProtoEnabled); it = consumer.m_toSync.erase(it); } @@ -438,7 +505,7 @@ void StpMgr::processStpVlanPortAttr(const string op, uint32_t vlan_id, const str msg.opcode = STP_DEL_COMMAND; } - sendMsgStpd(STP_VLAN_PORT_CONFIG, sizeof(msg), (void *)&msg); + sendMsgStpd(STP_VLAN_PORT_CONFIG, sizeof(msg), (void *)&msg, l2ProtoEnabled); } void StpMgr::doStpVlanPortTask(Consumer &consumer) @@ -621,7 +688,7 @@ void StpMgr::processStpPortAttr(const string op, } // Send the fully prepared message to the STP daemon. - sendMsgStpd(STP_PORT_CONFIG, len, reinterpret_cast(msg)); + sendMsgStpd(STP_PORT_CONFIG, len, reinterpret_cast(msg), l2ProtoEnabled); // Clean up. free(msg); @@ -750,7 +817,7 @@ void StpMgr::doVlanMemUpdateTask(Consumer &consumer) strncpy(msg.intf_name, intfName.c_str(), IFNAMSIZ-1); - sendMsgStpd(STP_VLAN_MEM_CONFIG, sizeof(msg), (void *)&msg); + sendMsgStpd(STP_VLAN_MEM_CONFIG, sizeof(msg), (void *)&msg, l2ProtoEnabled); } it = consumer.m_toSync.erase(it); @@ -1105,7 +1172,7 @@ void StpMgr::doStpMstInstTask(Consumer &consumer) updateVlanInstanceMap(instance_id, vlan_ids, false); } - sendMsgStpd(STP_MST_INST_CONFIG, len, (void *)msg); + sendMsgStpd(STP_MST_INST_CONFIG, len, (void *)msg, l2ProtoEnabled); if (msg) free(msg); @@ -1149,7 +1216,7 @@ void StpMgr::processStpMstInstPortAttr(const string op, uint16_t mst_id, const s } // Send the message to the daemon - sendMsgStpd(STP_MST_INST_PORT_CONFIG, sizeof(msg), (void *)&msg); + sendMsgStpd(STP_MST_INST_PORT_CONFIG, sizeof(msg), (void *)&msg, l2ProtoEnabled); } @@ -1215,7 +1282,7 @@ void StpMgr::doStpMstInstPortTask(Consumer &consumer) } // Send Message to STPd -int StpMgr::sendMsgStpd(STP_MSG_TYPE msgType, uint32_t msgLen, void *data) +int StpMgr::sendMsgStpd(STP_MSG_TYPE msgType, uint32_t msgLen, void *data, L2_PROTO_MODE protocol) { STP_IPC_MSG *tx_msg; size_t len = 0; @@ -1228,12 +1295,13 @@ int StpMgr::sendMsgStpd(STP_MSG_TYPE msgType, uint32_t msgLen, void *data) tx_msg = (STP_IPC_MSG *)calloc(1, len); if (tx_msg == NULL) { - SWSS_LOG_ERROR("tx_msg mem alloc error\n"); + SWSS_LOG_ERROR("tx_msg mem alloc error\n"); return -1; } tx_msg->msg_type = msgType; tx_msg->msg_len = msgLen; + tx_msg->proto_mode = protocol; memcpy(tx_msg->data, data, msgLen); bzero(&addr, sizeof(addr)); @@ -1243,11 +1311,11 @@ int StpMgr::sendMsgStpd(STP_MSG_TYPE msgType, uint32_t msgLen, void *data) rc = (int)sendto(stpd_fd, (void*)tx_msg, len, 0, (struct sockaddr *)&addr, sizeof(addr)); if (rc == -1) { - SWSS_LOG_ERROR("tx_msg send error\n"); + SWSS_LOG_ERROR("tx_msg send error\n"); } else { - SWSS_LOG_INFO("tx_msg sent %d", rc); + SWSS_LOG_INFO("tx_msg sent %d, proto_mode %d", rc, protocol); } free(tx_msg); diff --git a/cfgmgr/stpmgr.h b/cfgmgr/stpmgr.h index 263bac46fc..89f362a04e 100644 --- a/cfgmgr/stpmgr.h +++ b/cfgmgr/stpmgr.h @@ -32,6 +32,8 @@ #define INVALID_MODE -1 #define MAX_VLANS 4096 +#define MIN_VLAN_ID 1 +#define MAX_VLAN_ID 4095 // Maximum number of instances supported #define L2_INSTANCE_MAX MAX_VLANS @@ -73,6 +75,7 @@ typedef enum STP_MSG_TYPE { STP_STPCTL_MSG, STP_MST_GLOBAL_CONFIG, STP_MST_INST_CONFIG, + STP_MST_VLAN_PORT_LIST_CONFIG, STP_MST_INST_PORT_CONFIG, STP_MAX_MSG } STP_MSG_TYPE; @@ -225,6 +228,19 @@ typedef struct STP_MST_INST_PORT_CONFIG_MSG { int priority; // Port priority } __attribute__((packed)) STP_MST_INST_PORT_CONFIG_MSG; +typedef struct PORT_LIST { + char intf_name[IFNAMSIZ]; + int8_t tagging_mode; +} PORT_LIST; + +typedef struct STP_MST_VLAN_PORT_MAP { + uint16_t vlan_id; + uint16_t port_count; + int8_t stp_mode; + uint8_t add; + PORT_LIST port_list[0]; +} __attribute__((aligned(4))) STP_MST_VLAN_PORT_MAP; + namespace swss { class StpMgr : public Orch @@ -235,7 +251,7 @@ class StpMgr : public Orch using Orch::doTask; void ipcInitStpd(); - int sendMsgStpd(STP_MSG_TYPE msgType, uint32_t msgLen, void *data); + int sendMsgStpd(STP_MSG_TYPE msgType, uint32_t msgLen, void *data, L2_PROTO_MODE protocol); MacAddress macAddress; bool isPortInitDone(DBConnector *app_db); uint16_t getStpMaxInstances(void); diff --git a/cfgmgr/stpmgrd.cpp b/cfgmgr/stpmgrd.cpp index 52b9f5a9dd..ab69c0cd09 100644 --- a/cfgmgr/stpmgrd.cpp +++ b/cfgmgr/stpmgrd.cpp @@ -73,7 +73,7 @@ int main(int argc, char **argv) STP_INIT_READY_MSG msg; memset(&msg, 0, sizeof(STP_INIT_READY_MSG)); msg.max_stp_instances = stpmgr.getStpMaxInstances(); - stpmgr.sendMsgStpd(STP_INIT_READY, sizeof(msg), (void *)&msg); + stpmgr.sendMsgStpd(STP_INIT_READY, sizeof(msg), (void *)&msg, L2_NONE); // Get Base MAC Table table(&conf_db, "DEVICE_METADATA");