示例#1
0
文件: bearer.c 项目: 3null/linux
/**
 * 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;
}
示例#2
0
/* 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;
}
示例#3
0
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;
}
示例#4
0
文件: macvtap.c 项目: mdamt/linux
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;
}
示例#5
0
文件: raw.c 项目: 020gzh/linux
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;
}
示例#6
0
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;
}
示例#7
0
文件: vrf.c 项目: 513855417/linux
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;
}
示例#8
0
文件: ib_media.c 项目: yuwgit/pmfs
/**
 * 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;
}
示例#9
0
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;
}
示例#10
0
文件: led.c 项目: 03199618/linux
/* 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;
}
示例#11
0
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;
}
示例#12
0
文件: rxe_net.c 项目: avagin/linux
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;
}
示例#13
0
文件: slave.c 项目: andy-shev/linux
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;
}
示例#14
0
文件: offload.c 项目: krzk/linux
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;
}
示例#15
0
文件: core.c 项目: AK101111/linux
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;
}
示例#16
0
/**
 * 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;
}
示例#17
0
文件: br.c 项目: 19Dan01/linux
/*
 * 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;
}
示例#18
0
	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:
示例#19
0
	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;
示例#20
0
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;
}
示例#21
0
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;

}
示例#22
0
文件: vlan.c 项目: BozkurTR/kernel
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);
		}