⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vlan.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
			__FUNCTION__, real_dev->name);		goto out_put_dev;	}	if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&	    (real_dev->vlan_rx_register == NULL ||	     real_dev->vlan_rx_kill_vid == NULL)) {		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",			__FUNCTION__, real_dev->name);		goto out_put_dev;	}	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&	    (real_dev->vlan_rx_add_vid == NULL ||	     real_dev->vlan_rx_kill_vid == NULL)) {		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",			__FUNCTION__, real_dev->name);		goto out_put_dev;	}	/* From this point on, all the data structures must remain	 * consistent.	 */	rtnl_lock();	/* The real device must be up and operating in order to	 * assosciate a VLAN device with it.	 */	if (!(real_dev->flags & IFF_UP))		goto out_unlock;	if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) {		/* was already registered. */		printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);		goto out_unlock;	}	/* Gotta set up the fields for the device. */#ifdef VLAN_DEBUG	printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n",	       vlan_name_type);#endif	switch (vlan_name_type) {	case VLAN_NAME_TYPE_RAW_PLUS_VID:		/* name will look like:	 eth1.0005 */		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID);		break;	case VLAN_NAME_TYPE_PLUS_VID_NO_PAD:		/* Put our vlan.VID in the name.		 * Name will look like:	 vlan5		 */		snprintf(name, IFNAMSIZ, "vlan%i", VLAN_ID);		break;	case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD:		/* Put our vlan.VID in the name.		 * Name will look like:	 eth0.5		 */		snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, VLAN_ID);		break;	case VLAN_NAME_TYPE_PLUS_VID:		/* Put our vlan.VID in the name.		 * Name will look like:	 vlan0005		 */	default:		snprintf(name, IFNAMSIZ, "vlan%.4i", VLAN_ID);	};		    	new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,			       vlan_setup);	if (new_dev == NULL)		goto out_unlock;#ifdef VLAN_DEBUG	printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);#endif	/* IFF_BROADCAST|IFF_MULTICAST; ??? */	new_dev->flags = real_dev->flags;	new_dev->flags &= ~IFF_UP;	new_dev->state = real_dev->state & VLAN_LINK_STATE_MASK;	/* need 4 bytes for extra VLAN header info,	 * hope the underlying device can handle it.	 */	new_dev->mtu = real_dev->mtu;	/* TODO: maybe just assign it to be ETHERNET? */	new_dev->type = real_dev->type;	new_dev->hard_header_len = real_dev->hard_header_len;	if (!(real_dev->features & NETIF_F_HW_VLAN_TX)) {		/* Regular ethernet + 4 bytes (18 total). */		new_dev->hard_header_len += VLAN_HLEN;	}	VLAN_MEM_DBG("new_dev->priv malloc, addr: %p  size: %i\n",		     new_dev->priv,		     sizeof(struct vlan_dev_info));	    	memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);	memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);	new_dev->addr_len = real_dev->addr_len;	if (real_dev->features & NETIF_F_HW_VLAN_TX) {		new_dev->hard_header = real_dev->hard_header;		new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;		new_dev->rebuild_header = real_dev->rebuild_header;	} else {		new_dev->hard_header = vlan_dev_hard_header;		new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;		new_dev->rebuild_header = vlan_dev_rebuild_header;	}	new_dev->hard_header_parse = real_dev->hard_header_parse;	VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */	VLAN_DEV_INFO(new_dev)->real_dev = real_dev;	VLAN_DEV_INFO(new_dev)->dent = NULL;	VLAN_DEV_INFO(new_dev)->flags = vlan_default_dev_flags;#ifdef VLAN_DEBUG	printk(VLAN_DBG "About to go find the group for idx: %i\n",	       real_dev->ifindex);#endif	    	if (register_netdevice(new_dev))		goto out_free_newdev;	/* So, got the sucker initialized, now lets place	 * it into our local structure.	 */	grp = __vlan_find_group(real_dev->ifindex);	/* Note, we are running under the RTNL semaphore	 * so it cannot "appear" on us.	 */	if (!grp) { /* need to add a new group */		grp = kmalloc(sizeof(struct vlan_group), GFP_KERNEL);		if (!grp)			goto out_free_unregister;							/* printk(KERN_ALERT "VLAN REGISTER:  Allocated new group.\n"); */		memset(grp, 0, sizeof(struct vlan_group));		grp->real_dev_ifindex = real_dev->ifindex;		hlist_add_head_rcu(&grp->hlist, 				   &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);		if (real_dev->features & NETIF_F_HW_VLAN_RX)			real_dev->vlan_rx_register(real_dev, grp);	}	    	grp->vlan_devices[VLAN_ID] = new_dev;	if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */            	printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",					                 new_dev->name);	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)		real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);	rtnl_unlock();#ifdef VLAN_DEBUG	printk(VLAN_DBG "Allocated new device successfully, returning.\n");#endif	return new_dev;out_free_unregister:	unregister_netdev(new_dev);	goto out_unlock;out_free_newdev:	free_netdev(new_dev);out_unlock:	rtnl_unlock();out_put_dev:	dev_put(real_dev);out_ret_null:	return NULL;}static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr){	struct net_device *dev = ptr;	struct vlan_group *grp = __vlan_find_group(dev->ifindex);	int i, flgs;	struct net_device *vlandev;	if (!grp)		goto out;	/* 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:		/* Propogate real device state to vlan devices */		flgs = dev->state & VLAN_LINK_STATE_MASK;		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {			vlandev = grp->vlan_devices[i];			if (!vlandev)				continue;			if ((vlandev->state & VLAN_LINK_STATE_MASK) != flgs) {				vlandev->state = (vlandev->state &~ VLAN_LINK_STATE_MASK) 					| flgs;				netdev_state_change(vlandev);			}		}		break;	case NETDEV_DOWN:		/* Put all VLANs for this dev in the down state too.  */		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {			vlandev = grp->vlan_devices[i];			if (!vlandev)				continue;			flgs = vlandev->flags;			if (!(flgs & IFF_UP))				continue;			dev_change_flags(vlandev, flgs & ~IFF_UP);		}		break;	case NETDEV_UP:		/* Put all VLANs for this dev in the up state too.  */		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {			vlandev = grp->vlan_devices[i];			if (!vlandev)				continue;							flgs = vlandev->flags;			if (flgs & IFF_UP)				continue;			dev_change_flags(vlandev, flgs | IFF_UP);		}		break;			case NETDEV_UNREGISTER:		/* Delete all VLANs for this dev. */		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {			int ret;			vlandev = grp->vlan_devices[i];			if (!vlandev)				continue;			ret = unregister_vlan_dev(dev,						  VLAN_DEV_INFO(vlandev)->vlan_id);			unregister_netdevice(vlandev);			/* Group was destroyed? */			if (ret == 1)				break;		}		break;	};out:	return NOTIFY_DONE;}/* *	VLAN IOCTL handler. *	o execute requested action or pass command to the device driver *   arg is really a struct vlan_ioctl_args __user *. */static int vlan_ioctl_handler(void __user *arg){	int err = 0;	struct vlan_ioctl_args args;	/* everything here needs root permissions, except aguably the	 * hack ioctls for sending packets.  However, I know _I_ don't	 * want users running that on my network! --BLG	 */	if (!capable(CAP_NET_ADMIN))		return -EPERM;	if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))		return -EFAULT;	/* Null terminate this sucker, just in case. */	args.device1[23] = 0;	args.u.device2[23] = 0;#ifdef VLAN_DEBUG	printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);#endif	switch (args.cmd) {	case SET_VLAN_INGRESS_PRIORITY_CMD:		err = vlan_dev_set_ingress_priority(args.device1,						    args.u.skb_priority,						    args.vlan_qos);		break;	case SET_VLAN_EGRESS_PRIORITY_CMD:		err = vlan_dev_set_egress_priority(args.device1,						   args.u.skb_priority,						   args.vlan_qos);		break;	case SET_VLAN_FLAG_CMD:		err = vlan_dev_set_vlan_flag(args.device1,					     args.u.flag,					     args.vlan_qos);		break;	case SET_VLAN_NAME_TYPE_CMD:		if ((args.u.name_type >= 0) &&		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {			vlan_name_type = args.u.name_type;			err = 0;		} else {			err = -EINVAL;		}		break;		/* TODO:  Figure out how to pass info back...		   case GET_VLAN_INGRESS_PRIORITY_IOCTL:		   err = vlan_dev_get_ingress_priority(args);		   break;		   case GET_VLAN_EGRESS_PRIORITY_IOCTL:		   err = vlan_dev_get_egress_priority(args);		   break;		*/	case ADD_VLAN_CMD:		/* we have been given the name of the Ethernet Device we want to		 * talk to:  args.dev1	 We also have the		 * VLAN ID:  args.u.VID		 */		if (register_vlan_device(args.device1, args.u.VID)) {			err = 0;		} else {			err = -EINVAL;		}		break;	case DEL_VLAN_CMD:		/* Here, the args.dev1 is the actual VLAN we want		 * to get rid of.		 */		err = unregister_vlan_device(args.device1);		break;	default:		/* pass on to underlying device instead?? */		printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",			__FUNCTION__, args.cmd);		return -EINVAL;	};	return err;}MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -