ice_lag.c (10298B)
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (C) 2018-2021, Intel Corporation. */ 3 4/* Link Aggregation code */ 5 6#include "ice.h" 7#include "ice_lag.h" 8 9/** 10 * ice_lag_nop_handler - no-op Rx handler to disable LAG 11 * @pskb: pointer to skb pointer 12 */ 13rx_handler_result_t ice_lag_nop_handler(struct sk_buff __always_unused **pskb) 14{ 15 return RX_HANDLER_PASS; 16} 17 18/** 19 * ice_lag_set_primary - set PF LAG state as Primary 20 * @lag: LAG info struct 21 */ 22static void ice_lag_set_primary(struct ice_lag *lag) 23{ 24 struct ice_pf *pf = lag->pf; 25 26 if (!pf) 27 return; 28 29 if (lag->role != ICE_LAG_UNSET && lag->role != ICE_LAG_BACKUP) { 30 dev_warn(ice_pf_to_dev(pf), "%s: Attempt to be Primary, but incompatible state.\n", 31 netdev_name(lag->netdev)); 32 return; 33 } 34 35 lag->role = ICE_LAG_PRIMARY; 36} 37 38/** 39 * ice_lag_set_backup - set PF LAG state to Backup 40 * @lag: LAG info struct 41 */ 42static void ice_lag_set_backup(struct ice_lag *lag) 43{ 44 struct ice_pf *pf = lag->pf; 45 46 if (!pf) 47 return; 48 49 if (lag->role != ICE_LAG_UNSET && lag->role != ICE_LAG_PRIMARY) { 50 dev_dbg(ice_pf_to_dev(pf), "%s: Attempt to be Backup, but incompatible state\n", 51 netdev_name(lag->netdev)); 52 return; 53 } 54 55 lag->role = ICE_LAG_BACKUP; 56} 57 58/** 59 * ice_display_lag_info - print LAG info 60 * @lag: LAG info struct 61 */ 62static void ice_display_lag_info(struct ice_lag *lag) 63{ 64 const char *name, *peer, *upper, *role, *bonded, *master; 65 struct device *dev = &lag->pf->pdev->dev; 66 67 name = lag->netdev ? netdev_name(lag->netdev) : "unset"; 68 peer = lag->peer_netdev ? netdev_name(lag->peer_netdev) : "unset"; 69 upper = lag->upper_netdev ? netdev_name(lag->upper_netdev) : "unset"; 70 master = lag->master ? "TRUE" : "FALSE"; 71 bonded = lag->bonded ? "BONDED" : "UNBONDED"; 72 73 switch (lag->role) { 74 case ICE_LAG_NONE: 75 role = "NONE"; 76 break; 77 case ICE_LAG_PRIMARY: 78 role = "PRIMARY"; 79 break; 80 case ICE_LAG_BACKUP: 81 role = "BACKUP"; 82 break; 83 case ICE_LAG_UNSET: 84 role = "UNSET"; 85 break; 86 default: 87 role = "ERROR"; 88 } 89 90 dev_dbg(dev, "%s %s, peer:%s, upper:%s, role:%s, master:%s\n", name, 91 bonded, peer, upper, role, master); 92} 93 94/** 95 * ice_lag_info_event - handle NETDEV_BONDING_INFO event 96 * @lag: LAG info struct 97 * @ptr: opaque data pointer 98 * 99 * ptr is to be cast to (netdev_notifier_bonding_info *) 100 */ 101static void ice_lag_info_event(struct ice_lag *lag, void *ptr) 102{ 103 struct netdev_notifier_bonding_info *info; 104 struct netdev_bonding_info *bonding_info; 105 struct net_device *event_netdev; 106 const char *lag_netdev_name; 107 108 event_netdev = netdev_notifier_info_to_dev(ptr); 109 info = ptr; 110 lag_netdev_name = netdev_name(lag->netdev); 111 bonding_info = &info->bonding_info; 112 113 if (event_netdev != lag->netdev || !lag->bonded || !lag->upper_netdev) 114 return; 115 116 if (bonding_info->master.bond_mode != BOND_MODE_ACTIVEBACKUP) { 117 netdev_dbg(lag->netdev, "Bonding event recv, but mode not active/backup\n"); 118 goto lag_out; 119 } 120 121 if (strcmp(bonding_info->slave.slave_name, lag_netdev_name)) { 122 netdev_dbg(lag->netdev, "Bonding event recv, but slave info not for us\n"); 123 goto lag_out; 124 } 125 126 if (bonding_info->slave.state) 127 ice_lag_set_backup(lag); 128 else 129 ice_lag_set_primary(lag); 130 131lag_out: 132 ice_display_lag_info(lag); 133} 134 135/** 136 * ice_lag_link - handle LAG link event 137 * @lag: LAG info struct 138 * @info: info from the netdev notifier 139 */ 140static void 141ice_lag_link(struct ice_lag *lag, struct netdev_notifier_changeupper_info *info) 142{ 143 struct net_device *netdev_tmp, *upper = info->upper_dev; 144 struct ice_pf *pf = lag->pf; 145 int peers = 0; 146 147 if (lag->bonded) 148 dev_warn(ice_pf_to_dev(pf), "%s Already part of a bond\n", 149 netdev_name(lag->netdev)); 150 151 rcu_read_lock(); 152 for_each_netdev_in_bond_rcu(upper, netdev_tmp) 153 peers++; 154 rcu_read_unlock(); 155 156 if (lag->upper_netdev != upper) { 157 dev_hold(upper); 158 lag->upper_netdev = upper; 159 } 160 161 ice_clear_sriov_cap(pf); 162 ice_clear_rdma_cap(pf); 163 164 lag->bonded = true; 165 lag->role = ICE_LAG_UNSET; 166 167 /* if this is the first element in an LAG mark as master */ 168 lag->master = !!(peers == 1); 169} 170 171/** 172 * ice_lag_unlink - handle unlink event 173 * @lag: LAG info struct 174 * @info: info from netdev notification 175 */ 176static void 177ice_lag_unlink(struct ice_lag *lag, 178 struct netdev_notifier_changeupper_info *info) 179{ 180 struct net_device *netdev_tmp, *upper = info->upper_dev; 181 struct ice_pf *pf = lag->pf; 182 bool found = false; 183 184 if (!lag->bonded) { 185 netdev_dbg(lag->netdev, "bonding unlink event on non-LAG netdev\n"); 186 return; 187 } 188 189 /* determine if we are in the new LAG config or not */ 190 rcu_read_lock(); 191 for_each_netdev_in_bond_rcu(upper, netdev_tmp) { 192 if (netdev_tmp == lag->netdev) { 193 found = true; 194 break; 195 } 196 } 197 rcu_read_unlock(); 198 199 if (found) 200 return; 201 202 if (lag->upper_netdev) { 203 dev_put(lag->upper_netdev); 204 lag->upper_netdev = NULL; 205 } 206 207 lag->peer_netdev = NULL; 208 ice_set_sriov_cap(pf); 209 ice_set_rdma_cap(pf); 210 lag->bonded = false; 211 lag->role = ICE_LAG_NONE; 212} 213 214/** 215 * ice_lag_unregister - handle netdev unregister events 216 * @lag: LAG info struct 217 * @netdev: netdev reporting the event 218 */ 219static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev) 220{ 221 struct ice_pf *pf = lag->pf; 222 223 /* check to see if this event is for this netdev 224 * check that we are in an aggregate 225 */ 226 if (netdev != lag->netdev || !lag->bonded) 227 return; 228 229 if (lag->upper_netdev) { 230 dev_put(lag->upper_netdev); 231 lag->upper_netdev = NULL; 232 ice_set_sriov_cap(pf); 233 ice_set_rdma_cap(pf); 234 } 235 /* perform some cleanup in case we come back */ 236 lag->bonded = false; 237 lag->role = ICE_LAG_NONE; 238} 239 240/** 241 * ice_lag_changeupper_event - handle LAG changeupper event 242 * @lag: LAG info struct 243 * @ptr: opaque pointer data 244 * 245 * ptr is to be cast into netdev_notifier_changeupper_info 246 */ 247static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) 248{ 249 struct netdev_notifier_changeupper_info *info; 250 struct net_device *netdev; 251 252 info = ptr; 253 netdev = netdev_notifier_info_to_dev(ptr); 254 255 /* not for this netdev */ 256 if (netdev != lag->netdev) 257 return; 258 259 if (!info->upper_dev) { 260 netdev_dbg(netdev, "changeupper rcvd, but no upper defined\n"); 261 return; 262 } 263 264 netdev_dbg(netdev, "bonding %s\n", info->linking ? "LINK" : "UNLINK"); 265 266 if (!netif_is_lag_master(info->upper_dev)) { 267 netdev_dbg(netdev, "changeupper rcvd, but not master. bail\n"); 268 return; 269 } 270 271 if (info->linking) 272 ice_lag_link(lag, info); 273 else 274 ice_lag_unlink(lag, info); 275 276 ice_display_lag_info(lag); 277} 278 279/** 280 * ice_lag_changelower_event - handle LAG changelower event 281 * @lag: LAG info struct 282 * @ptr: opaque data pointer 283 * 284 * ptr to be cast to netdev_notifier_changelowerstate_info 285 */ 286static void ice_lag_changelower_event(struct ice_lag *lag, void *ptr) 287{ 288 struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 289 290 if (netdev != lag->netdev) 291 return; 292 293 netdev_dbg(netdev, "bonding info\n"); 294 295 if (!netif_is_lag_port(netdev)) 296 netdev_dbg(netdev, "CHANGELOWER rcvd, but netdev not in LAG. Bail\n"); 297} 298 299/** 300 * ice_lag_event_handler - handle LAG events from netdev 301 * @notif_blk: notifier block registered by this netdev 302 * @event: event type 303 * @ptr: opaque data containing notifier event 304 */ 305static int 306ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event, 307 void *ptr) 308{ 309 struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 310 struct ice_lag *lag; 311 312 lag = container_of(notif_blk, struct ice_lag, notif_block); 313 314 if (!lag->netdev) 315 return NOTIFY_DONE; 316 317 /* Check that the netdev is in the working namespace */ 318 if (!net_eq(dev_net(netdev), &init_net)) 319 return NOTIFY_DONE; 320 321 switch (event) { 322 case NETDEV_CHANGEUPPER: 323 ice_lag_changeupper_event(lag, ptr); 324 break; 325 case NETDEV_CHANGELOWERSTATE: 326 ice_lag_changelower_event(lag, ptr); 327 break; 328 case NETDEV_BONDING_INFO: 329 ice_lag_info_event(lag, ptr); 330 break; 331 case NETDEV_UNREGISTER: 332 ice_lag_unregister(lag, netdev); 333 break; 334 default: 335 break; 336 } 337 338 return NOTIFY_DONE; 339} 340 341/** 342 * ice_register_lag_handler - register LAG handler on netdev 343 * @lag: LAG struct 344 */ 345static int ice_register_lag_handler(struct ice_lag *lag) 346{ 347 struct device *dev = ice_pf_to_dev(lag->pf); 348 struct notifier_block *notif_blk; 349 350 notif_blk = &lag->notif_block; 351 352 if (!notif_blk->notifier_call) { 353 notif_blk->notifier_call = ice_lag_event_handler; 354 if (register_netdevice_notifier(notif_blk)) { 355 notif_blk->notifier_call = NULL; 356 dev_err(dev, "FAIL register LAG event handler!\n"); 357 return -EINVAL; 358 } 359 dev_dbg(dev, "LAG event handler registered\n"); 360 } 361 return 0; 362} 363 364/** 365 * ice_unregister_lag_handler - unregister LAG handler on netdev 366 * @lag: LAG struct 367 */ 368static void ice_unregister_lag_handler(struct ice_lag *lag) 369{ 370 struct device *dev = ice_pf_to_dev(lag->pf); 371 struct notifier_block *notif_blk; 372 373 notif_blk = &lag->notif_block; 374 if (notif_blk->notifier_call) { 375 unregister_netdevice_notifier(notif_blk); 376 dev_dbg(dev, "LAG event handler unregistered\n"); 377 } 378} 379 380/** 381 * ice_init_lag - initialize support for LAG 382 * @pf: PF struct 383 * 384 * Alloc memory for LAG structs and initialize the elements. 385 * Memory will be freed in ice_deinit_lag 386 */ 387int ice_init_lag(struct ice_pf *pf) 388{ 389 struct device *dev = ice_pf_to_dev(pf); 390 struct ice_lag *lag; 391 struct ice_vsi *vsi; 392 int err; 393 394 pf->lag = kzalloc(sizeof(*lag), GFP_KERNEL); 395 if (!pf->lag) 396 return -ENOMEM; 397 lag = pf->lag; 398 399 vsi = ice_get_main_vsi(pf); 400 if (!vsi) { 401 dev_err(dev, "couldn't get main vsi, link aggregation init fail\n"); 402 err = -EIO; 403 goto lag_error; 404 } 405 406 lag->pf = pf; 407 lag->netdev = vsi->netdev; 408 lag->role = ICE_LAG_NONE; 409 lag->bonded = false; 410 lag->peer_netdev = NULL; 411 lag->upper_netdev = NULL; 412 lag->notif_block.notifier_call = NULL; 413 414 err = ice_register_lag_handler(lag); 415 if (err) { 416 dev_warn(dev, "INIT LAG: Failed to register event handler\n"); 417 goto lag_error; 418 } 419 420 ice_display_lag_info(lag); 421 422 dev_dbg(dev, "INIT LAG complete\n"); 423 return 0; 424 425lag_error: 426 kfree(lag); 427 pf->lag = NULL; 428 return err; 429} 430 431/** 432 * ice_deinit_lag - Clean up LAG 433 * @pf: PF struct 434 * 435 * Clean up kernel LAG info and free memory 436 * This function is meant to only be called on driver remove/shutdown 437 */ 438void ice_deinit_lag(struct ice_pf *pf) 439{ 440 struct ice_lag *lag; 441 442 lag = pf->lag; 443 444 if (!lag) 445 return; 446 447 if (lag->pf) 448 ice_unregister_lag_handler(lag); 449 450 if (lag->upper_netdev) 451 dev_put(lag->upper_netdev); 452 453 if (lag->peer_netdev) 454 dev_put(lag->peer_netdev); 455 456 kfree(lag); 457 458 pf->lag = NULL; 459}