/** * tipc_l2_device_event - handle device events from network device * @nb: the context of the notification * @evt: the type of event * @ptr: the net device that the event was on * * This function is called by the Ethernet driver in case of link * change event. */ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, void *ptr) { struct tipc_bearer *b_ptr; struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; b_ptr = rtnl_dereference(dev->tipc_ptr); if (!b_ptr) return NOTIFY_DONE; b_ptr->mtu = dev->mtu; switch (evt) { case NETDEV_CHANGE: if (netif_carrier_ok(dev)) break; case NETDEV_DOWN: case NETDEV_CHANGEMTU: tipc_reset_bearer(b_ptr); break; case NETDEV_CHANGEADDR: b_ptr->media->raw2addr(b_ptr, &b_ptr->addr, (char *)dev->dev_addr); tipc_reset_bearer(b_ptr); break; case NETDEV_UNREGISTER: case NETDEV_CHANGENAME: bearer_disable(b_ptr, false); break; } return NOTIFY_OK; }
/* Register for a notification on device removal */ static int linux_netmap_notifier_cb(struct notifier_block *b, unsigned long val, void *v) { struct ifnet *ifp = netdev_notifier_info_to_dev(v); /* linux calls us while holding rtnl_lock() */ switch (val) { case NETDEV_REGISTER: netmap_undo_zombie(ifp); break; case NETDEV_UNREGISTER: netmap_make_zombie(ifp); break; case NETDEV_GOING_DOWN: netmap_disable_all_rings(ifp); break; case NETDEV_UP: netmap_enable_all_rings(ifp); break; default: /* we don't care */ break; } return NOTIFY_OK; }
static int brnf_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct brnf_net *brnet; struct net *net; int ret; if (event != NETDEV_REGISTER || !(dev->priv_flags & IFF_EBRIDGE)) return NOTIFY_DONE; ASSERT_RTNL(); net = dev_net(dev); brnet = net_generic(net, brnf_net_id); if (brnet->enabled) return NOTIFY_OK; ret = nf_register_net_hooks(net, br_nf_ops, ARRAY_SIZE(br_nf_ops)); if (ret) return NOTIFY_BAD; brnet->enabled = true; return NOTIFY_OK; }
static int macvtap_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct macvtap_dev *vlantap; struct device *classdev; dev_t devt; int err; char tap_name[IFNAMSIZ]; if (dev->rtnl_link_ops != &macvtap_link_ops) return NOTIFY_DONE; snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex); vlantap = netdev_priv(dev); switch (event) { case NETDEV_REGISTER: /* Create the device node here after the network device has * been registered but before register_netdevice has * finished running. */ err = tap_get_minor(macvtap_major, &vlantap->tap); if (err) return notifier_from_errno(err); devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor); classdev = device_create(&macvtap_class, &dev->dev, devt, dev, tap_name); if (IS_ERR(classdev)) { tap_free_minor(macvtap_major, &vlantap->tap); return notifier_from_errno(PTR_ERR(classdev)); } err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj, tap_name); if (err) return notifier_from_errno(err); break; case NETDEV_UNREGISTER: /* vlan->minor == 0 if NETDEV_REGISTER above failed */ if (vlantap->tap.minor == 0) break; sysfs_remove_link(&dev->dev.kobj, tap_name); devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor); device_destroy(&macvtap_class, devt); tap_free_minor(macvtap_major, &vlantap->tap); break; case NETDEV_CHANGE_TX_QUEUE_LEN: if (tap_queue_resize(&vlantap->tap)) return NOTIFY_BAD; break; } return NOTIFY_DONE; }
static int raw_notifier(struct notifier_block *nb, unsigned long msg, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct raw_sock *ro = container_of(nb, struct raw_sock, notifier); struct sock *sk = &ro->sk; if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; if (dev->type != ARPHRD_CAN) return NOTIFY_DONE; if (ro->ifindex != dev->ifindex) return NOTIFY_DONE; switch (msg) { case NETDEV_UNREGISTER: lock_sock(sk); /* remove current filters & unregister */ if (ro->bound) raw_disable_allfilters(dev, sk); if (ro->count > 1) kfree(ro->filter); ro->ifindex = 0; ro->bound = 0; ro->count = 0; release_sock(sk); sk->sk_err = ENODEV; if (!sock_flag(sk, SOCK_DEAD)) sk->sk_error_report(sk); break; case NETDEV_DOWN: sk->sk_err = ENETDOWN; if (!sock_flag(sk, SOCK_DEAD)) sk->sk_error_report(sk); break; } return NOTIFY_DONE; }
static int vti_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct ip_tunnel *tunnel = netdev_priv(dev); if (!is_vti_tunnel(dev)) return NOTIFY_DONE; switch (event) { case NETDEV_DOWN: if (!net_eq(tunnel->net, dev_net(dev))) xfrm_garbage_collect(tunnel->net); break; } return NOTIFY_DONE; }
static int vrf_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); /* only care about unregister events to drop slave references */ if (event == NETDEV_UNREGISTER) { struct net_device *vrf_dev; if (!netif_is_l3_slave(dev)) goto out; vrf_dev = netdev_master_upper_dev_get(dev); vrf_del_slave(vrf_dev, dev); } out: return NOTIFY_DONE; }
/** * recv_notification - handle device updates from OS * * Change the state of the InfiniBand bearer (if any) associated with the * specified device. */ static int recv_notification(struct notifier_block *nb, unsigned long evt, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct ib_bearer *ib_ptr = &ib_bearers[0]; struct ib_bearer *stop = &ib_bearers[MAX_IB_BEARERS]; if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; while ((ib_ptr->dev != dev)) { if (++ib_ptr == stop) return NOTIFY_DONE; /* couldn't find device */ } if (!ib_ptr->bearer) return NOTIFY_DONE; /* bearer had been disabled */ ib_ptr->bearer->mtu = dev->mtu; switch (evt) { case NETDEV_CHANGE: if (netif_carrier_ok(dev)) tipc_continue(ib_ptr->bearer); else tipc_block_bearer(ib_ptr->bearer->name); break; case NETDEV_UP: tipc_continue(ib_ptr->bearer); break; case NETDEV_DOWN: tipc_block_bearer(ib_ptr->bearer->name); break; case NETDEV_CHANGEMTU: case NETDEV_CHANGEADDR: tipc_block_bearer(ib_ptr->bearer->name); tipc_continue(ib_ptr->bearer); break; case NETDEV_UNREGISTER: case NETDEV_CHANGENAME: tipc_disable_bearer(ib_ptr->bearer->name); break; } return NOTIFY_OK; }
static int netdev_trig_notify(struct notifier_block *nb, unsigned long evt, void *dv) { struct net_device *dev = netdev_notifier_info_to_dev((struct netdev_notifier_info *) dv); struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier); if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER && evt != NETDEV_CHANGENAME) return NOTIFY_DONE; spin_lock_bh(&trigger_data->lock); if (strcmp(dev->name, trigger_data->device_name)) goto done; del_timer_sync(&trigger_data->timer); if (evt == NETDEV_REGISTER || evt == NETDEV_CHANGENAME) { if (trigger_data->net_dev != NULL) dev_put(trigger_data->net_dev); dev_hold(dev); trigger_data->net_dev = dev; trigger_data->link_up = 0; goto done; } if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) { dev_put(trigger_data->net_dev); trigger_data->net_dev = NULL; goto done; } /* UP / DOWN / CHANGE */ trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev)); set_baseline_state(trigger_data); done: spin_unlock_bh(&trigger_data->lock); return NOTIFY_DONE; }
/* NETDEV rename notifier to rename the associated led triggers too */ static int can_led_notifier(struct notifier_block *nb, unsigned long msg, void *ptr) { struct net_device *netdev = netdev_notifier_info_to_dev(ptr); struct can_priv *priv = safe_candev_priv(netdev); char name[CAN_LED_NAME_SZ]; if (!priv) return NOTIFY_DONE; if (msg == NETDEV_CHANGENAME) { snprintf(name, sizeof(name), "%s-tx", netdev->name); led_trigger_rename_static(name, priv->tx_led_trig); snprintf(name, sizeof(name), "%s-rx", netdev->name); led_trigger_rename_static(name, priv->rx_led_trig); } return NOTIFY_DONE; }
static int rmnet_config_notify_cb(struct notifier_block *nb, unsigned long event, void *data) { struct net_device *dev = netdev_notifier_info_to_dev(data); if (!dev) return NOTIFY_DONE; switch (event) { case NETDEV_UNREGISTER: netdev_dbg(dev, "Kernel unregister\n"); rmnet_force_unassociate_device(dev); break; default: break; } return NOTIFY_DONE; }
static int rxe_notify(struct notifier_block *not_blk, unsigned long event, void *arg) { struct net_device *ndev = netdev_notifier_info_to_dev(arg); struct rxe_dev *rxe = rxe_get_dev_from_net(ndev); if (!rxe) return NOTIFY_OK; switch (event) { case NETDEV_UNREGISTER: ib_unregister_device_queued(&rxe->ib_dev); break; case NETDEV_UP: rxe_port_up(rxe); break; case NETDEV_DOWN: rxe_port_down(rxe); break; case NETDEV_CHANGEMTU: pr_info("%s changed mtu to %d\n", ndev->name, ndev->mtu); rxe_set_mtu(rxe, ndev->mtu); break; case NETDEV_CHANGE: rxe_set_port_state(rxe); break; case NETDEV_REBOOT: case NETDEV_GOING_DOWN: case NETDEV_CHANGEADDR: case NETDEV_CHANGENAME: case NETDEV_FEAT_CHANGE: default: pr_info("ignoring netdev event = %ld for %s\n", event, ndev->name); break; } ib_device_put(&rxe->ib_dev); return NOTIFY_OK; }
int dsa_slave_netdevice_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev; int err = 0; switch (event) { case NETDEV_CHANGEUPPER: dev = netdev_notifier_info_to_dev(ptr); if (!dsa_slave_dev_check(dev)) goto out; err = dsa_slave_master_changed(dev); if (err && err != -EOPNOTSUPP) netdev_warn(dev, "failed to reflect master change\n"); break; } out: return NOTIFY_DONE; }
static int bpf_offload_notification(struct notifier_block *notifier, ulong event, void *ptr) { struct net_device *netdev = netdev_notifier_info_to_dev(ptr); ASSERT_RTNL(); switch (event) { case NETDEV_UNREGISTER: /* ignore namespace changes */ if (netdev->reg_state != NETREG_UNREGISTERING) break; down_write(&bpf_devs_lock); bpf_offload_orphan_all_progs(netdev); bpf_offload_orphan_all_maps(netdev); up_write(&bpf_devs_lock); break; default: break; } return NOTIFY_OK; }
static int lowpan_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct inet6_dev *idev; struct in6_addr addr; int i; if (dev->type != ARPHRD_6LOWPAN) return NOTIFY_DONE; idev = __in6_dev_get(dev); if (!idev) return NOTIFY_DONE; switch (event) { case NETDEV_UP: case NETDEV_CHANGE: /* (802.15.4 6LoWPAN short address slaac handling */ if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154) && addrconf_ifid_802154_6lowpan(addr.s6_addr + 8, dev) == 0) { __ipv6_addr_set_half(&addr.s6_addr32[0], htonl(0xFE800000), 0); addrconf_add_linklocal(idev, &addr, 0); } break; case NETDEV_DOWN: for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) clear_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, &lowpan_dev(dev)->ctx.table[i].flags); break; default: return NOTIFY_DONE; } return NOTIFY_OK; }
/** * 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; }
/* * Handle changes in state of network devices enslaved to a bridge. * * Note: don't care about up/down if bridge itself is down, because * port state is checked when bridge is brought up. */ static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_bridge_port *p; struct net_bridge *br; bool changed_addr; int err; /* register of bridge completed, add sysfs entries */ if ((dev->priv_flags & IFF_EBRIDGE) && event == NETDEV_REGISTER) { br_sysfs_addbr(dev); return NOTIFY_DONE; } /* not a port of a bridge */ p = br_port_get_rtnl(dev); if (!p) return NOTIFY_DONE; br = p->br; switch (event) { case NETDEV_CHANGEMTU: dev_set_mtu(br->dev, br_min_mtu(br)); break; case NETDEV_CHANGEADDR: spin_lock_bh(&br->lock); br_fdb_changeaddr(p, dev->dev_addr); changed_addr = br_stp_recalculate_bridge_id(br); spin_unlock_bh(&br->lock); if (changed_addr) call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); break; case NETDEV_CHANGE: br_port_carrier_check(p); break; case NETDEV_FEAT_CHANGE: netdev_update_features(br->dev); break; case NETDEV_DOWN: spin_lock_bh(&br->lock); if (br->dev->flags & IFF_UP) br_stp_disable_port(p); spin_unlock_bh(&br->lock); break; case NETDEV_UP: if (netif_running(br->dev) && netif_oper_up(dev)) { spin_lock_bh(&br->lock); br_stp_enable_port(p); spin_unlock_bh(&br->lock); } break; case NETDEV_UNREGISTER: br_del_if(br, dev); break; case NETDEV_CHANGENAME: err = br_sysfs_renameif(p); if (err) return notifier_from_errno(err); break; case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ return NOTIFY_BAD; case NETDEV_RESEND_IGMP: /* Propagate to master device */ call_netdevice_notifiers(event, br->dev); break; } /* Events that may cause spanning tree to refresh */ if (event == NETDEV_CHANGEADDR || event == NETDEV_UP || event == NETDEV_CHANGE || event == NETDEV_DOWN) br_ifinfo_notify(RTM_NEWLINK, p); return NOTIFY_DONE; }
for(i=0; i<MAX_REQ_BATCH_SIZE; ++i){ gnom_tx(m_lw_pending_batches[batch_ind].tx_batch_ind, i, 1024); } #endif return 0; write_err: printk("[GNoM_km]: Error on buffer recycle... (n_cpy=%d, call_back=%p, batch_id=%d, v_batch_id: %d)\n", n_cpy, ixgbe_callback_recycle_grxb_batch, m_lw_pending_batches[batch_ind].batch_id, v_batch_id); return 1; } // Structure and code borrowed from NTOP PF_RING to set hooks for GNoM_ND (Modified Intel IXGBE network driver). static int gpu_notifier(struct notifier_block *this, unsigned long msg, void *data){ struct net_device *dev = netdev_notifier_info_to_dev(data); ubc_gpu_hooks *hook; if(dev != NULL) { /* Skip non ethernet interfaces */ if( (dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_IEEE80211) && (dev->type != ARPHRD_IEEE80211_PRISM) && (dev->type != ARPHRD_IEEE80211_RADIOTAP) && strncmp(dev->name, "bond", 4)) { return NOTIFY_DONE; } switch(msg) { case NETDEV_PRE_UP: case NETDEV_UP:
return NOTIFY_DONE; } static int xfrm_dev_down(struct net_device *dev) { if (dev->features & NETIF_F_HW_ESP) xfrm_dev_state_flush(dev_net(dev), dev, true); xfrm_policy_cache_flush(); return NOTIFY_DONE; } static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); switch (event) { case NETDEV_REGISTER: return xfrm_dev_register(dev); case NETDEV_UNREGISTER: return xfrm_dev_unregister(dev); case NETDEV_FEAT_CHANGE: return xfrm_dev_feat_change(dev); case NETDEV_DOWN: return xfrm_dev_down(dev); } return NOTIFY_DONE;
static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct mpoa_client *mpc; struct lec_priv *priv; if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; if (strncmp(dev->name, "lec", 3)) return NOTIFY_DONE; /* we are only interested in lec:s */ switch (event) { case NETDEV_REGISTER: /* a new lec device was allocated */ priv = netdev_priv(dev); if (priv->lane_version < 2) break; priv->lane2_ops->associate_indicator = lane2_assoc_ind; mpc = find_mpc_by_itfnum(priv->itfnum); if (mpc == NULL) { dprintk("allocating new mpc for %s\n", dev->name); mpc = alloc_mpc(); if (mpc == NULL) { pr_info("no new mpc"); break; } } mpc->dev_num = priv->itfnum; mpc->dev = dev; dev_hold(dev); dprintk("(%s) was initialized\n", dev->name); break; case NETDEV_UNREGISTER: /* the lec device was deallocated */ mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; dprintk("device (%s) was deallocated\n", dev->name); stop_mpc(mpc); dev_put(mpc->dev); mpc->dev = NULL; break; case NETDEV_UP: /* the dev was ifconfig'ed up */ mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; if (mpc->mpoad_vcc != NULL) start_mpc(mpc, dev); break; case NETDEV_DOWN: /* the dev was ifconfig'ed down */ /* this means that the flow of packets from the * upper layer stops */ mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; if (mpc->mpoad_vcc != NULL) stop_mpc(mpc); break; case NETDEV_REBOOT: case NETDEV_CHANGE: case NETDEV_CHANGEMTU: case NETDEV_CHANGEADDR: case NETDEV_GOING_DOWN: break; default: break; } return NOTIFY_DONE; }
static int netdev_callback(struct notifier_block *self, unsigned long event, void *ctx) { struct net_device *dev; struct net_device *dev_n = netdev_notifier_info_to_dev(ctx); struct in_device *in_dev; char *lo_if = "lo"; switch (event) { case NETDEV_UP: case NETDEV_CHANGE: case NETDEV_CHANGEADDR: case NETDEV_NOTIFY_PEERS: in_dev = __in_dev_get_rtnl(dev_n); if (!in_dev) { printk(KERN_INFO "not in dev, skip\n"); break; } if (dev_n->operstate == IF_OPER_UP) { msleep( garp_delay ); if (debug == 1) printk(KERN_INFO "send gratuitous arp from [%s]\n", dev_n->name); inetdev_send_gratuitous_arp(dev_n, in_dev); } if (send_all == 1) { if ( strcmp(dev_n->name, lo_if) == 0){ if (debug == 1) printk(KERN_INFO "notification from lo, skip\n"); break; } dev = first_net_device(&init_net); read_lock(&dev_base_lock); while (dev) { if (debug == 1) printk(KERN_INFO "found [%s], notification from [%s]\n", dev->name, dev_n->name); if (dev->operstate == IF_OPER_UP) { if (debug == 1) printk(KERN_INFO "[%s] type [%d] state [%d] is up\n", dev->name, dev->type, dev->operstate); } else { if (debug == 1) printk(KERN_INFO "[%s] type [%d] state [%d] unknown oper state\n", dev->name, dev->type, dev->operstate); } if (strcmp(dev->name, lo_if) == 0){ if (debug == 1) printk(KERN_INFO "skip lo\n"); dev = next_net_device(dev); continue; } in_dev = __in_dev_get_rtnl(dev); if (!in_dev) { if (debug == 1) printk(KERN_INFO "not in dev\n"); dev = next_net_device(dev); continue; } if (dev->operstate == IF_OPER_UP) { inetdev_send_gratuitous_arp(dev, in_dev); } dev = next_net_device(dev); } read_unlock(&dev_base_lock); } break; } if (debug == 1) { switch (event) { case NETDEV_UP: printk(KERN_INFO "got NETDEV_UP\n"); break; case NETDEV_DOWN: printk(KERN_INFO "got NETDEV_DOWN\n"); break; case NETDEV_REBOOT: printk(KERN_INFO "got NETDEV_REBOOT\n"); break; case NETDEV_CHANGE: printk(KERN_INFO "got NETDEV_CHANGE\n"); break; case NETDEV_REGISTER: printk(KERN_INFO "got NETDEV_REGISTER\n"); break; case NETDEV_UNREGISTER: printk(KERN_INFO "got NETDEV_UNREGISTER\n"); break; case NETDEV_CHANGEMTU: printk(KERN_INFO "got NETDEV_CHANGEMTU\n"); break; case NETDEV_CHANGEADDR: printk(KERN_INFO "got NETDEV_CHANGEADDR\n"); break; case NETDEV_GOING_DOWN: printk(KERN_INFO "got NETDEV_GOING_DOWN\n"); break; case NETDEV_CHANGENAME: printk(KERN_INFO "got NETDEV_CHANGENAME\n"); break; case NETDEV_FEAT_CHANGE: printk(KERN_INFO "got NETDEV_FEAT_CHANGE\n"); break; case NETDEV_BONDING_FAILOVER: printk(KERN_INFO "got NETDEV_BONDING_FAILOVER\n"); break; case NETDEV_PRE_UP: printk(KERN_INFO "got NETDEV_PRE_UP\n"); break; case NETDEV_PRE_TYPE_CHANGE: printk(KERN_INFO "got NETDEV_PRE_TYPE_CHANGE\n"); break; case NETDEV_POST_TYPE_CHANGE: printk(KERN_INFO "got NETDEV_POST_TYPE_CHANGE\n"); break; case NETDEV_POST_INIT: printk(KERN_INFO "got NETDEV_POST_INIT\n"); break; case NETDEV_UNREGISTER_FINAL: printk(KERN_INFO "got NETDEV_UNREGISTER_FINAL\n"); break; case NETDEV_RELEASE: printk(KERN_INFO "got NETDEV_RELEASE\n"); break; case NETDEV_NOTIFY_PEERS: printk(KERN_INFO "got NETDEV_NOTIFY_PEERS\n"); break; case NETDEV_JOIN: printk(KERN_INFO "got NETDEV_JOIN\n"); break; #ifdef NETDEV_PRECHANGEMTU case NETDEV_CHANGEUPPER: printk(KERN_INFO "got NETDEV_CHANGEUPPER\n"); break; case NETDEV_RESEND_IGMP: printk(KERN_INFO "got NETDEV_RESEND_IGMP\n"); break; case NETDEV_PRECHANGEMTU: printk(KERN_INFO "got NETDEV_PRECHANGEMTU\n"); break; #endif #ifdef NETDEV_CHANGEINFODATA case NETDEV_CHANGEINFODATA: printk(KERN_INFO "got NETDEV_CHANGEINFODATA\n"); break; #endif default: printk(KERN_INFO "got unknown NETDEV event\n"); } } return 0; }
static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct vlan_group *grp; struct vlan_info *vlan_info; int i, flgs; struct net_device *vlandev; struct vlan_dev_priv *vlan; bool last = false; LIST_HEAD(list); if (is_vlan_dev(dev)) __vlan_device_event(dev, event); if ((event == NETDEV_UP) && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { pr_info("adding VLAN 0 to HW filter on device %s\n", dev->name); vlan_vid_add(dev, htons(ETH_P_8021Q), 0); } vlan_info = rtnl_dereference(dev->vlan_info); if (!vlan_info) goto out; grp = &vlan_info->grp; /* It is OK that we do not hold the group lock right now, * as we run under the RTNL lock. */ switch (event) { case NETDEV_CHANGE: /* Propagate real device state to vlan devices */ vlan_group_for_each_dev(grp, i, vlandev) netif_stacked_transfer_operstate(dev, vlandev); break; case NETDEV_CHANGEADDR: /* Adjust unicast filters on underlying device */ vlan_group_for_each_dev(grp, i, vlandev) { flgs = vlandev->flags; if (!(flgs & IFF_UP)) continue; vlan_sync_address(dev, vlandev); } break; case NETDEV_CHANGEMTU: vlan_group_for_each_dev(grp, i, vlandev) { if (vlandev->mtu <= dev->mtu) continue; dev_set_mtu(vlandev, dev->mtu); } break; case NETDEV_FEAT_CHANGE: /* Propagate device features to underlying device */ vlan_group_for_each_dev(grp, i, vlandev) vlan_transfer_features(dev, vlandev); break; case NETDEV_DOWN: if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) vlan_vid_del(dev, htons(ETH_P_8021Q), 0); /* Put all VLANs for this dev in the down state too. */ vlan_group_for_each_dev(grp, i, vlandev) { flgs = vlandev->flags; if (!(flgs & IFF_UP)) continue; vlan = vlan_dev_priv(vlandev); if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) dev_change_flags(vlandev, flgs & ~IFF_UP); netif_stacked_transfer_operstate(dev, vlandev); }