/* Set default rules to pass unmatched frames */
val = vsc8584_macsec_phy_read(phydev, bank,
MSCC_MS_PARAMS2_IG_CC_CONTROL);
val |= MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_CTRL_ACT |
MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_ACT;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CC_CONTROL,
val);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CP_TAG,
MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_STAG |
MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QTAG |
MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QINQ);
}
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
MSCC_MS_ENA_CFG_SW_RST |
MSCC_MS_ENA_CFG_MACSEC_BYPASS_ENA);
/* Set the MACsec block out of s/w reset and enable clocks */
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
MSCC_MS_ENA_CFG_CLK_ENA);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_STATUS_CONTEXT_CTRL,
bank == MACSEC_INGR ? 0xe5880214 : 0xe5880218);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_MISC_CONTROL,
MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX(bank == MACSEC_INGR ? 57 : 40) |
MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE(bank == MACSEC_INGR ? 1 : 2));
/* Clear the counters */
val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
val |= MSCC_MS_COUNT_CONTROL_AUTO_CNTR_RESET;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
/* Enable octet increment mode */
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PP_CTRL,
MSCC_MS_PP_CTRL_MACSEC_OCTET_INCR_MODE);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_BLOCK_CTX_UPDATE, 0x3);
val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
val |= MSCC_MS_COUNT_CONTROL_RESET_ALL;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
/* Set the MTU */
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_NON_VLAN_MTU_CHECK,
MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE(32761) |
MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMP_DROP);
for (i = 0; i < 8; i++)
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_VLAN_MTU_CHECK(i),
MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE(32761) |
MSCC_MS_VLAN_MTU_CHECK_MTU_COMP_DROP);
if (bank == MACSEC_EGR) {
val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_INTR_CTRL_STATUS);
val &= ~MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE_M;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_INTR_CTRL_STATUS, val);
/* Clear host & line stats */ for (i = 0; i < 36; i++)
vsc8584_macsec_phy_write(phydev, bank, 0x1c + i, 0);
val = vsc8584_macsec_phy_read(phydev, bank,
MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL);
val &= ~MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE_M;
val |= MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE(2) |
MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE(0xffff);
vsc8584_macsec_phy_write(phydev, bank,
MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL, val);
val = vsc8584_macsec_phy_read(phydev, bank,
MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2);
val |= 0xffff;
vsc8584_macsec_phy_write(phydev, bank,
MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2, val);
val = vsc8584_macsec_phy_read(phydev, bank,
MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL); if (bank == HOST_MAC)
val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_TIMER_ENA |
MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA; else
val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_REACT_ENA |
MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA |
MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_MODE |
MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_EARLY_PAUSE_DETECT_ENA;
vsc8584_macsec_phy_write(phydev, bank,
MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL, val);
val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MODE_CFG);
val &= ~MSCC_MAC_CFG_MODE_CFG_DISABLE_DIC;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MODE_CFG, val);
val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG);
val &= ~MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_M;
val |= MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN(10240);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG, val);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ADV_CHK_CFG,
MSCC_MAC_CFG_ADV_CHK_CFG_SFD_CHK_ENA |
MSCC_MAC_CFG_ADV_CHK_CFG_PRM_CHK_ENA |
MSCC_MAC_CFG_ADV_CHK_CFG_OOR_ERR_ENA |
MSCC_MAC_CFG_ADV_CHK_CFG_INR_ERR_ENA);
val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_LFS_CFG);
val &= ~MSCC_MAC_CFG_LFS_CFG_LFS_MODE_ENA;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_LFS_CFG, val);
/* Must be called with mdio_lock taken */ staticint __vsc8584_macsec_init(struct phy_device *phydev)
{ struct vsc8531_private *priv = phydev->priv; enum macsec_bank proc_bank;
u32 val;
val = vsc8584_macsec_phy_read(phydev, FC_BUFFER,
MSCC_FCBUF_TX_DATA_QUEUE_CFG);
val &= ~(MSCC_FCBUF_TX_DATA_QUEUE_CFG_START_M |
MSCC_FCBUF_TX_DATA_QUEUE_CFG_END_M);
val |= MSCC_FCBUF_TX_DATA_QUEUE_CFG_START(0) |
MSCC_FCBUF_TX_DATA_QUEUE_CFG_END(5119);
vsc8584_macsec_phy_write(phydev, FC_BUFFER,
MSCC_FCBUF_TX_DATA_QUEUE_CFG, val);
val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG);
val |= MSCC_FCBUF_ENA_CFG_TX_ENA | MSCC_FCBUF_ENA_CFG_RX_ENA;
vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG, val);
proc_bank = (priv->addr < 2) ? PROC_0 : PROC_2;
val = vsc8584_macsec_phy_read(phydev, proc_bank,
MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL);
val &= ~MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE_M;
val |= MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE(4);
vsc8584_macsec_phy_write(phydev, proc_bank,
MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL, val);
match |= MSCC_MS_SAM_MISC_MATCH_TCI(BIT(3));
mask |= MSCC_MS_SAM_MASK_TCI_MASK(BIT(3)) |
MSCC_MS_SAM_MASK_SCI_MASK;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_LO(idx),
lower_32_bits(sci));
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_HI(idx),
upper_32_bits(sci));
}
if (flow->match.etype) {
mask |= MSCC_MS_SAM_MASK_MAC_ETYPE_MASK;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MAC_SA_MATCH_HI(idx),
MSCC_MS_SAM_MAC_SA_MATCH_HI_ETYPE((__force u32)htons(flow->etype)));
}
match |= MSCC_MS_SAM_MISC_MATCH_PRIORITY(flow->priority);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MISC_MATCH(idx), match);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MASK(idx), mask);
val = MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE(action) |
MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION(MSCC_MS_ACTION_DROP) |
MSCC_MS_SAM_FLOW_CTRL_DEST_PORT(flow->port);
if (action == MSCC_MS_FLOW_BYPASS) goto write_ctrl;
if (bank == MACSEC_INGR) { if (priv->secy->replay_protect)
val |= MSCC_MS_SAM_FLOW_CTRL_REPLAY_PROTECT; if (priv->secy->validate_frames == MACSEC_VALIDATE_STRICT)
val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_STRICT); elseif (priv->secy->validate_frames == MACSEC_VALIDATE_CHECK)
val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_CHECK);
} elseif (bank == MACSEC_EGR) { if (priv->secy->protect_frames)
val |= MSCC_MS_SAM_FLOW_CTRL_PROTECT_FRAME; if (priv->secy->tx_sc.encrypt)
val |= MSCC_MS_SAM_FLOW_CTRL_CONF_PROTECT; if (priv->secy->tx_sc.send_sci)
val |= MSCC_MS_SAM_FLOW_CTRL_INCLUDE_SCI;
}
write_ctrl:
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
}
/* Enable */
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_SET1, BIT(idx));
/* Set in-use */
val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
val |= MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
}
/* Disable */
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_CLEAR1, BIT(idx));
/* Clear in-use */
val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
val &= ~MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
}
/* Derive the AES key to get a key for the hash autentication */ staticint vsc8584_macsec_derive_key(const u8 *key, u16 key_len, u8 hkey[16])
{ const u8 input[AES_BLOCK_SIZE] = {0}; struct crypto_aes_ctx ctx; int ret;
ret = aes_expandkey(&ctx, key, key_len); if (ret) return ret;
staticint vsc8584_macsec_transformation(struct phy_device *phydev, struct macsec_flow *flow, const u8 *key)
{ struct vsc8531_private *priv = phydev->priv; enum macsec_bank bank = flow->bank; int i, ret, index = flow->index;
u32 rec = 0, control = 0;
u8 hkey[16];
u64 sci;
ret = vsc8584_macsec_derive_key(key, priv->secy->key_len, hkey); if (ret) return ret;
switch (priv->secy->key_len) { case 16:
control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_128); break; case 32:
control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_256); break; default: return -EINVAL;
}
/* Set the control word */
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
control);
/* Set the context ID. Must be unique. */
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
vsc8584_macsec_flow_context_id(flow));
/* Set the encryption/decryption key */ for (i = 0; i < priv->secy->key_len / sizeof(u32); i++)
vsc8584_macsec_phy_write(phydev, bank,
MSCC_MS_XFORM_REC(index, rec++),
((u32 *)key)[i]);
/* Set the authentication key */ for (i = 0; i < 4; i++)
vsc8584_macsec_phy_write(phydev, bank,
MSCC_MS_XFORM_REC(index, rec++),
((u32 *)hkey)[i]);
/* Initial sequence number */
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
bank == MACSEC_INGR ?
flow->rx_sa->next_pn : flow->tx_sa->next_pn);
if (bank == MACSEC_INGR) /* Set the mask (replay window size) */
vsc8584_macsec_phy_write(phydev, bank,
MSCC_MS_XFORM_REC(index, rec++),
priv->secy->replay_window);
/* Set the input vectors */
sci = (__force u64)(bank == MACSEC_INGR ? flow->rx_sa->sc->sci : priv->secy->sci);
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
lower_32_bits(sci));
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
upper_32_bits(sci));
while (rec < 20)
vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
0);
/* Add a rule to let the MKA traffic go through, ingress */
flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_INGR); if (IS_ERR(flow)) return PTR_ERR(flow);
/* Add a rule to let the MKA traffic go through, egress */
flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_EGR); if (IS_ERR(flow)) return PTR_ERR(flow);
int vsc8584_macsec_init(struct phy_device *phydev)
{ struct vsc8531_private *vsc8531 = phydev->priv;
switch (phydev->phy_id & phydev->drv->phy_id_mask) { case PHY_ID_VSC856X: case PHY_ID_VSC8582: case PHY_ID_VSC8584:
INIT_LIST_HEAD(&vsc8531->macsec_flows);
vsc8531->secy = NULL;
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.