/** * i40iw_inetaddr_event - system notifier for ipv4 addr events * @notfier: not used * @event: event for notifier * @ptr: if address */ int i40iw_inetaddr_event(struct notifier_block *notifier, unsigned long event, void *ptr) { struct in_ifaddr *ifa = ptr; struct net_device *event_netdev = ifa->ifa_dev->dev; struct net_device *netdev; struct net_device *upper_dev; struct i40iw_device *iwdev; struct i40iw_handler *hdl; u32 local_ipaddr; u32 action = I40IW_ARP_ADD; hdl = i40iw_find_netdev(event_netdev); if (!hdl) return NOTIFY_DONE; iwdev = &hdl->device; if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing) return NOTIFY_DONE; netdev = iwdev->ldev->netdev; upper_dev = netdev_master_upper_dev_get(netdev); if (netdev != event_netdev) return NOTIFY_DONE; if (upper_dev) { struct in_device *in; rcu_read_lock(); in = __in_dev_get_rcu(upper_dev); local_ipaddr = ntohl(in->ifa_list->ifa_address); rcu_read_unlock(); } else { local_ipaddr = ntohl(ifa->ifa_address); } switch (event) { case NETDEV_DOWN: action = I40IW_ARP_DELETE; /* Fall through */ case NETDEV_UP: /* Fall through */ case NETDEV_CHANGEADDR: i40iw_manage_arp_cache(iwdev, netdev->dev_addr, &local_ipaddr, true, action); i40iw_if_notify(iwdev, netdev, &local_ipaddr, true, (action == I40IW_ARP_ADD) ? true : false); break; default: break; } return NOTIFY_DONE; }
/** * i40iw_inet6addr_event - system notifier for ipv6 addr events * @notfier: not used * @event: event for notifier * @ptr: if address */ int i40iw_inet6addr_event(struct notifier_block *notifier, unsigned long event, void *ptr) { struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; struct net_device *event_netdev = ifa->idev->dev; struct net_device *netdev; struct i40iw_device *iwdev; struct i40iw_handler *hdl; u32 local_ipaddr6[4]; u32 action = I40IW_ARP_ADD; hdl = i40iw_find_netdev(event_netdev); if (!hdl) return NOTIFY_DONE; iwdev = &hdl->device; if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing) return NOTIFY_DONE; netdev = iwdev->ldev->netdev; if (netdev != event_netdev) return NOTIFY_DONE; i40iw_copy_ip_ntohl(local_ipaddr6, ifa->addr.in6_u.u6_addr32); switch (event) { case NETDEV_DOWN: action = I40IW_ARP_DELETE; /* Fall through */ case NETDEV_UP: /* Fall through */ case NETDEV_CHANGEADDR: i40iw_manage_arp_cache(iwdev, netdev->dev_addr, local_ipaddr6, false, action); i40iw_if_notify(iwdev, netdev, local_ipaddr6, false, (action == I40IW_ARP_ADD) ? true : false); break; default: break; } return NOTIFY_DONE; }
/** * i40iw_net_event - system notifier for netevents * @notfier: not used * @event: event for notifier * @ptr: neighbor */ int i40iw_net_event(struct notifier_block *notifier, unsigned long event, void *ptr) { struct neighbour *neigh = ptr; struct i40iw_device *iwdev; struct i40iw_handler *iwhdl; __be32 *p; u32 local_ipaddr[4]; switch (event) { case NETEVENT_NEIGH_UPDATE: iwhdl = i40iw_find_netdev((struct net_device *)neigh->dev); if (!iwhdl) return NOTIFY_DONE; iwdev = &iwhdl->device; if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing) return NOTIFY_DONE; p = (__be32 *)neigh->primary_key; i40iw_copy_ip_ntohl(local_ipaddr, p); if (neigh->nud_state & NUD_VALID) { i40iw_manage_arp_cache(iwdev, neigh->ha, local_ipaddr, false, I40IW_ARP_ADD); } else { i40iw_manage_arp_cache(iwdev, neigh->ha, local_ipaddr, false, I40IW_ARP_DELETE); } break; default: break; } return NOTIFY_DONE; }
/** * i40iw_netdevice_event - system notifier for netdev events * @notfier: not used * @event: event for notifier * @ptr: netdev */ int i40iw_netdevice_event(struct notifier_block *notifier, unsigned long event, void *ptr) { struct net_device *event_netdev; struct net_device *netdev; struct i40iw_device *iwdev; struct i40iw_handler *hdl; event_netdev = netdev_notifier_info_to_dev(ptr); hdl = i40iw_find_netdev(event_netdev); if (!hdl) return NOTIFY_DONE; iwdev = &hdl->device; if (iwdev->init_state < RDMA_DEV_REGISTERED || iwdev->closing) return NOTIFY_DONE; netdev = iwdev->ldev->netdev; if (netdev != event_netdev) return NOTIFY_DONE; iwdev->iw_status = 1; switch (event) { case NETDEV_DOWN: iwdev->iw_status = 0; /* Fall through */ case NETDEV_UP: i40iw_port_ibevent(iwdev); break; default: break; } return NOTIFY_DONE; }