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

📄 vlan.c

📁 linux 下对8021q协议的配置和实现的增强
💻 C
📖 第 1 页 / 共 2 页
字号:
		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 & ((1<<__LINK_STATE_NOCARRIER) |					     (1<<__LINK_STATE_DORMANT))) |			 (1<<__LINK_STATE_PRESENT); 	/* 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 = 1;#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;	lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key);	new_dev->iflink = real_dev->ifindex;	vlan_transfer_operstate(real_dev, new_dev);	linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */	/* 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 = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);		if (!grp)			goto out_free_unregister;							/* printk(KERN_ALERT "VLAN REGISTER:  Allocated new group.\n"); */		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:		/* Propagate real device state to vlan devices */		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {			vlandev = grp->vlan_devices[i];			if (!vlandev)				continue;			vlan_transfer_operstate(dev, 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;	unsigned short vid = 0;	struct vlan_ioctl_args args;	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:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		err = vlan_dev_set_ingress_priority(args.device1,						    args.u.skb_priority,						    args.vlan_qos);		break;	case SET_VLAN_EGRESS_PRIORITY_CMD:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		err = vlan_dev_set_egress_priority(args.device1,						   args.u.skb_priority,						   args.vlan_qos);		break;	case SET_VLAN_FLAG_CMD:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		err = vlan_dev_set_vlan_flag(args.device1,					     args.u.flag,					     args.vlan_qos);		break;	case SET_VLAN_NAME_TYPE_CMD:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		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;	case ADD_VLAN_CMD:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		/* 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:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		/* Here, the args.dev1 is the actual VLAN we want		 * to get rid of.		 */		err = unregister_vlan_device(args.device1);		break;	case GET_VLAN_INGRESS_PRIORITY_CMD:		/* TODO:  Implement		   err = vlan_dev_get_ingress_priority(args);		   if (copy_to_user((void*)arg, &args,		        sizeof(struct vlan_ioctl_args))) {		        err = -EFAULT;		   }		*/		err = -EINVAL;		break;	case GET_VLAN_EGRESS_PRIORITY_CMD:		/* TODO:  Implement		   err = vlan_dev_get_egress_priority(args.device1, &(args.args);		   if (copy_to_user((void*)arg, &args,		        sizeof(struct vlan_ioctl_args))) {		        err = -EFAULT;		   }		*/		err = -EINVAL;		break;	case GET_VLAN_REALDEV_NAME_CMD:		err = vlan_dev_get_realdev_name(args.device1, args.u.device2);		if (err)			goto out;		if (copy_to_user(arg, &args,				 sizeof(struct vlan_ioctl_args))) {			err = -EFAULT;		}		break;	case GET_VLAN_VID_CMD:		err = vlan_dev_get_vid(args.device1, &vid);		if (err)			goto out;		args.u.VID = vid;		if (copy_to_user(arg, &args,				 sizeof(struct vlan_ioctl_args))) {                      err = -EFAULT;		}		break;	default:		/* pass on to underlying device instead?? */		printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",			__FUNCTION__, args.cmd);		return -EINVAL;	};out:	return err;}MODULE_LICENSE("GPL");MODULE_VERSION(DRV_VERSION);

⌨️ 快捷键说明

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