#include <net/sock.h>
 #include <net/gro_cells.h>
 #include <net/macsec.h>
+#include <net/dst_metadata.h>
 #include <linux/phy.h>
 #include <linux/byteorder/generic.h>
 #include <linux/if_arp.h>
        int ret, len;
 
        if (macsec_is_offloaded(netdev_priv(dev))) {
+               struct metadata_dst *md_dst = secy->tx_sc.md_dst;
+
+               skb_dst_drop(skb);
+               dst_hold(&md_dst->dst);
+               skb_dst_set(skb, &md_dst->dst);
                skb->dev = macsec->real_dev;
                return dev_queue_xmit(skb);
        }
 {
        struct macsec_dev *macsec = macsec_priv(dev);
 
+       metadata_dst_free(macsec->secy.tx_sc.md_dst);
        free_percpu(macsec->stats);
        free_percpu(macsec->secy.tx_sc.stats);
 
                return -ENOMEM;
        }
 
+       secy->tx_sc.md_dst = metadata_dst_alloc(0, METADATA_MACSEC, GFP_KERNEL);
+       if (!secy->tx_sc.md_dst) {
+               free_percpu(secy->tx_sc.stats);
+               free_percpu(macsec->stats);
+               return -ENOMEM;
+       }
+
        if (sci == MACSEC_UNDEF_SCI)
                sci = dev_to_sci(dev, MACSEC_PORT_ES);
 
        secy->xpn = DEFAULT_XPN;
 
        secy->sci = sci;
+       secy->tx_sc.md_dst->u.macsec_info.sci = sci;
        secy->tx_sc.active = true;
        secy->tx_sc.encoding_sa = DEFAULT_ENCODING_SA;
        secy->tx_sc.encrypt = DEFAULT_ENCRYPT;
 
 
 #include <linux/skbuff.h>
 #include <net/ip_tunnels.h>
+#include <net/macsec.h>
 #include <net/dst.h>
 
 enum metadata_type {
        METADATA_IP_TUNNEL,
        METADATA_HW_PORT_MUX,
+       METADATA_MACSEC,
 };
 
 struct hw_port_info {
        u32 port_id;
 };
 
+struct macsec_info {
+       sci_t sci;
+};
+
 struct metadata_dst {
        struct dst_entry                dst;
        enum metadata_type              type;
        union {
                struct ip_tunnel_info   tun_info;
                struct hw_port_info     port_info;
+               struct macsec_info      macsec_info;
        } u;
 };
 
                return memcmp(&a->u.tun_info, &b->u.tun_info,
                              sizeof(a->u.tun_info) +
                                         a->u.tun_info.options_len);
+       case METADATA_MACSEC:
+               return memcmp(&a->u.macsec_info, &b->u.macsec_info,
+                             sizeof(a->u.macsec_info));
        default:
                return 1;
        }
 
 typedef u64 __bitwise sci_t;
 typedef u32 __bitwise ssci_t;
 
+struct metadata_dst;
+
 typedef union salt {
        struct {
                u32 ssci;
  * @scb: single copy broadcast flag
  * @sa: array of secure associations
  * @stats: stats for this TXSC
+ * @md_dst: MACsec offload metadata dst
  */
 struct macsec_tx_sc {
        bool active;
        bool scb;
        struct macsec_tx_sa __rcu *sa[MACSEC_NUM_AN];
        struct pcpu_tx_sc_stats __percpu *stats;
+       struct metadata_dst *md_dst;
 };
 
 /**