/* Set flags and the VID to configure */
lan_rmw(ANA_VLANTIDX_VLAN_PGID_CPU_DIS_SET(cpu_dis) |
ANA_VLANTIDX_V_INDEX_SET(vid),
ANA_VLANTIDX_VLAN_PGID_CPU_DIS |
ANA_VLANTIDX_V_INDEX,
lan966x, ANA_VLANTIDX);
/* Set the vlan port members mask */
lan_rmw(ANA_VLAN_PORT_MASK_VLAN_PORT_MASK_SET(mask),
ANA_VLAN_PORT_MASK_VLAN_PORT_MASK,
lan966x, ANA_VLAN_PORT_MASK);
/* Issue a write command */
lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_WRITE),
ANA_VLANACCESS_VLAN_TBL_CMD,
lan966x, ANA_VLANACCESS);
if (lan966x_vlan_wait_for_completion(lan966x))
dev_err(lan966x->dev, "Vlan set mask failed\n");
}
/* When the interface is in host mode, the interface should not be vlan aware * but it should insert all the tags that it gets from the network stack. * The tags are not in the data of the frame but actually in the skb and the ifh * is configured already to get this tag. So what we need to do is to update the * rewriter to insert the vlan tag for all frames which have a vlan tag * different than 0.
*/ void lan966x_vlan_port_rew_host(struct lan966x_port *port)
{ struct lan966x *lan966x = port->lan966x;
u32 val;
/* Tag all frames except when VID=0*/
val = REW_TAG_CFG_TAG_CFG_SET(2);
/* Update only some bits in the register */
lan_rmw(val,
REW_TAG_CFG_TAG_CFG,
lan966x, REW_TAG_CFG(port->chip_port));
}
/* Ingress classification (ANA_PORT_VLAN_CFG) */ /* Default vlan to classify for untagged frames (may be zero) */
val = ANA_VLAN_CFG_VLAN_VID_SET(pvid); if (port->vlan_aware)
val |= ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) |
ANA_VLAN_CFG_VLAN_POP_CNT_SET(1);
/* Drop frames with multicast source address */
val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1); if (port->vlan_aware && !pvid) /* If port is vlan-aware and tagged, drop untagged and priority * tagged frames.
*/
val |= ANA_DROP_CFG_DROP_UNTAGGED_ENA_SET(1) |
ANA_DROP_CFG_DROP_PRIO_S_TAGGED_ENA_SET(1) |
ANA_DROP_CFG_DROP_PRIO_C_TAGGED_ENA_SET(1);
/* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q */
val = REW_TAG_CFG_TAG_TPID_CFG_SET(0); if (port->vlan_aware) { if (port->vid) /* Tag all frames except when VID == DEFAULT_VLAN */
val |= REW_TAG_CFG_TAG_CFG_SET(1); else
val |= REW_TAG_CFG_TAG_CFG_SET(3);
}
/* Update only some bits in the register */
lan_rmw(val,
REW_TAG_CFG_TAG_TPID_CFG | REW_TAG_CFG_TAG_CFG,
lan966x, REW_TAG_CFG(port->chip_port));
/* Set default VLAN and tag type to 8021Q */
lan_rmw(REW_PORT_VLAN_CFG_PORT_TPID_SET(ETH_P_8021Q) |
REW_PORT_VLAN_CFG_PORT_VID_SET(port->vid),
REW_PORT_VLAN_CFG_PORT_TPID |
REW_PORT_VLAN_CFG_PORT_VID,
lan966x, REW_PORT_VLAN_CFG(port->chip_port));
}
/* If the CPU(br) is already part of the vlan then add the fdb * entries in MAC table to copy the frames to the CPU(br). * If the CPU(br) is not part of the vlan then it would * just drop the frames.
*/ if (lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x, vid)) {
lan966x_vlan_cpu_add_vlan_mask(lan966x, vid);
lan966x_fdb_write_entries(lan966x, vid);
lan966x_mdb_write_entries(lan966x, vid);
}
/* In case there are no other ports in vlan then remove the CPU from * that vlan but still keep it in the mask because it may be needed * again then another port gets added in that vlan
*/ if (!lan966x_vlan_port_any_vlan_mask(lan966x, vid)) {
lan966x_vlan_cpu_del_vlan_mask(lan966x, vid);
lan966x_fdb_erase_entries(lan966x, vid);
lan966x_mdb_erase_entries(lan966x, vid);
}
}
void lan966x_vlan_cpu_add_vlan(struct lan966x *lan966x, u16 vid)
{ /* Add an entry in the MAC table for the CPU * Add the CPU part of the vlan only if there is another port in that * vlan otherwise all the broadcast frames in that vlan will go to CPU * even if none of the ports are in the vlan and then the CPU will just * need to discard these frames. It is required to store this * information so when a front port is added then it would add also the * CPU port.
*/ if (lan966x_vlan_port_any_vlan_mask(lan966x, vid)) {
lan966x_vlan_cpu_add_vlan_mask(lan966x, vid);
lan966x_mdb_write_entries(lan966x, vid);
}
void lan966x_vlan_cpu_del_vlan(struct lan966x *lan966x, u16 vid)
{ /* Remove the CPU part of the vlan */
lan966x_vlan_cpu_del_cpu_vlan_mask(lan966x, vid);
lan966x_vlan_cpu_del_vlan_mask(lan966x, vid);
lan966x_fdb_erase_entries(lan966x, vid);
lan966x_mdb_erase_entries(lan966x, vid);
}
/* Clear VLAN table, by default all ports are members of all VLANS */
lan_rmw(ANA_VLANACCESS_VLAN_TBL_CMD_SET(VLANACCESS_CMD_INIT),
ANA_VLANACCESS_VLAN_TBL_CMD,
lan966x, ANA_VLANACCESS);
lan966x_vlan_wait_for_completion(lan966x);
for (vid = 1; vid < VLAN_N_VID; vid++) {
lan966x->vlan_mask[vid] = 0;
lan966x_vlan_set_mask(lan966x, vid);
}
/* Set all the ports + cpu to be part of HOST_PVID and UNAWARE_PVID */
lan966x->vlan_mask[HOST_PVID] =
GENMASK(lan966x->num_phys_ports - 1, 0) | BIT(CPU_PORT);
lan966x_vlan_set_mask(lan966x, HOST_PVID);
/* Configure the CPU port to be vlan aware */
lan_wr(ANA_VLAN_CFG_VLAN_VID_SET(0) |
ANA_VLAN_CFG_VLAN_AWARE_ENA_SET(1) |
ANA_VLAN_CFG_VLAN_POP_CNT_SET(1),
lan966x, ANA_VLAN_CFG(CPU_PORT));
/* Set vlan ingress filter mask to all ports */
lan_wr(GENMASK(lan966x->num_phys_ports, 0),
lan966x, ANA_VLANMASK);
for (port = 0; port < lan966x->num_phys_ports; port++) {
lan_wr(0, lan966x, REW_PORT_VLAN_CFG(port));
lan_wr(0, lan966x, REW_TAG_CFG(port));
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.