--- zzzz-none-000/linux-5.15.111/drivers/net/macsec.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/drivers/net/macsec.c 2024-02-07 10:23:12.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 @@ -23,108 +28,7 @@ #include #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 { - union { - u8 short_secure_channel_id[4]; - ssci_t ssci; - }; - __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); -} +#include static struct macsec_rxh_data *macsec_data_rcu(const struct net_device *dev) { @@ -1038,7 +942,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,9 +962,15 @@ 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 } } @@ -1087,6 +1002,21 @@ goto drop_direct; 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 + if (hdr->eth.h_proto != htons(ETH_P_MACSEC)) return handle_not_macsec(skb); @@ -1453,6 +1383,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) @@ -1747,6 +1680,16 @@ return -EINVAL; } +#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 + pn_len = secy->xpn ? MACSEC_XPN_PN_LEN : MACSEC_DEFAULT_PN_LEN; if (tb_sa[MACSEC_SA_ATTR_PN] && nla_len(tb_sa[MACSEC_SA_ATTR_PN]) != pn_len) { @@ -1884,7 +1827,17 @@ return PTR_ERR(dev); } +#ifdef CONFIG_MACSEC_HW_OFFLOAD secy = &macsec_priv(dev)->secy; + /* 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]) @@ -1991,6 +1944,16 @@ return -EINVAL; } +#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 + pn_len = secy->xpn ? MACSEC_XPN_PN_LEN : MACSEC_DEFAULT_PN_LEN; if (nla_len(tb_sa[MACSEC_SA_ATTR_PN]) != pn_len) { pr_notice("macsec: nl: add_txsa: bad pn length: %d != %d\n", @@ -2145,6 +2108,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 +2180,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 +2252,15 @@ 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 +2370,15 @@ 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 +2472,17 @@ 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 +2553,15 @@ 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 +3298,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 +3412,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 +3865,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 +4049,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 +4083,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 +4317,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 +4385,40 @@ .notifier_call = macsec_notify, }; +#ifdef CONFIG_MACSEC_HW_OFFLOAD +struct macsec_dev *macsec_priv(const struct net_device *dev) +{ + return (struct macsec_dev *)netdev_priv(dev); +} +EXPORT_SYMBOL(macsec_priv); + +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;