--- zzzz-none-000/linux-5.15.111/drivers/net/macsec.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-arm-6670-761/linux-5.15.111/drivers/net/macsec.c 2024-02-07 09:27:53.000000000 +0000 @@ -5,6 +5,11 @@ * Copyright (c) 2015 Sabrina Dubroca */ + /* +* Includes Intel Corporation's changes dated: 2019. +* Changed portions - Copyright 2019, Intel Corporation. +*/ + #include #include #include @@ -24,52 +29,6 @@ #include -#define MACSEC_SCI_LEN 8 - -/* SecTAG length = macsec_eth_header without the optional SCI */ -#define MACSEC_TAG_LEN 6 - -struct macsec_eth_header { - struct ethhdr eth; - /* SecTAG */ - u8 tci_an; -#if defined(__LITTLE_ENDIAN_BITFIELD) - u8 short_length:6, - unused:2; -#elif defined(__BIG_ENDIAN_BITFIELD) - u8 unused:2, - short_length:6; -#else -#error "Please fix " -#endif - __be32 packet_number; - u8 secure_channel_id[8]; /* optional */ -} __packed; - -#define MACSEC_TCI_VERSION 0x80 -#define MACSEC_TCI_ES 0x40 /* end station */ -#define MACSEC_TCI_SC 0x20 /* SCI present */ -#define MACSEC_TCI_SCB 0x10 /* epon */ -#define MACSEC_TCI_E 0x08 /* encryption */ -#define MACSEC_TCI_C 0x04 /* changed text */ -#define MACSEC_AN_MASK 0x03 /* association number */ -#define MACSEC_TCI_CONFID (MACSEC_TCI_E | MACSEC_TCI_C) - -/* minimum secure data length deemed "not short", see IEEE 802.1AE-2006 9.7 */ -#define MIN_NON_SHORT_LEN 48 - -#define GCM_AES_IV_LEN 12 -#define DEFAULT_ICV_LEN 16 - -#define for_each_rxsc(secy, sc) \ - for (sc = rcu_dereference_bh(secy->rx_sc); \ - sc; \ - sc = rcu_dereference_bh(sc->next)) -#define for_each_rxsc_rtnl(secy, sc) \ - for (sc = rtnl_dereference(secy->rx_sc); \ - sc; \ - sc = rtnl_dereference(sc->next)) - #define pn_same_half(pn1, pn2) (!(((pn1) >> 31) ^ ((pn2) >> 31))) struct gcm_iv_xpn { @@ -80,52 +39,6 @@ __be64 pn; } __packed; -struct gcm_iv { - union { - u8 secure_channel_id[8]; - sci_t sci; - }; - __be32 pn; -}; - -#define MACSEC_VALIDATE_DEFAULT MACSEC_VALIDATE_STRICT - -struct pcpu_secy_stats { - struct macsec_dev_stats stats; - struct u64_stats_sync syncp; -}; - -/** - * struct macsec_dev - private data - * @secy: SecY config - * @real_dev: pointer to underlying netdevice - * @stats: MACsec device stats - * @secys: linked list of SecY's on the underlying device - * @gro_cells: pointer to the Generic Receive Offload cell - * @offload: status of offloading on the MACsec device - */ -struct macsec_dev { - struct macsec_secy secy; - struct net_device *real_dev; - struct pcpu_secy_stats __percpu *stats; - struct list_head secys; - struct gro_cells gro_cells; - enum macsec_offload offload; -}; - -/** - * struct macsec_rxh_data - rx_handler private argument - * @secys: linked list of SecY's on this underlying device - */ -struct macsec_rxh_data { - struct list_head secys; -}; - -static struct macsec_dev *macsec_priv(const struct net_device *dev) -{ - return (struct macsec_dev *)netdev_priv(dev); -} - static struct macsec_rxh_data *macsec_data_rcu(const struct net_device *dev) { return rcu_dereference_bh(dev->rx_handler_data); @@ -1038,7 +951,12 @@ * Strict, frames without a SecTAG are received, counted, and * delivered to the Controlled Port */ +#ifdef CONFIG_MACSEC_HW_OFFLOAD + if ((macsec->hw_offload == false) + && (macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT)) { +#else if (macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) { +#endif u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.InPktsNoTag++; u64_stats_update_end(&secy_stats->syncp); @@ -1053,10 +971,17 @@ nskb->dev = ndev; if (netif_rx(nskb) == NET_RX_SUCCESS) { +#ifdef CONFIG_MACSEC_HW_OFFLOAD + if (macsec->hw_offload == false) { +#endif + u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.InPktsUntagged++; u64_stats_update_end(&secy_stats->syncp); } +#ifdef CONFIG_MACSEC_HW_OFFLOAD + } +#endif } out: @@ -1103,6 +1028,21 @@ hdr = macsec_ethhdr(skb); +#ifdef CONFIG_MACSEC_HW_OFFLOAD + if (macsec_priv(dev)->hw_offload) { + if (hdr->eth.h_proto != htons(ETH_P_PAE)) { + handle_not_macsec(skb); + + kfree_skb(skb); + *pskb = NULL; + return RX_HANDLER_CONSUMED; + } + + /* Deliver to the uncontrolled port the authentication packets */ + return RX_HANDLER_PASS; + } +#endif + /* Frames with a SecTAG that has the TCI E bit set but the C * bit clear are discarded, as this reserved encoding is used * to identify frames with a SecTAG that are not to be @@ -1453,6 +1393,9 @@ } static struct genl_family macsec_fam; +#ifdef CONFIG_MACSEC_HW_OFFLOAD +static struct macsec_hw_driver *macsec_hw_drv = NULL; +#endif static struct net_device *get_dev_from_nl(struct net *net, struct nlattr **attrs) @@ -1771,6 +1714,16 @@ } } +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->add_rxsa) { + if (macsec_hw_drv->add_rxsa(dev, secy, tb_rxsc, tb_sa)) { + rtnl_unlock(); + return -EIO; + } + } +#endif + rx_sa = rtnl_dereference(rx_sc->sa[assoc_num]); if (rx_sa) { rtnl_unlock(); @@ -1862,6 +1815,9 @@ struct net_device *dev; sci_t sci = MACSEC_UNDEF_SCI; struct nlattr **attrs = info->attrs; +//#ifdef CONFIG_MACSEC_HW_OFFLOAD +// struct macsec_secy *secy; +//#endif struct macsec_rx_sc *rx_sc; struct nlattr *tb_rxsc[MACSEC_RXSC_ATTR_MAX + 1]; struct macsec_secy *secy; @@ -1885,6 +1841,17 @@ } secy = &macsec_priv(dev)->secy; + +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->add_rxsc) { + if (macsec_hw_drv->add_rxsc(dev, secy, tb_rxsc)) { + rtnl_unlock(); + return -EIO; + } + } +#endif + sci = nla_get_sci(tb_rxsc[MACSEC_RXSC_ATTR_SCI]); if (tb_rxsc[MACSEC_RXSC_ATTR_ACTIVE]) @@ -2014,6 +1981,16 @@ } } +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->add_txsa) { + if (macsec_hw_drv->add_txsa(dev, secy, tb_sa)) { + rtnl_unlock(); + return -EIO; + } + } +#endif + tx_sa = rtnl_dereference(tx_sc->sa[assoc_num]); if (tx_sa) { rtnl_unlock(); @@ -2145,6 +2122,15 @@ RCU_INIT_POINTER(rx_sc->sa[assoc_num], NULL); clear_rx_sa(rx_sa); +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->del_rxsa) { + if (macsec_hw_drv->del_rxsa(dev, secy, tb_rxsc, tb_sa)) { + rtnl_unlock(); + return -EIO; + } + } +#endif rtnl_unlock(); return 0; @@ -2208,6 +2194,16 @@ } free_rx_sc(rx_sc); + +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->del_rxsc) { + if (macsec_hw_drv->del_rxsc(dev, secy, tb_rxsc)) { + rtnl_unlock(); + return -EIO; + } + } +#endif rtnl_unlock(); return 0; @@ -2270,6 +2266,16 @@ RCU_INIT_POINTER(tx_sc->sa[assoc_num], NULL); clear_tx_sa(tx_sa); +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->del_txsa) { + if (macsec_hw_drv->del_txsa(dev, secy, tb_sa)) { + rtnl_unlock(); + return -EIO; + } + } +#endif + rtnl_unlock(); return 0; @@ -2379,6 +2385,16 @@ goto cleanup; } +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->upd_txsa) { + if (macsec_hw_drv->upd_txsa(dev, secy, tb_sa)) { + rtnl_unlock(); + return -EIO; + } + } +#endif + rtnl_unlock(); return 0; @@ -2472,7 +2488,18 @@ goto cleanup; } +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->upd_rxsa) { + if (macsec_hw_drv->upd_rxsa(dev, secy, tb_rxsc, tb_sa)) { + rtnl_unlock(); + return -EIO; + } + } +#endif + rtnl_unlock(); + return 0; cleanup: @@ -2543,6 +2570,16 @@ goto cleanup; } +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->upd_rxsc) { + if (macsec_hw_drv->upd_rxsc(dev, secy, tb_rxsc)) { + rtnl_unlock(); + return -EIO; + } + } +#endif + rtnl_unlock(); return 0; @@ -3279,6 +3316,14 @@ goto next; secy = &macsec_priv(dev)->secy; + +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->dump) { + if (macsec_hw_drv->dump(dev, secy)) + goto done; + } +#endif if (dump_secy(secy, dev, skb, cb) < 0) goto done; next: @@ -3385,11 +3430,19 @@ } /* 10.5 */ +#ifdef CONFIG_MACSEC_HW_OFFLOAD + if (!secy->protect_frames && !macsec->hw_offload) { +#else if (!secy->protect_frames) { +#endif secy_stats = this_cpu_ptr(macsec->stats); u64_stats_update_begin(&secy_stats->syncp); secy_stats->stats.OutPktsUntagged++; u64_stats_update_end(&secy_stats->syncp); +#ifdef CONFIG_MACSEC_HW_OFFLOAD + } + if (!secy->protect_frames || macsec->hw_offload) { +#endif skb->dev = macsec->real_dev; len = skb->len; ret = dev_queue_xmit(skb); @@ -3830,6 +3883,14 @@ goto cleanup; } +#ifdef CONFIG_MACSEC_HW_OFFLOAD + /* HW driver notification */ + if (macsec_hw_drv && macsec_hw_drv->change_link) { + if (macsec_hw_drv->change_link(dev, &macsec_priv(dev)->secy)) + return -EIO; + } +#endif + return 0; cleanup: @@ -4006,6 +4067,9 @@ dev->priv_flags |= IFF_MACSEC; macsec->real_dev = real_dev; +#ifdef CONFIG_MACSEC_HW_OFFLOAD + macsec->hw_offload = false; +#endif if (data && data[IFLA_MACSEC_OFFLOAD]) macsec->offload = nla_get_offload(data[IFLA_MACSEC_OFFLOAD]); @@ -4037,7 +4101,10 @@ rx_handler = rtnl_dereference(real_dev->rx_handler); if (rx_handler && rx_handler != macsec_handle_frame) + { + pr_info("macsec: rx_handler already registered\n"); return -EBUSY; + } err = register_netdevice(dev); if (err < 0) @@ -4268,10 +4335,11 @@ .get_link_net = macsec_get_link_net, }; -static bool is_macsec_master(struct net_device *dev) +bool is_macsec_master(struct net_device *dev) { return rcu_access_pointer(dev->rx_handler) == macsec_handle_frame; } +EXPORT_SYMBOL(is_macsec_master); static int macsec_notify(struct notifier_block *this, unsigned long event, void *ptr) @@ -4335,6 +4403,34 @@ .notifier_call = macsec_notify, }; +#ifdef CONFIG_MACSEC_HW_OFFLOAD +int macsec_register_hw_driver(struct macsec_hw_driver * hw_driver) +{ + if (!hw_driver) { + return -EINVAL; + } + + rtnl_lock(); + macsec_hw_drv = hw_driver; + rtnl_unlock(); + + pr_info("MACsec hw driver registered\n"); + + return 0; +} +EXPORT_SYMBOL(macsec_register_hw_driver); + +void macsec_unregister_hw_driver(void) +{ + rtnl_lock(); + macsec_hw_drv = NULL; + rtnl_unlock(); + + pr_info("MACsec hw driver unregistered\n"); +} +EXPORT_SYMBOL(macsec_unregister_hw_driver); +#endif /* CONFIG_MACSEC_HW_OFFLOAD */ + static int __init macsec_init(void) { int err;