162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include "lan966x_main.h" 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#define VLANACCESS_CMD_IDLE 0 662306a36Sopenharmony_ci#define VLANACCESS_CMD_READ 1 762306a36Sopenharmony_ci#define VLANACCESS_CMD_WRITE 2 862306a36Sopenharmony_ci#define VLANACCESS_CMD_INIT 3 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistatic int lan966x_vlan_get_status(struct lan966x *lan966x) 1162306a36Sopenharmony_ci{ 1262306a36Sopenharmony_ci return lan_rd(lan966x, ANA_VLANACCESS); 1362306a36Sopenharmony_ci} 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic int lan966x_vlan_wait_for_completion(struct lan966x *lan966x) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci u32 val; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci return readx_poll_timeout(lan966x_vlan_get_status, 2062306a36Sopenharmony_ci lan966x, val, 2162306a36Sopenharmony_ci (val & ANA_VLANACCESS_VLAN_TBL_CMD) == 2262306a36Sopenharmony_ci VLANACCESS_CMD_IDLE, 2362306a36Sopenharmony_ci TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US); 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic void lan966x_vlan_set_mask(struct lan966x *lan966x, u16 vid) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci u16 mask = lan966x->vlan_mask[vid]; 2962306a36Sopenharmony_ci bool cpu_dis; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci cpu_dis = !(mask & BIT(CPU_PORT)); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci /* Set flags and the VID to configure */ 3462306a36Sopenharmony_ci lan_rmw(ANA_VLANTIDX_VLAN_PGID_CPU_DIS_SET(cpu_dis) | 3562306a36Sopenharmony_ci ANA_VLANTIDX_V_INDEX_SET(vid), 3662306a36Sopenharmony_ci ANA_VLANTIDX_VLAN_PGID_CPU_DIS | 3762306a36Sopenharmony_ci ANA_VLANTIDX_V_INDEX, 3862306a36Sopenharmony_ci lan966x, ANA_VLANTIDX); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* Set the vlan port members mask */ 4162306a36Sopenharmony_ci lan_rmw(ANA_VLAN_PORT_MASK_VLAN_PORT_MASK_SET(mask), 4262306a36Sopenharmony_ci ANA_VLAN_PORT_MASK_VLAN_PORT_MASK, 4362306a36Sopenharmony_ci lan966x, ANA_VLAN_PORT_MASK); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* Issue a write command */ 4662306a36Sopenharmony_ci lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_WRITE), 4762306a36Sopenharmony_ci ANA_VLANACCESS_VLAN_TBL_CMD, 4862306a36Sopenharmony_ci lan966x, ANA_VLANACCESS); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (lan966x_vlan_wait_for_completion(lan966x)) 5162306a36Sopenharmony_ci dev_err(lan966x->dev, "Vlan set mask failed\n"); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic void lan966x_vlan_port_add_vlan_mask(struct lan966x_port *port, u16 vid) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci struct lan966x *lan966x = port->lan966x; 5762306a36Sopenharmony_ci u8 p = port->chip_port; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci lan966x->vlan_mask[vid] |= BIT(p); 6062306a36Sopenharmony_ci lan966x_vlan_set_mask(lan966x, vid); 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic void lan966x_vlan_port_del_vlan_mask(struct lan966x_port *port, u16 vid) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci struct lan966x *lan966x = port->lan966x; 6662306a36Sopenharmony_ci u8 p = port->chip_port; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci lan966x->vlan_mask[vid] &= ~BIT(p); 6962306a36Sopenharmony_ci lan966x_vlan_set_mask(lan966x, vid); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic bool lan966x_vlan_port_any_vlan_mask(struct lan966x *lan966x, u16 vid) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci return !!(lan966x->vlan_mask[vid] & ~BIT(CPU_PORT)); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic void lan966x_vlan_cpu_add_vlan_mask(struct lan966x *lan966x, u16 vid) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci lan966x->vlan_mask[vid] |= BIT(CPU_PORT); 8062306a36Sopenharmony_ci lan966x_vlan_set_mask(lan966x, vid); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic void lan966x_vlan_cpu_del_vlan_mask(struct lan966x *lan966x, u16 vid) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci lan966x->vlan_mask[vid] &= ~BIT(CPU_PORT); 8662306a36Sopenharmony_ci lan966x_vlan_set_mask(lan966x, vid); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic void lan966x_vlan_cpu_add_cpu_vlan_mask(struct lan966x *lan966x, u16 vid) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci __set_bit(vid, lan966x->cpu_vlan_mask); 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic void lan966x_vlan_cpu_del_cpu_vlan_mask(struct lan966x *lan966x, u16 vid) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci __clear_bit(vid, lan966x->cpu_vlan_mask); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cibool lan966x_vlan_cpu_member_cpu_vlan_mask(struct lan966x *lan966x, u16 vid) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return test_bit(vid, lan966x->cpu_vlan_mask); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic u16 lan966x_vlan_port_get_pvid(struct lan966x_port *port) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci struct lan966x *lan966x = port->lan966x; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (!(lan966x->bridge_mask & BIT(port->chip_port))) 10962306a36Sopenharmony_ci return HOST_PVID; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci return port->vlan_aware ? port->pvid : UNAWARE_PVID; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciint lan966x_vlan_port_set_vid(struct lan966x_port *port, u16 vid, 11562306a36Sopenharmony_ci bool pvid, bool untagged) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct lan966x *lan966x = port->lan966x; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* Egress vlan classification */ 12062306a36Sopenharmony_ci if (untagged && port->vid != vid) { 12162306a36Sopenharmony_ci if (port->vid) { 12262306a36Sopenharmony_ci dev_err(lan966x->dev, 12362306a36Sopenharmony_ci "Port already has a native VLAN: %d\n", 12462306a36Sopenharmony_ci port->vid); 12562306a36Sopenharmony_ci return -EBUSY; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci port->vid = vid; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* Default ingress vlan classification */ 13162306a36Sopenharmony_ci if (pvid) 13262306a36Sopenharmony_ci port->pvid = vid; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci return 0; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic void lan966x_vlan_port_remove_vid(struct lan966x_port *port, u16 vid) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci if (port->pvid == vid) 14062306a36Sopenharmony_ci port->pvid = 0; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (port->vid == vid) 14362306a36Sopenharmony_ci port->vid = 0; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_civoid lan966x_vlan_port_set_vlan_aware(struct lan966x_port *port, 14762306a36Sopenharmony_ci bool vlan_aware) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci port->vlan_aware = vlan_aware; 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_civoid lan966x_vlan_port_apply(struct lan966x_port *port) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci struct lan966x *lan966x = port->lan966x; 15562306a36Sopenharmony_ci u16 pvid; 15662306a36Sopenharmony_ci u32 val; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci pvid = lan966x_vlan_port_get_pvid(port); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* Ingress clasification (ANA_PORT_VLAN_CFG) */ 16162306a36Sopenharmony_ci /* Default vlan to classify for untagged frames (may be zero) */ 16262306a36Sopenharmony_ci val = ANA_VLAN_CFG_VLAN_VID_SET(pvid); 16362306a36Sopenharmony_ci if (port->vlan_aware) 16462306a36Sopenharmony_ci val |= ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) | 16562306a36Sopenharmony_ci ANA_VLAN_CFG_VLAN_POP_CNT_SET(1); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci lan_rmw(val, 16862306a36Sopenharmony_ci ANA_VLAN_CFG_VLAN_VID | ANA_VLAN_CFG_VLAN_AWARE_ENA | 16962306a36Sopenharmony_ci ANA_VLAN_CFG_VLAN_POP_CNT, 17062306a36Sopenharmony_ci lan966x, ANA_VLAN_CFG(port->chip_port)); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci lan_rmw(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(port->vlan_aware) | 17362306a36Sopenharmony_ci DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(port->vlan_aware), 17462306a36Sopenharmony_ci DEV_MAC_TAGS_CFG_VLAN_AWR_ENA | 17562306a36Sopenharmony_ci DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, 17662306a36Sopenharmony_ci lan966x, DEV_MAC_TAGS_CFG(port->chip_port)); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci /* Drop frames with multicast source address */ 17962306a36Sopenharmony_ci val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1); 18062306a36Sopenharmony_ci if (port->vlan_aware && !pvid) 18162306a36Sopenharmony_ci /* If port is vlan-aware and tagged, drop untagged and priority 18262306a36Sopenharmony_ci * tagged frames. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_ci val |= ANA_DROP_CFG_DROP_UNTAGGED_ENA_SET(1) | 18562306a36Sopenharmony_ci ANA_DROP_CFG_DROP_PRIO_S_TAGGED_ENA_SET(1) | 18662306a36Sopenharmony_ci ANA_DROP_CFG_DROP_PRIO_C_TAGGED_ENA_SET(1); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci lan_wr(val, lan966x, ANA_DROP_CFG(port->chip_port)); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q */ 19162306a36Sopenharmony_ci val = REW_TAG_CFG_TAG_TPID_CFG_SET(0); 19262306a36Sopenharmony_ci if (port->vlan_aware) { 19362306a36Sopenharmony_ci if (port->vid) 19462306a36Sopenharmony_ci /* Tag all frames except when VID == DEFAULT_VLAN */ 19562306a36Sopenharmony_ci val |= REW_TAG_CFG_TAG_CFG_SET(1); 19662306a36Sopenharmony_ci else 19762306a36Sopenharmony_ci val |= REW_TAG_CFG_TAG_CFG_SET(3); 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci /* Update only some bits in the register */ 20162306a36Sopenharmony_ci lan_rmw(val, 20262306a36Sopenharmony_ci REW_TAG_CFG_TAG_TPID_CFG | REW_TAG_CFG_TAG_CFG, 20362306a36Sopenharmony_ci lan966x, REW_TAG_CFG(port->chip_port)); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* Set default VLAN and tag type to 8021Q */ 20662306a36Sopenharmony_ci lan_rmw(REW_PORT_VLAN_CFG_PORT_TPID_SET(ETH_P_8021Q) | 20762306a36Sopenharmony_ci REW_PORT_VLAN_CFG_PORT_VID_SET(port->vid), 20862306a36Sopenharmony_ci REW_PORT_VLAN_CFG_PORT_TPID | 20962306a36Sopenharmony_ci REW_PORT_VLAN_CFG_PORT_VID, 21062306a36Sopenharmony_ci lan966x, REW_PORT_VLAN_CFG(port->chip_port)); 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_civoid lan966x_vlan_port_add_vlan(struct lan966x_port *port, 21462306a36Sopenharmony_ci u16 vid, 21562306a36Sopenharmony_ci bool pvid, 21662306a36Sopenharmony_ci bool untagged) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct lan966x *lan966x = port->lan966x; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* If the CPU(br) is already part of the vlan then add the fdb 22162306a36Sopenharmony_ci * entries in MAC table to copy the frames to the CPU(br). 22262306a36Sopenharmony_ci * If the CPU(br) is not part of the vlan then it would 22362306a36Sopenharmony_ci * just drop the frames. 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_ci if (lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x, vid)) { 22662306a36Sopenharmony_ci lan966x_vlan_cpu_add_vlan_mask(lan966x, vid); 22762306a36Sopenharmony_ci lan966x_fdb_write_entries(lan966x, vid); 22862306a36Sopenharmony_ci lan966x_mdb_write_entries(lan966x, vid); 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci lan966x_vlan_port_set_vid(port, vid, pvid, untagged); 23262306a36Sopenharmony_ci lan966x_vlan_port_add_vlan_mask(port, vid); 23362306a36Sopenharmony_ci lan966x_vlan_port_apply(port); 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_civoid lan966x_vlan_port_del_vlan(struct lan966x_port *port, u16 vid) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci struct lan966x *lan966x = port->lan966x; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci lan966x_vlan_port_remove_vid(port, vid); 24162306a36Sopenharmony_ci lan966x_vlan_port_del_vlan_mask(port, vid); 24262306a36Sopenharmony_ci lan966x_vlan_port_apply(port); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* In case there are no other ports in vlan then remove the CPU from 24562306a36Sopenharmony_ci * that vlan but still keep it in the mask because it may be needed 24662306a36Sopenharmony_ci * again then another port gets added in that vlan 24762306a36Sopenharmony_ci */ 24862306a36Sopenharmony_ci if (!lan966x_vlan_port_any_vlan_mask(lan966x, vid)) { 24962306a36Sopenharmony_ci lan966x_vlan_cpu_del_vlan_mask(lan966x, vid); 25062306a36Sopenharmony_ci lan966x_fdb_erase_entries(lan966x, vid); 25162306a36Sopenharmony_ci lan966x_mdb_erase_entries(lan966x, vid); 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_civoid lan966x_vlan_cpu_add_vlan(struct lan966x *lan966x, u16 vid) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci /* Add an entry in the MAC table for the CPU 25862306a36Sopenharmony_ci * Add the CPU part of the vlan only if there is another port in that 25962306a36Sopenharmony_ci * vlan otherwise all the broadcast frames in that vlan will go to CPU 26062306a36Sopenharmony_ci * even if none of the ports are in the vlan and then the CPU will just 26162306a36Sopenharmony_ci * need to discard these frames. It is required to store this 26262306a36Sopenharmony_ci * information so when a front port is added then it would add also the 26362306a36Sopenharmony_ci * CPU port. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ci if (lan966x_vlan_port_any_vlan_mask(lan966x, vid)) { 26662306a36Sopenharmony_ci lan966x_vlan_cpu_add_vlan_mask(lan966x, vid); 26762306a36Sopenharmony_ci lan966x_mdb_write_entries(lan966x, vid); 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, vid); 27162306a36Sopenharmony_ci lan966x_fdb_write_entries(lan966x, vid); 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_civoid lan966x_vlan_cpu_del_vlan(struct lan966x *lan966x, u16 vid) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci /* Remove the CPU part of the vlan */ 27762306a36Sopenharmony_ci lan966x_vlan_cpu_del_cpu_vlan_mask(lan966x, vid); 27862306a36Sopenharmony_ci lan966x_vlan_cpu_del_vlan_mask(lan966x, vid); 27962306a36Sopenharmony_ci lan966x_fdb_erase_entries(lan966x, vid); 28062306a36Sopenharmony_ci lan966x_mdb_erase_entries(lan966x, vid); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_civoid lan966x_vlan_init(struct lan966x *lan966x) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci u16 port, vid; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci /* Clear VLAN table, by default all ports are members of all VLANS */ 28862306a36Sopenharmony_ci lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_INIT), 28962306a36Sopenharmony_ci ANA_VLANACCESS_VLAN_TBL_CMD, 29062306a36Sopenharmony_ci lan966x, ANA_VLANACCESS); 29162306a36Sopenharmony_ci lan966x_vlan_wait_for_completion(lan966x); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci for (vid = 1; vid < VLAN_N_VID; vid++) { 29462306a36Sopenharmony_ci lan966x->vlan_mask[vid] = 0; 29562306a36Sopenharmony_ci lan966x_vlan_set_mask(lan966x, vid); 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* Set all the ports + cpu to be part of HOST_PVID and UNAWARE_PVID */ 29962306a36Sopenharmony_ci lan966x->vlan_mask[HOST_PVID] = 30062306a36Sopenharmony_ci GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT); 30162306a36Sopenharmony_ci lan966x_vlan_set_mask(lan966x, HOST_PVID); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci lan966x->vlan_mask[UNAWARE_PVID] = 30462306a36Sopenharmony_ci GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT); 30562306a36Sopenharmony_ci lan966x_vlan_set_mask(lan966x, UNAWARE_PVID); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci lan966x_vlan_cpu_add_cpu_vlan_mask(lan966x, UNAWARE_PVID); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci /* Configure the CPU port to be vlan aware */ 31062306a36Sopenharmony_ci lan_wr(ANA_VLAN_CFG_VLAN_VID_SET(0) | 31162306a36Sopenharmony_ci ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) | 31262306a36Sopenharmony_ci ANA_VLAN_CFG_VLAN_POP_CNT_SET(1), 31362306a36Sopenharmony_ci lan966x, ANA_VLAN_CFG(CPU_PORT)); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* Set vlan ingress filter mask to all ports */ 31662306a36Sopenharmony_ci lan_wr(GENMASK(lan966x->num_phys_ports, 0), 31762306a36Sopenharmony_ci lan966x, ANA_VLANMASK); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci for (port = 0; port < lan966x->num_phys_ports; port++) { 32062306a36Sopenharmony_ci lan_wr(0, lan966x, REW_PORT_VLAN_CFG(port)); 32162306a36Sopenharmony_ci lan_wr(0, lan966x, REW_TAG_CFG(port)); 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci} 324