コード例 #1
0
ファイル: br_if.c プロジェクト: nhanh0/hah
int br_add_if(struct net_bridge *br, struct net_device *dev)
{
	struct net_bridge_port *p;

	if (dev->br_port != NULL)
		return -EBUSY;

	if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
		return -EINVAL;

	dev_hold(dev);
	write_lock_bh(&br->lock);
	if ((p = new_nbp(br, dev)) == NULL) {
		write_unlock_bh(&br->lock);
		dev_put(dev);
		return -EXFULL;
	}

	dev_set_promiscuity(dev, 1);

	br_stp_recalculate_bridge_id(br);
	br_fdb_insert(br, p, dev->dev_addr, 1);
	if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP))
		br_stp_enable_port(p);
	write_unlock_bh(&br->lock);

	return 0;
}
コード例 #2
0
/*
 * 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 = ptr;
	struct net_bridge_port *p = dev->br_port;
	struct net_bridge *br;

	/* not a port of a bridge */
	if (p == NULL)
		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);
		br_ifinfo_notify(RTM_NEWLINK, p);
		br_stp_recalculate_bridge_id(br);
		spin_unlock_bh(&br->lock);
		break;

	case NETDEV_CHANGE:
		br_port_carrier_check(p);
		break;

	case NETDEV_FEAT_CHANGE:
		spin_lock_bh(&br->lock);
		if (netif_running(br->dev))
			br_features_recompute(br);
		spin_unlock_bh(&br->lock);
		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:
		spin_lock_bh(&br->lock);
		if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP))
			br_stp_enable_port(p);
		spin_unlock_bh(&br->lock);
		break;

	case NETDEV_UNREGISTER:
		br_del_if(br, dev);
		break;
	}

	return NOTIFY_DONE;
}
コード例 #3
0
ファイル: br_notify.c プロジェクト: iwangv/edimax-br-6528n
static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{
	struct net_device *dev;
	struct net_bridge_port *p;

	dev = ptr;
	p = dev->br_port;

	if (p == NULL)
		return NOTIFY_DONE;

	switch (event)
	{
	case NETDEV_CHANGEADDR:
		read_lock(&p->br->lock);
		br_fdb_changeaddr(p, dev->dev_addr);
		br_stp_recalculate_bridge_id(p->br);
		read_unlock(&p->br->lock);
		break;

	case NETDEV_GOING_DOWN:
		/* extend the protocol to send some kind of notification? */
		break;

	case NETDEV_DOWN:
		if (p->br->dev.flags & IFF_UP) {
			read_lock(&p->br->lock);
#if 0
#ifdef STP_DISABLE_ETH
			//Chris: stp+mesh
			p->disable_by_mesh = 0;
#endif
#endif 
			br_stp_disable_port(dev->br_port);
			read_unlock(&p->br->lock);
		}
		break;

	case NETDEV_UP:
		if (p->br->dev.flags & IFF_UP) {
			read_lock(&p->br->lock);
			br_stp_enable_port(dev->br_port);
			read_unlock(&p->br->lock);
		}
		break;

	case NETDEV_UNREGISTER:
		br_del_if(dev->br_port->br, dev);
		break;
	}

	return NOTIFY_DONE;
}
コード例 #4
0
/* called under bridge lock */
void br_stp_enable_bridge(struct net_bridge *br)
{
	struct net_bridge_port *p;
	struct timer_list *timer = &br->tick;

	init_timer(timer);
	timer->data = (unsigned long) br;
	timer->function = br_tick;
	timer->expires = jiffies + 1;
	add_timer(timer);

	br_timer_set(&br->hello_timer, jiffies);
	br_config_bpdu_generation(br);

	p = br->port_list;
	while (p != NULL) {
		if (p->dev->flags & IFF_UP)
			br_stp_enable_port(p);

		p = p->next;
	}

	br_timer_set(&br->gc_timer, jiffies);
}
コード例 #5
0
int br_add_if(struct net_bridge *br, struct net_device *dev)
{
	struct net_bridge_port *p;

	if (dev->br_port != NULL)
		return -EBUSY;

#if 0
	if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
		return -EINVAL;
#endif

	if (dev->hard_start_xmit == br_dev_xmit)
		return -ELOOP;

	if (!is_valid_ether_addr(dev->dev_addr))
		return -EADDRNOTAVAIL;

	dev_hold(dev);
	write_lock_bh(&br->lock);
	if ((p = new_nbp(br, dev)) == NULL) {
		write_unlock_bh(&br->lock);
		dev_put(dev);
		return -EXFULL;
	}

	dev_set_promiscuity(dev, 1);

	br_stp_recalculate_bridge_id(br);
	br_fdb_insert(br, p, dev->dev_addr, 1);
	if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP))
		br_stp_enable_port(p);
	write_unlock_bh(&br->lock);

	return 0;
}
コード例 #6
0
static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{
    struct net_device *dev = ptr;
    struct net_bridge_port *p = dev->br_port;
    struct net_bridge *br;
    int err;

    /* not a port of a bridge */
    if (p == NULL)
        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);
        br_stp_recalculate_bridge_id(br);
        spin_unlock_bh(&br->lock);
        break;

    case NETDEV_CHANGE:
        br_port_carrier_check(p);
        break;

    case NETDEV_FEAT_CHANGE:
        spin_lock_bh(&br->lock);
        if (netif_running(br->dev))
            br_features_recompute(br);
        spin_unlock_bh(&br->lock);
        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_carrier_ok(dev) && (br->dev->flags & IFF_UP)) {
            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;
    }

    /* 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;
}
コード例 #7
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;
}
コード例 #8
0
/*
 * 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 = ptr;
	struct net_bridge_port *p = dev->br_port;
	struct net_bridge *br;

	/* not a port of a bridge */
	if (p == NULL)
		return NOTIFY_DONE;

	br = p->br;

	spin_lock_bh(&br->lock);
	switch (event) {
	case NETDEV_CHANGEMTU:
		dev_set_mtu(br->dev, br_min_mtu(br));
		break;

	case NETDEV_CHANGEADDR:
		br_fdb_changeaddr(p, dev->dev_addr);
		br_stp_recalculate_bridge_id(br);
		break;

	case NETDEV_CHANGE:	/* device is up but carrier changed */
		if (!(br->dev->flags & IFF_UP))
			break;

		if (netif_carrier_ok(dev)) {
			if (p->state == BR_STATE_DISABLED)
				br_stp_enable_port(p);
		} else {
			if (p->state != BR_STATE_DISABLED)
				br_stp_disable_port(p);
		}
		break;

	case NETDEV_FEAT_CHANGE:
		if (br->dev->flags & IFF_UP) 
			br_features_recompute(br);

		/* could do recursive feature change notification
		 * but who would care?? 
		 */
		break;

	case NETDEV_DOWN:
		if (br->dev->flags & IFF_UP)
			br_stp_disable_port(p);
		break;

	case NETDEV_UP:
		if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) 
			br_stp_enable_port(p);
		break;

	case NETDEV_UNREGISTER:
		spin_unlock_bh(&br->lock);
		br_del_if(br, dev);
		goto done;
	} 
	spin_unlock_bh(&br->lock);

 done:
	return NOTIFY_DONE;
}