示例#1
0
文件: br_stp.c 项目: cilynx/dd-wrt
/* called under bridge lock */
static void br_root_selection(struct net_bridge *br)
{
	struct net_bridge_port *p;
	int root_port;

	root_port = 0;

	p = br->port_list;
	while (p != NULL) {
		if (br_should_become_root_port(p, root_port))
			root_port = p->port_no;

		p = p->next;
	}

	br->root_port = root_port;

	if (!root_port) {
		br->designated_root = br->bridge_id;
		br->root_path_cost = 0;
	} else {
		p = br_get_port(br, root_port);
		br->designated_root = p->designated_root;
		br->root_path_cost = p->designated_cost + p->path_cost;
	}
}
示例#2
0
文件: br_if.c 项目: nhanh0/hah
/* called under bridge lock */
static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device *dev)
{
	int i;
	struct net_bridge_port *p;

	p = kmalloc(sizeof(*p), GFP_KERNEL);
	if (p == NULL)
		return p;

	memset(p, 0, sizeof(*p));
	p->br = br;
	p->dev = dev;
	p->path_cost = br_initial_port_cost(dev);
	p->priority = 0x80;

	dev->br_port = p;

	for (i=1;i<255;i++)
		if (br_get_port(br, i) == NULL)
			break;

	if (i == 255) {
		kfree(p);
		return NULL;
	}

	p->port_no = i;
	br_init_port(p);
	p->state = BR_STATE_DISABLED;

	p->next = br->port_list;
	br->port_list = p;

	return p;
}
示例#3
0
文件: br_stp.c 项目: cilynx/dd-wrt
/* called under bridge lock */
static int br_should_become_root_port(struct net_bridge_port *p, int root_port)
{
	struct net_bridge *br;
	struct net_bridge_port *rp;
	int t;

	br = p->br;
	if (p->state == BR_STATE_DISABLED ||
	    br_is_designated_port(p))
		return 0;

	if (memcmp(&br->bridge_id, &p->designated_root, 8) <= 0)
		return 0;

	if (!root_port)
		return 1;

	rp = br_get_port(br, root_port);

	t = memcmp(&p->designated_root, &rp->designated_root, 8);
	if (t < 0)
		return 1;
	else if (t > 0)
		return 0;

	if (p->designated_cost + p->path_cost <
	    rp->designated_cost + rp->path_cost)
		return 1;
	else if (p->designated_cost + p->path_cost >
		 rp->designated_cost + rp->path_cost)
		return 0;

	t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
	if (t < 0)
		return 1;
	else if (t > 0)
		return 0;

	if (p->designated_port < rp->designated_port)
		return 1;
	else if (p->designated_port > rp->designated_port)
		return 0;

	if (p->port_id < rp->port_id)
		return 1;

	return 0;
}
示例#4
0
文件: br_stp.c 项目: cilynx/dd-wrt
/* called under bridge lock */
void br_transmit_config(struct net_bridge_port *p)
{
	struct br_config_bpdu bpdu;
	struct net_bridge *br;

	if (br_timer_is_running(&p->hold_timer)) {
		p->config_pending = 1;
		return;
	}

	br = p->br;

	bpdu.topology_change = br->topology_change;
	bpdu.topology_change_ack = p->topology_change_ack;
	bpdu.root = br->designated_root;
	bpdu.root_path_cost = br->root_path_cost;
	bpdu.bridge_id = br->bridge_id;
	bpdu.port_id = p->port_id;
	if (br_is_root_bridge(br)) 
		bpdu.message_age = 0;
	else {
		struct net_bridge_port *root;

		root = br_get_port(br, br->root_port);
		bpdu.message_age =  br_timer_get_residue(&root->message_age_timer)
			+ MESSAGE_AGE_INCR;
	}
	bpdu.max_age = br->max_age;
	bpdu.hello_time = br->hello_time;
	bpdu.forward_delay = br->forward_delay;

	if (bpdu.message_age < br->max_age) {
		br_send_config_bpdu(p, &bpdu);

		p->topology_change_ack = 0;
		p->config_pending = 0;
		br_timer_set(&p->hold_timer, jiffies);
	}
}
示例#5
0
static int br_ioctl_device(struct net_bridge *br,
			   unsigned int cmd,
			   unsigned long arg0,
			   unsigned long arg1,
			   unsigned long arg2)
{
	if (br == NULL)
		return -EINVAL;

	switch (cmd)
	{
	case BRCTL_ADD_IF:
	case BRCTL_DEL_IF:
	{
		struct net_device *dev;
		int ret;

		dev = dev_get_by_index(arg0);
		if (dev == NULL)
			return -EINVAL;

		if (cmd == BRCTL_ADD_IF)
			ret = br_add_if(br, dev);
		else
			ret = br_del_if(br, dev);

		dev_put(dev);
		return ret;
	}

	case BRCTL_GET_BRIDGE_INFO:
	{
		struct __bridge_info b;

		memset(&b, 0, sizeof(struct __bridge_info));
		memcpy(&b.designated_root, &br->designated_root, 8);
		memcpy(&b.bridge_id, &br->bridge_id, 8);
		b.root_path_cost = br->root_path_cost;
		b.max_age = br->max_age;
		b.hello_time = br->hello_time;
		b.forward_delay = br->forward_delay;
		b.bridge_max_age = br->bridge_max_age;
		b.bridge_hello_time = br->bridge_hello_time;
		b.bridge_forward_delay = br->bridge_forward_delay;
		b.topology_change = br->topology_change;
		b.topology_change_detected = br->topology_change_detected;
		b.root_port = br->root_port;
		b.stp_enabled = br->stp_enabled;
		b.ageing_time = br->ageing_time;
		b.gc_interval = br->gc_interval;
		b.hello_timer_value = br_timer_get_residue(&br->hello_timer);
		b.tcn_timer_value = br_timer_get_residue(&br->tcn_timer);
		b.topology_change_timer_value = br_timer_get_residue(&br->topology_change_timer);
		b.gc_timer_value = br_timer_get_residue(&br->gc_timer);

		if (copy_to_user((void *)arg0, &b, sizeof(b)))
			return -EFAULT;

		return 0;
	}

	case BRCTL_GET_PORT_LIST:
	{
		int i;
		int indices[256];

		for (i=0;i<256;i++)
			indices[i] = 0;

		br_get_port_ifindices(br, indices);
		if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
			return -EFAULT;

		return 0;
	}

	case BRCTL_SET_BRIDGE_FORWARD_DELAY:
		br->bridge_forward_delay = arg0;
		if (br_is_root_bridge(br))
			br->forward_delay = arg0;
		return 0;

	case BRCTL_SET_BRIDGE_HELLO_TIME:
		br->bridge_hello_time = arg0;
		if (br_is_root_bridge(br))
			br->hello_time = arg0;
		return 0;

	case BRCTL_SET_BRIDGE_MAX_AGE:
		br->bridge_max_age = arg0;
		if (br_is_root_bridge(br))
			br->max_age = arg0;
		return 0;

	case BRCTL_SET_AGEING_TIME:
		br->ageing_time = arg0;
		return 0;

	case BRCTL_SET_GC_INTERVAL:
		br->gc_interval = arg0;
		return 0;

	case BRCTL_GET_PORT_INFO:
	{
		struct __port_info p;
		struct net_bridge_port *pt;

		if ((pt = br_get_port(br, arg1)) == NULL)
			return -EINVAL;

		memset(&p, 0, sizeof(struct __port_info));
		memcpy(&p.designated_root, &pt->designated_root, 8);
		memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
		p.port_id = pt->port_id;
		p.designated_port = pt->designated_port;
		p.path_cost = pt->path_cost;
		p.designated_cost = pt->designated_cost;
		p.state = pt->state;
		p.top_change_ack = pt->topology_change_ack;
		p.config_pending = pt->config_pending;
		p.message_age_timer_value = br_timer_get_residue(&pt->message_age_timer);
		p.forward_delay_timer_value = br_timer_get_residue(&pt->forward_delay_timer);
		p.hold_timer_value = br_timer_get_residue(&pt->hold_timer);

		if (copy_to_user((void *)arg0, &p, sizeof(p)))
			return -EFAULT;

		return 0;
	}

	case BRCTL_SET_BRIDGE_STP_STATE:
		br->stp_enabled = arg0?1:0;
		return 0;

	case BRCTL_SET_BRIDGE_PRIORITY:
		br_stp_set_bridge_priority(br, arg0);
		return 0;

	case BRCTL_SET_PORT_PRIORITY:
	{
		struct net_bridge_port *p;

		if ((p = br_get_port(br, arg0)) == NULL)
			return -EINVAL;
		br_stp_set_port_priority(p, arg1);
		return 0;
	}

	case BRCTL_SET_PATH_COST:
	{
		struct net_bridge_port *p;

		if ((p = br_get_port(br, arg0)) == NULL)
			return -EINVAL;
		br_stp_set_path_cost(p, arg1);
		return 0;
	}

	case BRCTL_GET_FDB_ENTRIES:
#ifdef CONFIG_RTK_GUEST_ZONE
		return br_fdb_get_entries(br, (void *)arg0, arg1, arg2, 0);
#else		
		return br_fdb_get_entries(br, (void *)arg0, arg1, arg2);
#endif

#ifdef MULTICAST_FILTER
	case 101:
		printk(KERN_INFO "%s: clear port list of multicast filter\n", br->dev.name);
		br->fltr_portlist_num = 0;
		return 0;

	case 102:
	{
		int i;

		if (br->fltr_portlist_num == MLCST_FLTR_ENTRY) {
			printk(KERN_INFO "%s: set port num of multicast filter, entries full!\n", br->dev.name);
			return 0;
		}
		for (i=0; i<br->fltr_portlist_num; i++)
			if (br->fltr_portlist[i] == (unsigned short)arg0)
				return 0;
		printk(KERN_INFO "%s: set port num [%d] of multicast filter\n", br->dev.name, (unsigned short)arg0);
		br->fltr_portlist[br->fltr_portlist_num] = (unsigned short)arg0;
		br->fltr_portlist_num++;
		return 0;
	}
#endif

#ifdef MULTICAST_BWCTRL
	case 103:
	{
		struct net_bridge_port *p;

		if ((p = br_get_port(br, arg0)) == NULL)
			return -EINVAL;
		if (arg1 == 0) {
			p->bandwidth = 0;
			printk(KERN_INFO "%s: port %i(%s) multicast bandwidth all\n",
			       p->br->dev.name, p->port_no, p->dev->name);
		}
		else {
			p->bandwidth = arg1 * 1000 / 8;
			printk(KERN_INFO "%s: port %i(%s) multicast bandwidth %dkbps\n",
			       p->br->dev.name, p->port_no, p->dev->name, (unsigned int)arg1);
		}
		return 0;
	}
#endif

#ifdef RTL_BRIDGE_MAC_CLONE
	case 104:	// MAC Clone enable/disable
	{
		struct net_bridge_port *p;
		unsigned char nullmac[] = {0, 0, 0, 0, 0, 0};

		if ((p = br_get_port(br, arg0)) == NULL)
			return -EINVAL;

		if ((p->macCloneTargetPort = br_get_port(br, arg1)) == NULL)
			return -EINVAL;

		p->enable_mac_clone = 1;
		p->mac_clone_completed = 0;

		if (clone_pair.port != p->macCloneTargetPort)
		{
			TRACE("clone_pair.port [%x] != p->macCloneTargetPort [%x], don't clone\n", (unsigned int)clone_pair.port, (unsigned int)p->macCloneTargetPort);
			clone_pair.port = p->macCloneTargetPort;
			TRACE("clone_pair.port = %x\n", (unsigned int)clone_pair.port);
			memset(clone_pair.mac.addr, 0, ETH_ALEN);
		}
		else
		{
			if(!memcmp(clone_pair.mac.addr, nullmac, ETH_ALEN))
			{
				TRACE("clone_pair.mac.addr == nullmac, don't clone\n");
			}
			else
			{
				TRACE("Clone MAC from previous one\n");
				br_mac_clone(p->macCloneTargetPort, clone_pair.mac.addr);
			}
		}

		TRACE("device %s, Enable MAC Clone to device %s\n", p->dev->name, p->macCloneTargetPort->dev->name);
		return 0;
	}
#endif

#ifdef CONFIG_RTK_GUEST_ZONE
	case 105:	// set zone
	{
		struct net_bridge_port *p;
		if ((p = br_get_port(br, arg0)) == NULL)
			return -EINVAL;
		p->is_guest_zone = arg1;
#ifdef DEBUG_GUEST_ZONE
		panic_printk("set device=%s is_guest_zone=%d\n", p->dev->name, p->is_guest_zone);
#endif
		return 0;
	}

	case 106:	// set zone isolation
		br->is_zone_isolated = arg0;
#ifdef DEBUG_GUEST_ZONE
		panic_printk("set zone isolation=%d\n",	br->is_zone_isolated);		
#endif
		return 0;
		
	case 107:	// set guest isolation
		br->is_guest_isolated = arg0;
#ifdef DEBUG_GUEST_ZONE
		panic_printk("set guest isolation=%d\n",	br->is_guest_isolated);		
#endif		
		return 0;

	case 108:	// set lock mac list
	{
		unsigned char mac[6];
		int i;
		if (copy_from_user(mac, (unsigned long*)arg0, 6))
			return -EFAULT;
#ifdef DEBUG_GUEST_ZONE
		panic_printk("set lock client list=%02x:%02x:%02x:%02x:%02x:%02x\n", 
							mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);	
#endif
		if (!memcmp(mac, "\x0\x0\x0\x0\x0\x0", 6)) {  // reset list
#ifdef DEBUG_GUEST_ZONE		
			panic_printk("reset lock list!\n");
#endif
			br->lock_client_num = 0;
			return 0;		
		}
		for (i=0; i<br->lock_client_num; i++) {
			if (!memcmp(mac, br->lock_client_list[i], 6)) {
#ifdef DEBUG_GUEST_ZONE				
				panic_printk("duplicated lock entry!\n");
#endif
				return 0;
			}			
		}
		if (br->lock_client_num >= MAX_LOCK_CLIENT) {
#ifdef DEBUG_GUEST_ZONE			
			panic_printk("Add failed, lock list table full!\n");
#endif
			return 0;
		}
		memcpy(br->lock_client_list[br->lock_client_num], mac, 6);
		br->lock_client_num++;
		return 0;
	}		
	case 109:	// show guest info
	{
		int i;
		panic_printk("\n");
		panic_printk("  zone isolation: %d\n", br->is_zone_isolated);
		panic_printk("  guest isolation: %d\n", br->is_guest_isolated);
		i = 1;
		while (1) {
			struct net_bridge_port *p;
			if ((p = br_get_port(br, i++)) == NULL)
				break;
			panic_printk("  %s: %s\n", p->dev->name, (p->is_guest_zone ? "guest" : "host"));			
		}		
		panic_printk("  locked client no: %d\n", br->lock_client_num);
		for (i=0; i< br->lock_client_num; i++) {
			unsigned char *mac;
			mac = br->lock_client_list[i];
			panic_printk("    mac=%02x:%02x:%02x:%02x:%02x:%02x\n", 
							mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);	
		}			
		panic_printk("\n");		
		return 0;
	}	

	case 110:
		return br_fdb_get_entries(br, (void *)arg0, arg1, arg2, 1);	
#endif	// CONFIG_RTK_GUEST_ZONE
	}

	return -EOPNOTSUPP;
}
示例#6
0
文件: br_stp.c 项目: cilynx/dd-wrt
/* called under bridge lock */
void br_transmit_tcn(struct net_bridge *br)
{
	br_send_tcn_bpdu(br_get_port(br, br->root_port));
}
示例#7
0
static int br_ioctl_device(struct net_bridge *br,
			   unsigned int cmd,
			   unsigned long arg0,
			   unsigned long arg1,
			   unsigned long arg2)
{
	if (br == NULL)
		return -EINVAL;

	switch (cmd)
	{
	case BRCTL_ADD_IF:
	case BRCTL_DEL_IF:
	{
		struct net_device *dev;
		int ret;

		dev = dev_get_by_index(arg0);
		if (dev == NULL)
			return -EINVAL;

		if (cmd == BRCTL_ADD_IF)
			ret = br_add_if(br, dev);
		else
			ret = br_del_if(br, dev);

		dev_put(dev);
		return ret;
	}

	case BRCTL_GET_BRIDGE_INFO:
	{
		struct __bridge_info b;

		memset(&b, 0, sizeof(struct __bridge_info));
		memcpy(&b.designated_root, &br->designated_root, 8);
		memcpy(&b.bridge_id, &br->bridge_id, 8);
		b.root_path_cost = br->root_path_cost;
		b.max_age = br->max_age;
		b.hello_time = br->hello_time;
		b.forward_delay = br->forward_delay;
		b.bridge_max_age = br->bridge_max_age;
		b.bridge_hello_time = br->bridge_hello_time;
		b.bridge_forward_delay = br->bridge_forward_delay;
		b.topology_change = br->topology_change;
		b.topology_change_detected = br->topology_change_detected;
		b.root_port = br->root_port;
		b.stp_enabled = br->stp_enabled;
		b.ageing_time = br->ageing_time;
		b.gc_interval = br->gc_interval;
		b.hello_timer_value = br_timer_get_residue(&br->hello_timer);
		b.tcn_timer_value = br_timer_get_residue(&br->tcn_timer);
		b.topology_change_timer_value = br_timer_get_residue(&br->topology_change_timer);
		b.gc_timer_value = br_timer_get_residue(&br->gc_timer);

		if (copy_to_user((void *)arg0, &b, sizeof(b)))
			return -EFAULT;

		return 0;
	}

	case BRCTL_GET_PORT_LIST:
	{
		int i;
		int indices[256];

		for (i=0;i<256;i++)
			indices[i] = 0;

		br_get_port_ifindices(br, indices);
		if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
			return -EFAULT;

		return 0;
	}

	case BRCTL_SET_BRIDGE_FORWARD_DELAY:
		br->bridge_forward_delay = arg0;
		if (br_is_root_bridge(br))
			br->forward_delay = arg0;
		return 0;

	case BRCTL_SET_BRIDGE_HELLO_TIME:
		br->bridge_hello_time = arg0;
		if (br_is_root_bridge(br))
			br->hello_time = arg0;
		return 0;

	case BRCTL_SET_BRIDGE_MAX_AGE:
		br->bridge_max_age = arg0;
		if (br_is_root_bridge(br))
			br->max_age = arg0;
		return 0;

	case BRCTL_SET_AGEING_TIME:
		br->ageing_time = arg0;
		return 0;

	case BRCTL_SET_GC_INTERVAL:
		br->gc_interval = arg0;
		return 0;

	case BRCTL_GET_PORT_INFO:
	{
		struct __port_info p;
		struct net_bridge_port *pt;

		if ((pt = br_get_port(br, arg1)) == NULL)
			return -EINVAL;

		memset(&p, 0, sizeof(struct __port_info));
		memcpy(&p.designated_root, &pt->designated_root, 8);
		memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
		p.port_id = pt->port_id;
		p.designated_port = pt->designated_port;
		p.path_cost = pt->path_cost;
		p.designated_cost = pt->designated_cost;
		p.state = pt->state;
		p.top_change_ack = pt->topology_change_ack;
		p.config_pending = pt->config_pending;
		p.message_age_timer_value = br_timer_get_residue(&pt->message_age_timer);
		p.forward_delay_timer_value = br_timer_get_residue(&pt->forward_delay_timer);
		p.hold_timer_value = br_timer_get_residue(&pt->hold_timer);

		if (copy_to_user((void *)arg0, &p, sizeof(p)))
			return -EFAULT;

		return 0;
	}

	case BRCTL_SET_BRIDGE_STP_STATE:
#ifdef CONFIG_BRIDGESTEP
		br->stp_enabled = arg0?1:0;
		return 0;
#else
		br->stp_enabled = 0;
		return 0;
#endif

	case BRCTL_SET_BRIDGE_PRIORITY:
		br_stp_set_bridge_priority(br, arg0);
		return 0;

	case BRCTL_SET_PORT_PRIORITY:
	{
		struct net_bridge_port *p;

		if ((p = br_get_port(br, arg0)) == NULL)
			return -EINVAL;
		br_stp_set_port_priority(p, arg1);
		return 0;
	}

	case BRCTL_SET_PATH_COST:
	{
		struct net_bridge_port *p;

		if ((p = br_get_port(br, arg0)) == NULL)
			return -EINVAL;
		br_stp_set_path_cost(p, arg1);
		return 0;
	}

	case BRCTL_GET_FDB_ENTRIES:
		return br_fdb_get_entries(br, (void *)arg0, arg1, arg2);

#ifdef CONFIG_EMUSWITCH_MODULE
#define EMUSWITCH_DEBUG(X) printk("EMUSWITCH: " X)
	case BRCTL_SET_PORT_EMUSWITCH: {
		printk("Emuswitch set port\n");
		struct net_bridge_port *p;
		struct __emuswitch_info info;

		if ((p = br_get_port(br, arg0)) == NULL) {
			printk("Emuswitch Could not get port %d\n", arg0);
			return -EINVAL;
		}
		if(copy_from_user(&info, (void*)arg1, sizeof(info))) {
			EMUSWITCH_DEBUG("Could not copy in info\n");
			return -EFAULT;
		}
		return br_port_set_emuswitch(p, &info);
	}
	case BRCTL_GET_PORT_EMUSWITCH: {
		printk("Emuswitch get port\n");
		struct net_bridge_port *p;
		struct __emuswitch_info info;
		if(copy_from_user(&info, (void*)arg1, sizeof(info))) {
			EMUSWITCH_DEBUG("Could not copy in info\n");
			return -EFAULT;
		}

		if ((p = br_get_port(br, arg0)) == NULL) {
			printk("EMUSWITCH: Could not get port %d\n", arg0);
			return -EINVAL;
		}
		br_port_get_emuswitch(p, &info);
		if(copy_to_user((void*)arg1, &info, sizeof(info))) {
			EMUSWITCH_DEBUG("Could not copy out info\n");
			return -EFAULT;
		}
		return 0;
	}
#undef EMUSWITCH_DEBUG
#endif // CONFIG_EMUSWITCH_MODULE
	}

	return -EOPNOTSUPP;
}