diff options
Diffstat (limited to 'drivers/net/macsec.c')
| -rw-r--r-- | drivers/net/macsec.c | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index f6cad0746a02..6147ee8b1d78 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2584,7 +2584,9 @@ static void macsec_inherit_tso_max(struct net_device *dev) netif_inherit_tso_max(dev, macsec->real_dev); } -static int macsec_update_offload(struct net_device *dev, enum macsec_offload offload) +static int macsec_update_offload(struct net_device *dev, + enum macsec_offload offload, + struct netlink_ext_ack *extack) { enum macsec_offload prev_offload; const struct macsec_ops *ops; @@ -2616,14 +2618,35 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload off if (!ops) return -EOPNOTSUPP; - macsec->offload = offload; - ctx.secy = &macsec->secy; ret = offload == MACSEC_OFFLOAD_OFF ? macsec_offload(ops->mdo_del_secy, &ctx) : macsec_offload(ops->mdo_add_secy, &ctx); - if (ret) { - macsec->offload = prev_offload; + if (ret) return ret; + + /* Remove VLAN filters when disabling offload. */ + if (offload == MACSEC_OFFLOAD_OFF) { + vlan_drop_rx_ctag_filter_info(dev); + vlan_drop_rx_stag_filter_info(dev); + } + macsec->offload = offload; + /* Add VLAN filters when enabling offload. */ + if (prev_offload == MACSEC_OFFLOAD_OFF) { + ret = vlan_get_rx_ctag_filter_info(dev); + if (ret) { + NL_SET_ERR_MSG_FMT(extack, + "adding ctag VLAN filters failed, err %d", + ret); + goto rollback_offload; + } + ret = vlan_get_rx_stag_filter_info(dev); + if (ret) { + NL_SET_ERR_MSG_FMT(extack, + "adding stag VLAN filters failed, err %d", + ret); + vlan_drop_rx_ctag_filter_info(dev); + goto rollback_offload; + } } macsec_set_head_tail_room(dev); @@ -2633,6 +2656,12 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload off netdev_update_features(dev); + return 0; + +rollback_offload: + macsec->offload = prev_offload; + macsec_offload(ops->mdo_del_secy, &ctx); + return ret; } @@ -2673,7 +2702,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) offload = nla_get_u8(tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]); if (macsec->offload != offload) - ret = macsec_update_offload(dev, offload); + ret = macsec_update_offload(dev, offload, info->extack); out: rtnl_unlock(); return ret; @@ -3486,7 +3515,8 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, } #define MACSEC_FEATURES \ - (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) + (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ + NETIF_F_HW_VLAN_STAG_FILTER | NETIF_F_HW_VLAN_CTAG_FILTER) #define MACSEC_OFFLOAD_FEATURES \ (MACSEC_FEATURES | NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES | \ @@ -3707,6 +3737,29 @@ restore_old_addr: return err; } +static int macsec_vlan_rx_add_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct macsec_dev *macsec = netdev_priv(dev); + + if (!macsec_is_offloaded(macsec)) + return 0; + + return vlan_vid_add(macsec->real_dev, proto, vid); +} + +static int macsec_vlan_rx_kill_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct macsec_dev *macsec = netdev_priv(dev); + + if (!macsec_is_offloaded(macsec)) + return 0; + + vlan_vid_del(macsec->real_dev, proto, vid); + return 0; +} + static int macsec_change_mtu(struct net_device *dev, int new_mtu) { struct macsec_dev *macsec = macsec_priv(dev); @@ -3748,6 +3801,8 @@ static const struct net_device_ops macsec_netdev_ops = { .ndo_set_rx_mode = macsec_dev_set_rx_mode, .ndo_change_rx_flags = macsec_dev_change_rx_flags, .ndo_set_mac_address = macsec_set_mac_address, + .ndo_vlan_rx_add_vid = macsec_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = macsec_vlan_rx_kill_vid, .ndo_start_xmit = macsec_start_xmit, .ndo_get_stats64 = macsec_get_stats64, .ndo_get_iflink = macsec_get_iflink, @@ -3912,7 +3967,7 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[], offload = nla_get_u8(data[IFLA_MACSEC_OFFLOAD]); if (macsec->offload != offload) { macsec_offload_state_change = true; - ret = macsec_update_offload(dev, offload); + ret = macsec_update_offload(dev, offload, extack); if (ret) goto cleanup; } |
