@@ -93,6 +93,8 @@ struct pcpu_secy_stats {
9393 * @secys: linked list of SecY's on the underlying device
9494 * @gro_cells: pointer to the Generic Receive Offload cell
9595 * @offload: status of offloading on the MACsec device
96+ * @insert_tx_tag: when offloading, device requires to insert an
97+ * additional tag
9698 */
9799struct macsec_dev {
98100 struct macsec_secy secy ;
@@ -102,6 +104,7 @@ struct macsec_dev {
102104 struct list_head secys ;
103105 struct gro_cells gro_cells ;
104106 enum macsec_offload offload ;
107+ bool insert_tx_tag ;
105108};
106109
107110/**
@@ -2568,6 +2571,33 @@ static bool macsec_is_configured(struct macsec_dev *macsec)
25682571 return false;
25692572}
25702573
2574+ static bool macsec_needs_tx_tag (struct macsec_dev * macsec ,
2575+ const struct macsec_ops * ops )
2576+ {
2577+ return macsec -> offload == MACSEC_OFFLOAD_PHY &&
2578+ ops -> mdo_insert_tx_tag ;
2579+ }
2580+
2581+ static void macsec_set_head_tail_room (struct net_device * dev )
2582+ {
2583+ struct macsec_dev * macsec = macsec_priv (dev );
2584+ struct net_device * real_dev = macsec -> real_dev ;
2585+ int needed_headroom , needed_tailroom ;
2586+ const struct macsec_ops * ops ;
2587+
2588+ ops = macsec_get_ops (macsec , NULL );
2589+ if (ops ) {
2590+ needed_headroom = ops -> needed_headroom ;
2591+ needed_tailroom = ops -> needed_tailroom ;
2592+ } else {
2593+ needed_headroom = MACSEC_NEEDED_HEADROOM ;
2594+ needed_tailroom = MACSEC_NEEDED_TAILROOM ;
2595+ }
2596+
2597+ dev -> needed_headroom = real_dev -> needed_headroom + needed_headroom ;
2598+ dev -> needed_tailroom = real_dev -> needed_tailroom + needed_tailroom ;
2599+ }
2600+
25712601static int macsec_update_offload (struct net_device * dev , enum macsec_offload offload )
25722602{
25732603 enum macsec_offload prev_offload ;
@@ -2605,8 +2635,13 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload off
26052635 ctx .secy = & macsec -> secy ;
26062636 ret = offload == MACSEC_OFFLOAD_OFF ? macsec_offload (ops -> mdo_del_secy , & ctx )
26072637 : macsec_offload (ops -> mdo_add_secy , & ctx );
2608- if (ret )
2638+ if (ret ) {
26092639 macsec -> offload = prev_offload ;
2640+ return ret ;
2641+ }
2642+
2643+ macsec_set_head_tail_room (dev );
2644+ macsec -> insert_tx_tag = macsec_needs_tx_tag (macsec , ops );
26102645
26112646 return ret ;
26122647}
@@ -3364,6 +3399,40 @@ static struct genl_family macsec_fam __ro_after_init = {
33643399 .resv_start_op = MACSEC_CMD_UPD_OFFLOAD + 1 ,
33653400};
33663401
3402+ static struct sk_buff * macsec_insert_tx_tag (struct sk_buff * skb ,
3403+ struct net_device * dev )
3404+ {
3405+ struct macsec_dev * macsec = macsec_priv (dev );
3406+ const struct macsec_ops * ops ;
3407+ struct phy_device * phydev ;
3408+ struct macsec_context ctx ;
3409+ int skb_final_len ;
3410+ int err ;
3411+
3412+ ops = macsec_get_ops (macsec , & ctx );
3413+ skb_final_len = skb -> len - ETH_HLEN + ops -> needed_headroom +
3414+ ops -> needed_tailroom ;
3415+ if (unlikely (skb_final_len > macsec -> real_dev -> mtu )) {
3416+ err = - EINVAL ;
3417+ goto cleanup ;
3418+ }
3419+
3420+ phydev = macsec -> real_dev -> phydev ;
3421+
3422+ err = skb_ensure_writable_head_tail (skb , dev );
3423+ if (unlikely (err < 0 ))
3424+ goto cleanup ;
3425+
3426+ err = ops -> mdo_insert_tx_tag (phydev , skb );
3427+ if (unlikely (err ))
3428+ goto cleanup ;
3429+
3430+ return skb ;
3431+ cleanup :
3432+ kfree_skb (skb );
3433+ return ERR_PTR (err );
3434+ }
3435+
33673436static netdev_tx_t macsec_start_xmit (struct sk_buff * skb ,
33683437 struct net_device * dev )
33693438{
@@ -3378,6 +3447,15 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
33783447 skb_dst_drop (skb );
33793448 dst_hold (& md_dst -> dst );
33803449 skb_dst_set (skb , & md_dst -> dst );
3450+
3451+ if (macsec -> insert_tx_tag ) {
3452+ skb = macsec_insert_tx_tag (skb , dev );
3453+ if (IS_ERR (skb )) {
3454+ DEV_STATS_INC (dev , tx_dropped );
3455+ return NETDEV_TX_OK ;
3456+ }
3457+ }
3458+
33813459 skb -> dev = macsec -> real_dev ;
33823460 return dev_queue_xmit (skb );
33833461 }
@@ -3439,10 +3517,7 @@ static int macsec_dev_init(struct net_device *dev)
34393517 dev -> features = real_dev -> features & MACSEC_FEATURES ;
34403518 dev -> features |= NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE ;
34413519
3442- dev -> needed_headroom = real_dev -> needed_headroom +
3443- MACSEC_NEEDED_HEADROOM ;
3444- dev -> needed_tailroom = real_dev -> needed_tailroom +
3445- MACSEC_NEEDED_TAILROOM ;
3520+ macsec_set_head_tail_room (dev );
34463521
34473522 if (is_zero_ether_addr (dev -> dev_addr ))
34483523 eth_hw_addr_inherit (dev , real_dev );
@@ -4125,6 +4200,9 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
41254200 err = macsec_offload (ops -> mdo_add_secy , & ctx );
41264201 if (err )
41274202 goto del_dev ;
4203+
4204+ macsec -> insert_tx_tag =
4205+ macsec_needs_tx_tag (macsec , ops );
41284206 }
41294207 }
41304208
0 commit comments