Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (C) 2018-2021, Intel Corporation. */
0003 
0004 /* Link Aggregation code */
0005 
0006 #include "ice.h"
0007 #include "ice_lag.h"
0008 
0009 /**
0010  * ice_lag_nop_handler - no-op Rx handler to disable LAG
0011  * @pskb: pointer to skb pointer
0012  */
0013 rx_handler_result_t ice_lag_nop_handler(struct sk_buff __always_unused **pskb)
0014 {
0015     return RX_HANDLER_PASS;
0016 }
0017 
0018 /**
0019  * ice_lag_set_primary - set PF LAG state as Primary
0020  * @lag: LAG info struct
0021  */
0022 static void ice_lag_set_primary(struct ice_lag *lag)
0023 {
0024     struct ice_pf *pf = lag->pf;
0025 
0026     if (!pf)
0027         return;
0028 
0029     if (lag->role != ICE_LAG_UNSET && lag->role != ICE_LAG_BACKUP) {
0030         dev_warn(ice_pf_to_dev(pf), "%s: Attempt to be Primary, but incompatible state.\n",
0031              netdev_name(lag->netdev));
0032         return;
0033     }
0034 
0035     lag->role = ICE_LAG_PRIMARY;
0036 }
0037 
0038 /**
0039  * ice_lag_set_backup - set PF LAG state to Backup
0040  * @lag: LAG info struct
0041  */
0042 static void ice_lag_set_backup(struct ice_lag *lag)
0043 {
0044     struct ice_pf *pf = lag->pf;
0045 
0046     if (!pf)
0047         return;
0048 
0049     if (lag->role != ICE_LAG_UNSET && lag->role != ICE_LAG_PRIMARY) {
0050         dev_dbg(ice_pf_to_dev(pf), "%s: Attempt to be Backup, but incompatible state\n",
0051             netdev_name(lag->netdev));
0052         return;
0053     }
0054 
0055     lag->role = ICE_LAG_BACKUP;
0056 }
0057 
0058 /**
0059  * ice_display_lag_info - print LAG info
0060  * @lag: LAG info struct
0061  */
0062 static void ice_display_lag_info(struct ice_lag *lag)
0063 {
0064     const char *name, *peer, *upper, *role, *bonded, *master;
0065     struct device *dev = &lag->pf->pdev->dev;
0066 
0067     name = lag->netdev ? netdev_name(lag->netdev) : "unset";
0068     peer = lag->peer_netdev ? netdev_name(lag->peer_netdev) : "unset";
0069     upper = lag->upper_netdev ? netdev_name(lag->upper_netdev) : "unset";
0070     master = lag->master ? "TRUE" : "FALSE";
0071     bonded = lag->bonded ? "BONDED" : "UNBONDED";
0072 
0073     switch (lag->role) {
0074     case ICE_LAG_NONE:
0075         role = "NONE";
0076         break;
0077     case ICE_LAG_PRIMARY:
0078         role = "PRIMARY";
0079         break;
0080     case ICE_LAG_BACKUP:
0081         role = "BACKUP";
0082         break;
0083     case ICE_LAG_UNSET:
0084         role = "UNSET";
0085         break;
0086     default:
0087         role = "ERROR";
0088     }
0089 
0090     dev_dbg(dev, "%s %s, peer:%s, upper:%s, role:%s, master:%s\n", name,
0091         bonded, peer, upper, role, master);
0092 }
0093 
0094 /**
0095  * ice_lag_info_event - handle NETDEV_BONDING_INFO event
0096  * @lag: LAG info struct
0097  * @ptr: opaque data pointer
0098  *
0099  * ptr is to be cast to (netdev_notifier_bonding_info *)
0100  */
0101 static void ice_lag_info_event(struct ice_lag *lag, void *ptr)
0102 {
0103     struct netdev_notifier_bonding_info *info;
0104     struct netdev_bonding_info *bonding_info;
0105     struct net_device *event_netdev;
0106     const char *lag_netdev_name;
0107 
0108     event_netdev = netdev_notifier_info_to_dev(ptr);
0109     info = ptr;
0110     lag_netdev_name = netdev_name(lag->netdev);
0111     bonding_info = &info->bonding_info;
0112 
0113     if (event_netdev != lag->netdev || !lag->bonded || !lag->upper_netdev)
0114         return;
0115 
0116     if (bonding_info->master.bond_mode != BOND_MODE_ACTIVEBACKUP) {
0117         netdev_dbg(lag->netdev, "Bonding event recv, but mode not active/backup\n");
0118         goto lag_out;
0119     }
0120 
0121     if (strcmp(bonding_info->slave.slave_name, lag_netdev_name)) {
0122         netdev_dbg(lag->netdev, "Bonding event recv, but slave info not for us\n");
0123         goto lag_out;
0124     }
0125 
0126     if (bonding_info->slave.state)
0127         ice_lag_set_backup(lag);
0128     else
0129         ice_lag_set_primary(lag);
0130 
0131 lag_out:
0132     ice_display_lag_info(lag);
0133 }
0134 
0135 /**
0136  * ice_lag_link - handle LAG link event
0137  * @lag: LAG info struct
0138  * @info: info from the netdev notifier
0139  */
0140 static void
0141 ice_lag_link(struct ice_lag *lag, struct netdev_notifier_changeupper_info *info)
0142 {
0143     struct net_device *netdev_tmp, *upper = info->upper_dev;
0144     struct ice_pf *pf = lag->pf;
0145     int peers = 0;
0146 
0147     if (lag->bonded)
0148         dev_warn(ice_pf_to_dev(pf), "%s Already part of a bond\n",
0149              netdev_name(lag->netdev));
0150 
0151     rcu_read_lock();
0152     for_each_netdev_in_bond_rcu(upper, netdev_tmp)
0153         peers++;
0154     rcu_read_unlock();
0155 
0156     if (lag->upper_netdev != upper) {
0157         dev_hold(upper);
0158         lag->upper_netdev = upper;
0159     }
0160 
0161     ice_clear_sriov_cap(pf);
0162     ice_clear_rdma_cap(pf);
0163 
0164     lag->bonded = true;
0165     lag->role = ICE_LAG_UNSET;
0166 
0167     /* if this is the first element in an LAG mark as master */
0168     lag->master = !!(peers == 1);
0169 }
0170 
0171 /**
0172  * ice_lag_unlink - handle unlink event
0173  * @lag: LAG info struct
0174  * @info: info from netdev notification
0175  */
0176 static void
0177 ice_lag_unlink(struct ice_lag *lag,
0178            struct netdev_notifier_changeupper_info *info)
0179 {
0180     struct net_device *netdev_tmp, *upper = info->upper_dev;
0181     struct ice_pf *pf = lag->pf;
0182     bool found = false;
0183 
0184     if (!lag->bonded) {
0185         netdev_dbg(lag->netdev, "bonding unlink event on non-LAG netdev\n");
0186         return;
0187     }
0188 
0189     /* determine if we are in the new LAG config or not */
0190     rcu_read_lock();
0191     for_each_netdev_in_bond_rcu(upper, netdev_tmp) {
0192         if (netdev_tmp == lag->netdev) {
0193             found = true;
0194             break;
0195         }
0196     }
0197     rcu_read_unlock();
0198 
0199     if (found)
0200         return;
0201 
0202     if (lag->upper_netdev) {
0203         dev_put(lag->upper_netdev);
0204         lag->upper_netdev = NULL;
0205     }
0206 
0207     lag->peer_netdev = NULL;
0208     ice_set_sriov_cap(pf);
0209     ice_set_rdma_cap(pf);
0210     lag->bonded = false;
0211     lag->role = ICE_LAG_NONE;
0212 }
0213 
0214 /**
0215  * ice_lag_unregister - handle netdev unregister events
0216  * @lag: LAG info struct
0217  * @netdev: netdev reporting the event
0218  */
0219 static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev)
0220 {
0221     struct ice_pf *pf = lag->pf;
0222 
0223     /* check to see if this event is for this netdev
0224      * check that we are in an aggregate
0225      */
0226     if (netdev != lag->netdev || !lag->bonded)
0227         return;
0228 
0229     if (lag->upper_netdev) {
0230         dev_put(lag->upper_netdev);
0231         lag->upper_netdev = NULL;
0232         ice_set_sriov_cap(pf);
0233         ice_set_rdma_cap(pf);
0234     }
0235     /* perform some cleanup in case we come back */
0236     lag->bonded = false;
0237     lag->role = ICE_LAG_NONE;
0238 }
0239 
0240 /**
0241  * ice_lag_changeupper_event - handle LAG changeupper event
0242  * @lag: LAG info struct
0243  * @ptr: opaque pointer data
0244  *
0245  * ptr is to be cast into netdev_notifier_changeupper_info
0246  */
0247 static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr)
0248 {
0249     struct netdev_notifier_changeupper_info *info;
0250     struct net_device *netdev;
0251 
0252     info = ptr;
0253     netdev = netdev_notifier_info_to_dev(ptr);
0254 
0255     /* not for this netdev */
0256     if (netdev != lag->netdev)
0257         return;
0258 
0259     if (!info->upper_dev) {
0260         netdev_dbg(netdev, "changeupper rcvd, but no upper defined\n");
0261         return;
0262     }
0263 
0264     netdev_dbg(netdev, "bonding %s\n", info->linking ? "LINK" : "UNLINK");
0265 
0266     if (!netif_is_lag_master(info->upper_dev)) {
0267         netdev_dbg(netdev, "changeupper rcvd, but not master. bail\n");
0268         return;
0269     }
0270 
0271     if (info->linking)
0272         ice_lag_link(lag, info);
0273     else
0274         ice_lag_unlink(lag, info);
0275 
0276     ice_display_lag_info(lag);
0277 }
0278 
0279 /**
0280  * ice_lag_changelower_event - handle LAG changelower event
0281  * @lag: LAG info struct
0282  * @ptr: opaque data pointer
0283  *
0284  * ptr to be cast to netdev_notifier_changelowerstate_info
0285  */
0286 static void ice_lag_changelower_event(struct ice_lag *lag, void *ptr)
0287 {
0288     struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
0289 
0290     if (netdev != lag->netdev)
0291         return;
0292 
0293     netdev_dbg(netdev, "bonding info\n");
0294 
0295     if (!netif_is_lag_port(netdev))
0296         netdev_dbg(netdev, "CHANGELOWER rcvd, but netdev not in LAG. Bail\n");
0297 }
0298 
0299 /**
0300  * ice_lag_event_handler - handle LAG events from netdev
0301  * @notif_blk: notifier block registered by this netdev
0302  * @event: event type
0303  * @ptr: opaque data containing notifier event
0304  */
0305 static int
0306 ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event,
0307               void *ptr)
0308 {
0309     struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
0310     struct ice_lag *lag;
0311 
0312     lag = container_of(notif_blk, struct ice_lag, notif_block);
0313 
0314     if (!lag->netdev)
0315         return NOTIFY_DONE;
0316 
0317     /* Check that the netdev is in the working namespace */
0318     if (!net_eq(dev_net(netdev), &init_net))
0319         return NOTIFY_DONE;
0320 
0321     switch (event) {
0322     case NETDEV_CHANGEUPPER:
0323         ice_lag_changeupper_event(lag, ptr);
0324         break;
0325     case NETDEV_CHANGELOWERSTATE:
0326         ice_lag_changelower_event(lag, ptr);
0327         break;
0328     case NETDEV_BONDING_INFO:
0329         ice_lag_info_event(lag, ptr);
0330         break;
0331     case NETDEV_UNREGISTER:
0332         ice_lag_unregister(lag, netdev);
0333         break;
0334     default:
0335         break;
0336     }
0337 
0338     return NOTIFY_DONE;
0339 }
0340 
0341 /**
0342  * ice_register_lag_handler - register LAG handler on netdev
0343  * @lag: LAG struct
0344  */
0345 static int ice_register_lag_handler(struct ice_lag *lag)
0346 {
0347     struct device *dev = ice_pf_to_dev(lag->pf);
0348     struct notifier_block *notif_blk;
0349 
0350     notif_blk = &lag->notif_block;
0351 
0352     if (!notif_blk->notifier_call) {
0353         notif_blk->notifier_call = ice_lag_event_handler;
0354         if (register_netdevice_notifier(notif_blk)) {
0355             notif_blk->notifier_call = NULL;
0356             dev_err(dev, "FAIL register LAG event handler!\n");
0357             return -EINVAL;
0358         }
0359         dev_dbg(dev, "LAG event handler registered\n");
0360     }
0361     return 0;
0362 }
0363 
0364 /**
0365  * ice_unregister_lag_handler - unregister LAG handler on netdev
0366  * @lag: LAG struct
0367  */
0368 static void ice_unregister_lag_handler(struct ice_lag *lag)
0369 {
0370     struct device *dev = ice_pf_to_dev(lag->pf);
0371     struct notifier_block *notif_blk;
0372 
0373     notif_blk = &lag->notif_block;
0374     if (notif_blk->notifier_call) {
0375         unregister_netdevice_notifier(notif_blk);
0376         dev_dbg(dev, "LAG event handler unregistered\n");
0377     }
0378 }
0379 
0380 /**
0381  * ice_init_lag - initialize support for LAG
0382  * @pf: PF struct
0383  *
0384  * Alloc memory for LAG structs and initialize the elements.
0385  * Memory will be freed in ice_deinit_lag
0386  */
0387 int ice_init_lag(struct ice_pf *pf)
0388 {
0389     struct device *dev = ice_pf_to_dev(pf);
0390     struct ice_lag *lag;
0391     struct ice_vsi *vsi;
0392     int err;
0393 
0394     pf->lag = kzalloc(sizeof(*lag), GFP_KERNEL);
0395     if (!pf->lag)
0396         return -ENOMEM;
0397     lag = pf->lag;
0398 
0399     vsi = ice_get_main_vsi(pf);
0400     if (!vsi) {
0401         dev_err(dev, "couldn't get main vsi, link aggregation init fail\n");
0402         err = -EIO;
0403         goto lag_error;
0404     }
0405 
0406     lag->pf = pf;
0407     lag->netdev = vsi->netdev;
0408     lag->role = ICE_LAG_NONE;
0409     lag->bonded = false;
0410     lag->peer_netdev = NULL;
0411     lag->upper_netdev = NULL;
0412     lag->notif_block.notifier_call = NULL;
0413 
0414     err = ice_register_lag_handler(lag);
0415     if (err) {
0416         dev_warn(dev, "INIT LAG: Failed to register event handler\n");
0417         goto lag_error;
0418     }
0419 
0420     ice_display_lag_info(lag);
0421 
0422     dev_dbg(dev, "INIT LAG complete\n");
0423     return 0;
0424 
0425 lag_error:
0426     kfree(lag);
0427     pf->lag = NULL;
0428     return err;
0429 }
0430 
0431 /**
0432  * ice_deinit_lag - Clean up LAG
0433  * @pf: PF struct
0434  *
0435  * Clean up kernel LAG info and free memory
0436  * This function is meant to only be called on driver remove/shutdown
0437  */
0438 void ice_deinit_lag(struct ice_pf *pf)
0439 {
0440     struct ice_lag *lag;
0441 
0442     lag = pf->lag;
0443 
0444     if (!lag)
0445         return;
0446 
0447     if (lag->pf)
0448         ice_unregister_lag_handler(lag);
0449 
0450     dev_put(lag->upper_netdev);
0451 
0452     dev_put(lag->peer_netdev);
0453 
0454     kfree(lag);
0455 
0456     pf->lag = NULL;
0457 }